From e91825634b381c512b5ca7ee553f1df681a8c5d6 Mon Sep 17 00:00:00 2001
From: Thoriq Firdaus <2067467+tfirdaus@users.noreply.github.com>
Date: Tue, 29 Jul 2025 08:15:38 +0700
Subject: [PATCH 1/3] Add `lt` command
---
app/Commands/LessThanCommand.php | 71 ++++++++++++++++++++++++++
app/Exceptions/InvalidArgumentType.php | 15 ++++--
2 files changed, 83 insertions(+), 3 deletions(-)
create mode 100644 app/Commands/LessThanCommand.php
diff --git a/app/Commands/LessThanCommand.php b/app/Commands/LessThanCommand.php
new file mode 100644
index 0000000..e52335a
--- /dev/null
+++ b/app/Commands/LessThanCommand.php
@@ -0,0 +1,71 @@
+setName('lt');
+ $this->setDescription('Compare if a version is less than another');
+ $this->addArgument('version-a', InputArgument::REQUIRED, 'First version to compare');
+ $this->addArgument('version-b', InputArgument::REQUIRED, 'Second version to compare against the first');
+ $this->setHelp(<<<'HELP'
+ This command compares two versions and checks if the first version is less than the second.
+
+ Usage:
+ version lt 0.9.0 1.0.0
+ version lt 2.1.0 2.1.0
+ HELP);
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $style = new SymfonyStyle($input, $output);
+ $versionA = $input->getArgument('version-a');
+ $versionB = $input->getArgument('version-b');
+
+ try {
+ if (! is_string($versionA) || ! is_string($versionB)) {
+ throw new InvalidArgumentType($versionA, $versionB);
+ }
+
+ /** @var Version $a */
+ $a = Version::fromString($versionA);
+
+ /** @var Version $b */
+ $b = Version::fromString($versionB);
+
+ if ($a->isLessThan($b)) {
+ $style->success(sprintf("Version '%s' is less than '%s'.", $a, $b));
+
+ return Command::SUCCESS;
+ }
+
+ $style->error(sprintf("Version '%s' is not less than '%s'.", $a, $b));
+
+ return Command::FAILURE;
+ } catch (Throwable $th) {
+ $style->error($th->getMessage());
+
+ return Command::FAILURE;
+ }
+ }
+}
diff --git a/app/Exceptions/InvalidArgumentType.php b/app/Exceptions/InvalidArgumentType.php
index 0132414..ee97d17 100644
--- a/app/Exceptions/InvalidArgumentType.php
+++ b/app/Exceptions/InvalidArgumentType.php
@@ -6,14 +6,23 @@
use InvalidArgumentException;
-use function gettype;
+use function array_map;
+use function implode;
use function sprintf;
class InvalidArgumentType extends InvalidArgumentException
{
/** @param mixed $value */
- public function __construct($value)
+ public function __construct(...$value)
{
- parent::__construct(sprintf("Invalid type of value. Expected '%s', '%s' given", 'string', gettype($value)));
+ $types = array_map('gettype', $value);
+
+ parent::__construct(
+ sprintf(
+ "Invalid type of value. Expected '%s', '%s' given",
+ 'string',
+ implode(', ', $types),
+ ),
+ );
}
}
From bf6dd6a68157aa5f6f6e6aae4374357cfb4635b3 Mon Sep 17 00:00:00 2001
From: Thoriq Firdaus <2067467+tfirdaus@users.noreply.github.com>
Date: Tue, 29 Jul 2025 08:18:25 +0700
Subject: [PATCH 2/3] Add assertion
---
app/Commands/GreaterThanCommand.php | 13 +++----------
app/Commands/LessThanCommand.php | 9 +++------
app/Commands/ValidateCommand.php | 14 +++++---------
app/Exceptions/InvalidArgumentType.php | 15 +++------------
composer.json | 2 ++
5 files changed, 16 insertions(+), 37 deletions(-)
diff --git a/app/Commands/GreaterThanCommand.php b/app/Commands/GreaterThanCommand.php
index 70a6280..1da27eb 100644
--- a/app/Commands/GreaterThanCommand.php
+++ b/app/Commands/GreaterThanCommand.php
@@ -4,16 +4,15 @@
namespace Syntatis\Version\CLI\Commands;
+use Assert\Assertion;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
-use Syntatis\Version\CLI\Exceptions\InvalidArgumentType;
use Throwable;
use Version\Version;
-use function is_string;
use function sprintf;
final class GreaterThanCommand extends Command
@@ -43,17 +42,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$versionB = $input->getArgument('version-b');
try {
- if (! is_string($versionA)) {
- throw new InvalidArgumentType($versionA);
- }
-
- if (! is_string($versionB)) {
- throw new InvalidArgumentType($versionB);
- }
+ Assertion::string($versionA);
+ Assertion::string($versionB);
/** @var Version $a */
$a = Version::fromString($versionA);
-
/** @var Version $b */
$b = Version::fromString($versionB);
diff --git a/app/Commands/LessThanCommand.php b/app/Commands/LessThanCommand.php
index e52335a..8b591ee 100644
--- a/app/Commands/LessThanCommand.php
+++ b/app/Commands/LessThanCommand.php
@@ -4,16 +4,15 @@
namespace Syntatis\Version\CLI\Commands;
+use Assert\Assertion;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
-use Syntatis\Version\CLI\Exceptions\InvalidArgumentType;
use Throwable;
use Version\Version;
-use function is_string;
use function sprintf;
final class LessThanCommand extends Command
@@ -43,13 +42,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$versionB = $input->getArgument('version-b');
try {
- if (! is_string($versionA) || ! is_string($versionB)) {
- throw new InvalidArgumentType($versionA, $versionB);
- }
+ Assertion::string($versionA);
+ Assertion::string($versionB);
/** @var Version $a */
$a = Version::fromString($versionA);
-
/** @var Version $b */
$b = Version::fromString($versionB);
diff --git a/app/Commands/ValidateCommand.php b/app/Commands/ValidateCommand.php
index 7d62b47..74f44bb 100644
--- a/app/Commands/ValidateCommand.php
+++ b/app/Commands/ValidateCommand.php
@@ -4,16 +4,15 @@
namespace Syntatis\Version\CLI\Commands;
+use Assert\Assertion;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
-use Syntatis\Version\CLI\Exceptions\InvalidArgumentType;
use Throwable;
use Version\Version;
-use function is_string;
use function sprintf;
final class ValidateCommand extends Command
@@ -36,15 +35,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$version = $input->getArgument('version');
try {
- if (is_string($version)) {
- Version::fromString($version);
+ Assertion::string($version);
+ Version::fromString($version);
- $style->success(sprintf("Version string '%s' is valid and can be parsed", $version));
+ $style->success(sprintf("Version string '%s' is valid and can be parsed", $version));
- return Command::SUCCESS;
- }
-
- throw new InvalidArgumentType($version);
+ return Command::SUCCESS;
} catch (Throwable $th) {
$style->error($th->getMessage());
diff --git a/app/Exceptions/InvalidArgumentType.php b/app/Exceptions/InvalidArgumentType.php
index ee97d17..0132414 100644
--- a/app/Exceptions/InvalidArgumentType.php
+++ b/app/Exceptions/InvalidArgumentType.php
@@ -6,23 +6,14 @@
use InvalidArgumentException;
-use function array_map;
-use function implode;
+use function gettype;
use function sprintf;
class InvalidArgumentType extends InvalidArgumentException
{
/** @param mixed $value */
- public function __construct(...$value)
+ public function __construct($value)
{
- $types = array_map('gettype', $value);
-
- parent::__construct(
- sprintf(
- "Invalid type of value. Expected '%s', '%s' given",
- 'string',
- implode(', ', $types),
- ),
- );
+ parent::__construct(sprintf("Invalid type of value. Expected '%s', '%s' given", 'string', gettype($value)));
}
}
diff --git a/composer.json b/composer.json
index 38f57f5..f0137d7 100644
--- a/composer.json
+++ b/composer.json
@@ -28,6 +28,7 @@
},
"require": {
"php": "^7.4 || ^8.0",
+ "beberlei/assert": "^3.3",
"nikolaposa/version": "^4.1.1",
"symfony/console": "^5.4 || ^6.0 || ^7.0"
},
@@ -37,6 +38,7 @@
"phpcompatibility/php-compatibility": "^9.3",
"phpstan/extension-installer": "^1.4",
"phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-beberlei-assert": "^2.0",
"phpstan/phpstan-deprecation-rules": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
From 58d07eb9da27660b289725d39f024b111e54de56 Mon Sep 17 00:00:00 2001
From: Thoriq Firdaus <2067467+tfirdaus@users.noreply.github.com>
Date: Tue, 29 Jul 2025 08:27:12 +0700
Subject: [PATCH 3/3] Load `lt` command, and add tests
---
app/Commander.php | 2 +
.../phpunit/Commands/LessThanCommandTest.php | 45 +++++++++++++++++++
2 files changed, 47 insertions(+)
create mode 100644 tests/phpunit/Commands/LessThanCommandTest.php
diff --git a/app/Commander.php b/app/Commander.php
index 6ba4b4d..511c0e9 100644
--- a/app/Commander.php
+++ b/app/Commander.php
@@ -8,6 +8,7 @@
use Symfony\Component\Console\Command\Command;
use Syntatis\Version\CLI\Commands\GreaterThanCommand;
use Syntatis\Version\CLI\Commands\IncrementCommand;
+use Syntatis\Version\CLI\Commands\LessThanCommand;
use Syntatis\Version\CLI\Commands\ValidateCommand;
final class Commander extends Application
@@ -31,6 +32,7 @@ private function getCommands(): array
new IncrementCommand(),
new ValidateCommand(),
new GreaterThanCommand(),
+ new LessThanCommand(),
];
}
}
diff --git a/tests/phpunit/Commands/LessThanCommandTest.php b/tests/phpunit/Commands/LessThanCommandTest.php
new file mode 100644
index 0000000..c125bb7
--- /dev/null
+++ b/tests/phpunit/Commands/LessThanCommandTest.php
@@ -0,0 +1,45 @@
+commander = new Commander();
+ $this->tester = new CommandTester($this->commander->get('lt'));
+ }
+
+ /** @dataProvider dataComparison */
+ public function testComparison(string $versionA, string $versionB, string $expect): void
+ {
+ $this->tester->execute(['version-a' => $versionA, 'version-b' => $versionB]);
+
+ self::assertStringContainsString(
+ $expect,
+ $this->tester->getDisplay(),
+ );
+ }
+
+ public static function dataComparison(): iterable
+ {
+ yield ['1.0.0', '2.0.0', sprintf("[OK] Version '%s' is less than '%s'.", '1.0.0', '2.0.0')];
+ yield ['2.0.0', '1.0.0', sprintf("[ERROR] Version '%s' is not less than '%s'.", '2.0.0', '1.0.0')];
+ yield ['1.0.0', '1.0.0', sprintf("[ERROR] Version '%s' is not less than '%s'.", '1.0.0', '1.0.0')];
+ yield ['1.0.0-alpha.1', '1.0.0-alpha.2', sprintf("[OK] Version '%s' is less than '%s'.", '1.0.0-alpha.1', '1.0.0-alpha.2')];
+ yield ['1.0.0-alpha.2', '1.0.0-alpha.1', sprintf("[ERROR] Version '%s' is not less than '%s'.", '1.0.0-alpha.2', '1.0.0-alpha.1')];
+ }
+}