From a6355c2f4dfa2b59ba909d004a2b72278aebaef9 Mon Sep 17 00:00:00 2001 From: Giuseppe Mazzapica Date: Mon, 27 Feb 2023 08:29:59 +0100 Subject: [PATCH] Add support for custom package types --- README.md | 24 +++++++++++- src/Config.php | 38 +++++++++++++++++++ src/Installer.php | 17 ++++++++- .../packages/custom-type/composer.json | 9 +++++ .../packages/custom-type/public/main.js | 0 tests/integration/IntegrationTest.php | 16 ++++++++ tests/src/TestCase.php | 7 +++- 7 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 tests/fixtures/packages/custom-type/composer.json create mode 100644 tests/fixtures/packages/custom-type/public/main.js diff --git a/README.md b/README.md index ab69701..5a5b8be 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Moreover, being that a WP standard path, we can use functions like `plugin_url() ## How it works This is a Composer plugin that provides **a custom installer for packages having -**`"wordpress-package"`** as type**. +**`"wordpress-package"`** as type**. Additional types can be supported via configuration. The installer does not change how the default Composer installer installs the package, but after the default installer has successfully installed the package, it looks into an @@ -217,6 +217,28 @@ To fail "hard", set `extra.package-assets-publisher.strict` to `true`. } ``` +### Custom types + +The installer by default only attempts to publish assets for packages with type: +**"wordpress-package"**. It is possible to support additional types, via configuration, like this: + +```json +{ + "extra": { + "package-assets-publisher": { + "types": [ + "wp-library" + ] + } + } +} +``` + +**Note**: This package is an _installer_ for custom types. By declaring support for a type we will +override the default installer for that type, which means that **if a package type needs to use a +custom installer, it should not be added to the supported types for this package**. + + ## Package config override Both the `extra.package-assets-publisher.symlink` and the `extra.package-assets-publisher.strict` diff --git a/src/Config.php b/src/Config.php index 5de067e..0208e67 100644 --- a/src/Config.php +++ b/src/Config.php @@ -39,6 +39,7 @@ class Config private const KEY_OPTIONS = 'options'; private const KEY_SYMLINK = 'symlink'; private const KEY_STRICT = 'strict'; + private const KEY_TYPES = 'types'; private Filesystem $filesystem; /** @var \SplObjectStorage */ @@ -46,6 +47,8 @@ class Config private ?string $assetsPath = null; private ?bool $isSymlink = null; private bool $isStrict = false; + /** @var list */ + private array $types = []; /** * @param array $extra @@ -101,6 +104,14 @@ public function isStrict(?PackageInterface $package): bool return $this->packageConfig($package)[1]; } + /** + * @return list + */ + public function types(): array + { + return $this->types; + } + /** * @param array $extra * @return void @@ -125,6 +136,7 @@ private function parseRoot(array $extra): void [$isStrict, $isSymlink] = $this->extractOptions($config); $this->isStrict = $isStrict; $this->isSymlink = $isSymlink; + $this->types = $this->extractTypes($config); } } @@ -227,6 +239,32 @@ private function extractOptions( return [$isStrict, $isSymlink]; } + /** + * @param array $source + * @return list + */ + private function extractTypes(array $source): array + { + $types = $source[self::KEY_TYPES] ?? null; + if (!is_array($types)) { + return []; + } + $parsed = []; + foreach ($types as $type) { + if ( + ($type !== '') + && is_string($type) + && !in_array($type, $parsed, true) + && preg_match('~^[a-z0-9_-]{2,}$~i', $type) + ) { + /** @var non-empty-string $type */ + $parsed[] = $type; + } + } + + return $parsed; + } + /** * @param array $array * @return bool diff --git a/src/Installer.php b/src/Installer.php index 679ccb4..8f6d6dc 100644 --- a/src/Installer.php +++ b/src/Installer.php @@ -41,6 +41,11 @@ class Installer extends LibraryInstaller */ private Publisher $publisher; + /** + * @var list + */ + private array $alternativeTypes; + /** * @param IOInterface $io * @param Composer $composer @@ -52,10 +57,20 @@ public function __construct(IOInterface $io, Composer $composer) $manager = $composer->getInstallationManager(); $filesystem = new Filesystem(new ComposerFilesystem()); $config = new Config($composer->getPackage()->getExtra(), $filesystem); - + $this->alternativeTypes = $config->types(); $this->publisher = new Publisher($manager, $io, $filesystem, $config); } + /** + * @param string $packageType + * @return bool + */ + public function supports(string $packageType): bool + { + return parent::supports($packageType) + || in_array($packageType, $this->alternativeTypes, true); + } + /** * @param InstalledRepositoryInterface $repo * @param PackageInterface $package diff --git a/tests/fixtures/packages/custom-type/composer.json b/tests/fixtures/packages/custom-type/composer.json new file mode 100644 index 0000000..ebd4fe4 --- /dev/null +++ b/tests/fixtures/packages/custom-type/composer.json @@ -0,0 +1,9 @@ +{ + "name": "test/custom-type", + "type": "wp-library", + "extra": { + "package-assets": [ + "public" + ] + } +} diff --git a/tests/fixtures/packages/custom-type/public/main.js b/tests/fixtures/packages/custom-type/public/main.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/integration/IntegrationTest.php b/tests/integration/IntegrationTest.php index 5b3cbc9..fbe345c 100644 --- a/tests/integration/IntegrationTest.php +++ b/tests/integration/IntegrationTest.php @@ -183,4 +183,20 @@ public function testPublishThenUnpublishWithOneFailure(): void static::assertFalse(is_file("{$expectedPath}/{$notExists}")); static::assertTrue(is_file("{$expectedPath}/{$exists}")); } + + /** + * @return void + */ + public function testCustomPackage(): void + { + $package = $this->loadPackage('custom-type'); + $publisher = $this->factoryPublisher(null, true, false, null, ['wp-library']); + + $publisher->publish($package); + + $expectedPath = $this->outputPath('.published-package-assets/test/custom-type'); + + static::assertTrue($this->io->hasOutputThatMatches('~published assets.+?public/~i')); + static::assertTrue(is_file("{$expectedPath}/public/main.js")); + } } diff --git a/tests/src/TestCase.php b/tests/src/TestCase.php index 75d191d..eb452c2 100644 --- a/tests/src/TestCase.php +++ b/tests/src/TestCase.php @@ -122,7 +122,7 @@ protected function factoryIo(int $verbosity = IOInterface::NORMAL): IOInterface } /** - * @return Config + * @return Filesystem */ protected function factoryFilesystem(): Filesystem { @@ -145,13 +145,15 @@ protected function factoryConfig(array $extra = []): Config * @param bool $strict * @param bool|null $symlink * @param string|null $targetBase + * @param array $types * @return Publisher */ protected function factoryPublisher( ?string $dir = null, bool $strict = false, ?bool $symlink = null, - ?string $targetBase = null + ?string $targetBase = null, + array $types = [] ): Publisher { $extra = [ @@ -159,6 +161,7 @@ protected function factoryPublisher( 'publish-dir' => ($dir ?? $this->outputPath()), 'strict' => $strict, 'symlink' => $symlink, + 'types' => $types, ], ];