Skip to content

Commit

Permalink
feat(documentator): requirements command will support package merging.
Browse files Browse the repository at this point in the history
  • Loading branch information
LastDragon-ru committed Mar 21, 2024
1 parent 5192462 commit 07adf1d
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 11 deletions.
12 changes: 12 additions & 0 deletions packages/documentator/docs/Commands/requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ PHP only:
}
```

You can also merge multiple requirements into one. For example, the
following will merge all `illuminate` into `laravel/framework` (the
package will be ignored if not listed in `require`):

```json
{
"merge": {
"illuminate/*": "laravel/framework"
}
}
```

## Arguments

### `cwd?`
Expand Down
86 changes: 79 additions & 7 deletions packages/documentator/src/Commands/Requirements.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use function array_diff_key;
use function array_filter;
use function array_keys;
use function array_map;
use function array_merge;
use function array_search;
use function array_unique;
Expand All @@ -33,9 +34,13 @@
use function json_decode;
use function mb_strlen;
use function mb_substr;
use function natsort;
use function preg_match;
use function preg_quote;
use function range;
use function reset;
use function str_starts_with;
use function strtr;
use function trim;
use function uksort;

Expand Down Expand Up @@ -73,6 +78,18 @@ class Requirements extends Command {
}
}
```
You can also merge multiple requirements into one. For example, the
following will merge all `illuminate` into `laravel/framework` (the
package will be ignored if not listed in `require`):
```json
{
"merge": {
"illuminate/*": "laravel/framework"
}
}
```
HELP;

public function __invoke(PackageViewer $viewer, Git $git, Serializer $serializer): void {
Expand All @@ -87,6 +104,9 @@ public function __invoke(PackageViewer $viewer, Git $git, Serializer $serializer
'php' => 'PHP',
'laravel/framework' => 'Laravel',
];
$merge = $metadata->merge ?? [
'illuminate/*' => 'laravel/framework',
];

foreach ($tags as $tag) {
// Cached?
Expand All @@ -106,13 +126,7 @@ public function __invoke(PackageViewer $viewer, Git $git, Serializer $serializer
}

// Update
$metadata->requirements[$tag] = [];

foreach ($packages as $key => $title) {
$required = explode('|', Cast::toString($package['require'][$key] ?? ''));
$required = array_values(array_filter($required));
$metadata->requirements[$tag][$key] = $required;
}
$metadata->requirements[$tag] = $this->getPackageRequirements($packages, $merge, $package);
}

// Cleanup
Expand Down Expand Up @@ -192,6 +206,64 @@ protected function getPackageInfo(Git $git, string $tag, string $cwd): ?array {
return $package;
}

/**
* @param array<string, string> $require
* @param array<string, string> $merge
* @param array<array-key, mixed> $package
*
* @return array<string, list<string>>
*/
protected function getPackageRequirements(array $require, array $merge, array $package): array {
// Prepare
$regexps = [];

foreach ($require as $key => $title) {
$regexp = '#^'.preg_quote($key).'$#u';
$regexps[$regexp] = $key;
}

foreach ($merge as $pattern => $key) {
$regexp = '#^'.strtr(preg_quote($pattern), ['\\*' => '.+?']).'$#u';
$regexps[$regexp] = $key;
}

// Requirements
$requirements = [];

foreach ($package['require'] ?? [] as $requirement => $constraint) {
// Match?
$match = false;

foreach ($regexps as $regexp => $key) {
if (preg_match($regexp, $requirement)) {
$requirement = $key;
$match = true;
break;
}
}

if (!$match) {
continue;
}

// Wanted?
if (!isset($require[$requirement])) {
continue;
}

// Add
$required = explode('|', Cast::toString($constraint));
$required = array_values(array_filter(array_map(trim(...), $required)));
$requirement = Cast::toString($requirement);
$requirements[$requirement] = array_merge($requirements[$requirement] ?? [], $required);
$requirements[$requirement] = array_values(array_unique($requirements[$requirement]));

natsort($requirements[$requirement]);
}

return $requirements;
}

/**
* @param array<string, string> $packages
*
Expand Down
54 changes: 54 additions & 0 deletions packages/documentator/src/Commands/RequirementsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,58 @@ public function getRequirements(array $packages, Metadata $metadata): array {
$command->getRequirements($packages, $metadata),
);
}

public function testGetPackageRequirements(): void {
$merge = [
'illuminate/*' => 'laravel/framework',
'example/package' => 'another/package',
];
$packages = [
'laravel/framework' => 'Laravel',
'php' => 'PHP',
];
$package = [
'require' => [
'php' => '^8.1|^8.2|^8.3',
'ext-mbstring' => '*',
'composer/semver' => '^3.2',
'laravel/framework' => '^10.34.0',
'league/commonmark' => '^2.4',
'illuminate/auth' => '^10 || ^9',
'illuminate/bus' => '^9 || ^10',
'illuminate/contracts' => '^9 || ^10 || ^11',
'example/package' => '~1.0.0',
],
];
$command = new class() extends Requirements {
/**
* @inheritDoc
*/
#[Override]
public function getPackageRequirements(array $require, array $merge, array $package): array {
return parent::getPackageRequirements(
$require,
$merge,
$package,
);
}
};

self::assertEquals(
[
'laravel/framework' => [
'^9',
'^10',
'^10.34.0',
'^11',
],
'php' => [
'^8.1',
'^8.2',
'^8.3',
],
],
$command->getPackageRequirements($packages, $merge, $package),
);
}
}
23 changes: 19 additions & 4 deletions packages/documentator/src/Metadata/Metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,28 @@
* @internal
*/
class Metadata implements Serializable {
/**
* @param array<string, string> $require
* @param array<string, array<string, list<string>>> $requirements
*/
public function __construct(
/**
* Package version.
*/
public ?string $version = null,
/**
* Requirements to show.
*
* @var array<string, string>
*/
public array $require = [],
/**
* Defines how to merge packages (`illuminate/*`, `symfony/*`, etc)
*
* @var array<string, string>|null
*/
public ?array $merge = null,
/**
* Cached requirements.
*
* @var array<string, array<string, list<string>>>
*/
public array $requirements = [],
) {
// empty
Expand Down

0 comments on commit 07adf1d

Please sign in to comment.