Skip to content

Commit

Permalink
Add support for custom package types
Browse files Browse the repository at this point in the history
  • Loading branch information
gmazzap committed Feb 27, 2023
1 parent 4f842c7 commit a6355c2
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 4 deletions.
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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`
Expand Down
38 changes: 38 additions & 0 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,16 @@ 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<PackageInterface, Package-Config> */
private \SplObjectStorage $packages;
private ?string $assetsPath = null;
private ?bool $isSymlink = null;
private bool $isStrict = false;
/** @var list<non-empty-string> */
private array $types = [];

/**
* @param array $extra
Expand Down Expand Up @@ -101,6 +104,14 @@ public function isStrict(?PackageInterface $package): bool
return $this->packageConfig($package)[1];
}

/**
* @return list<non-empty-string>
*/
public function types(): array
{
return $this->types;
}

/**
* @param array $extra
* @return void
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -227,6 +239,32 @@ private function extractOptions(
return [$isStrict, $isSymlink];
}

/**
* @param array $source
* @return list<non-empty-string>
*/
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
Expand Down
17 changes: 16 additions & 1 deletion src/Installer.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ class Installer extends LibraryInstaller
*/
private Publisher $publisher;

/**
* @var list<non-empty-string>
*/
private array $alternativeTypes;

/**
* @param IOInterface $io
* @param Composer $composer
Expand All @@ -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
Expand Down
9 changes: 9 additions & 0 deletions tests/fixtures/packages/custom-type/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "test/custom-type",
"type": "wp-library",
"extra": {
"package-assets": [
"public"
]
}
}
Empty file.
16 changes: 16 additions & 0 deletions tests/integration/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
}
}
7 changes: 5 additions & 2 deletions tests/src/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ protected function factoryIo(int $verbosity = IOInterface::NORMAL): IOInterface
}

/**
* @return Config
* @return Filesystem
*/
protected function factoryFilesystem(): Filesystem
{
Expand All @@ -145,20 +145,23 @@ 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 = [
'package-assets-publisher' => [
'publish-dir' => ($dir ?? $this->outputPath()),
'strict' => $strict,
'symlink' => $symlink,
'types' => $types,
],
];

Expand Down

0 comments on commit a6355c2

Please sign in to comment.