diff --git a/README.md b/README.md index 88632a0bf..755a00e6a 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,11 @@ These steps are provided for development purposes only. ``` 3. Start the web server: ```bash - symfony serve + symfony serve -d ``` 4. Start MySQL & Redis: ```bash - docker-compose up -d # or somehow run MySQL & Redis on localhost without docker + docker compose up -d # or somehow run MySQL & Redis on localhost without docker ``` 5. Create 2 databases: - `packagist` - for the web app diff --git a/src/Entity/Package.php b/src/Entity/Package.php index a01255b4b..ffa06024b 100644 --- a/src/Entity/Package.php +++ b/src/Entity/Package.php @@ -687,6 +687,21 @@ public function getType(): string|null return $this->type; } + public function getInstallCommand(Version $version = null): string + { + $command = 'create-project'; + + if ('project' !== $this->getType()) { + $command = 'require'; + + if (null !== $version && $version->hasDevTag()) { + $command .= ' --dev'; + } + } + + return sprintf('composer %s %s', $command, $this->getName()); + } + public function setRemoteId(string|null $remoteId): void { $this->remoteId = $remoteId; diff --git a/src/Entity/Tag.php b/src/Entity/Tag.php index a090d98f3..1b0d4ed5e 100644 --- a/src/Entity/Tag.php +++ b/src/Entity/Tag.php @@ -86,6 +86,12 @@ public function getName(): string return $this->name; } + public function isDev(): bool + { + // see Composer\Command\RequireCommand + return in_array(strtolower($this->name), ['dev', 'testing', 'static analysis'], true); + } + public function addVersions(Version $versions): void { $this->versions[] = $versions; diff --git a/src/Entity/Version.php b/src/Entity/Version.php index c76d86624..ccd59acb8 100644 --- a/src/Entity/Version.php +++ b/src/Entity/Version.php @@ -635,6 +635,17 @@ public function getTags(): Collection return $this->tags; } + public function hasDevTag(): bool + { + foreach ($this->getTags() as $tag) { + if ($tag->isDev()) { + return true; + } + } + + return false; + } + public function setUpdatedAt(DateTimeInterface $updatedAt): void { $this->updatedAt = $updatedAt; diff --git a/templates/package/view_package.html.twig b/templates/package/view_package.html.twig index f7aea720c..5a740392f 100644 --- a/templates/package/view_package.html.twig +++ b/templates/package/view_package.html.twig @@ -46,7 +46,7 @@
-

+

{% if not package.isAutoUpdated() and is_granted('update', package) %} {% if "github.com" in package.repository %} diff --git a/tests/Entity/PackageTest.php b/tests/Entity/PackageTest.php index ba4a06ba7..ee50453b5 100644 --- a/tests/Entity/PackageTest.php +++ b/tests/Entity/PackageTest.php @@ -13,6 +13,9 @@ namespace App\Tests\Entity; use App\Entity\Package; +use App\Entity\Tag; +use App\Entity\Version; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class PackageTest extends TestCase @@ -28,4 +31,34 @@ public function testWasUpdatedInTheLast24Hours(): void $package->setUpdatedAt(new \DateTime('now')); $this->assertTrue($package->wasUpdatedInTheLast24Hours()); } + + #[DataProvider('providePackageScenarios')] + public function testInstallCommand(string $type, string $tag, string $expected): void + { + $version = new Version(); + $version->addTag(new Tag($tag)); + + $package = new Package(); + $package->setName('vendor/name'); + $package->setType($type); + + self::assertSame($expected, $package->getInstallCommand($version)); + } + + public static function providePackageScenarios(): array + { + return [ + 'project' => ['project', 'dev', 'composer create-project vendor/name'], + 'library non-dev' => ['library', 'database', 'composer require vendor/name'], + 'library dev' => ['library', 'testing', 'composer require --dev vendor/name'], + ]; + } + + public function testInstallCommandWithoutVersion(): void + { + $package = new Package(); + $package->setName('vendor/name'); + + self::assertSame('composer require vendor/name', $package->getInstallCommand()); + } } diff --git a/tests/Entity/TagTest.php b/tests/Entity/TagTest.php new file mode 100644 index 000000000..c924c6b89 --- /dev/null +++ b/tests/Entity/TagTest.php @@ -0,0 +1,46 @@ +isDev()); + } + + public static function provideValidNames(): array + { + return [ + ['dev'], + ['testing'], + ['static analysis'], + ]; + } + + #[DataProvider('provideInvalidNames')] + public function testIsDevWithInvalidNames(string $name): void + { + $tag = new Tag($name); + + self::assertFalse($tag->isDev()); + } + + public static function provideInvalidNames(): array + { + return [ + ['orm'], + ['project'], + ['static-analysis'], + ]; + } +} diff --git a/tests/Entity/VersionTest.php b/tests/Entity/VersionTest.php new file mode 100644 index 000000000..320eeb450 --- /dev/null +++ b/tests/Entity/VersionTest.php @@ -0,0 +1,57 @@ +addTag(new Tag($tag)); + } + + self::assertTrue($version->hasDevTag()); + } + + public static function provideValidDevTagSets(): array + { + return [ + 'only dev' => [['dev']], + 'dev first' => [['dev', 'database']], + 'dev last' => [['database', 'dev']], + 'dev middle' => [['orm', 'dev', 'database']], + 'multiple' => [['dev', 'testing']], + ]; + } + #[DataProvider('provideInvalidDevTagSets')] + public function testHasDevTagWithout(array $tags): void + { + $version = new Version(); + + foreach ($tags as $tag) { + $version->addTag(new Tag($tag)); + } + + self::assertFalse($version->hasDevTag()); + } + + public static function provideInvalidDevTagSets(): array + { + return [ + 'none' => [[]], + 'one' => [['orm']], + 'two' => [['database', 'orm']], + 'three' => [['currency', 'database', 'clock']], + ]; + } +}