Skip to content

Commit

Permalink
feat: added package manifest (#337)
Browse files Browse the repository at this point in the history
* feat: added package manifest

- package manifest for composer installed package

* add default providers place header
  • Loading branch information
SonyPradana authored Jun 5, 2024
1 parent 04528ab commit ae26baa
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 0 deletions.
95 changes: 95 additions & 0 deletions src/System/Integrate/PackageManifest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

declare(strict_types=1);

namespace System\Integrate;

final class PackageManifest
{
/**
* Cached package manifest.
*
* @var array<string, array<string, array<int, string>>>|null
*/
public ?array $package_manifest = null;

public function __construct(
private string $base_path,
private string $application_cache_path,
private ?string $vendor_path = null
) {
$this->vendor_path ??= DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR;
}

/**
* Get provider in cache package manifest.
*
* @return string[]
*/
public function providers(): array
{
return $this->config()['providers'];
}

/**
* Get array of provider..
*
* @return array<string, string[]>
*/
protected function config(): array
{
$this->getPackageManifest();
$entry = [
'providers' => [],
];
foreach ($this->package_manifest ?? [] as $package) {
foreach ($package['providers'] ?? [] as $provider) {
$entry['providers'][] = $provider;
}
}

return $entry;
}

/**
* Get cached package manifest has been build.
*
* @return array<string, array<string, array<int, string>>>
*/
protected function getPackageManifest(): array
{
if ($this->package_manifest) {
return $this->package_manifest;
}

if (false === file_exists($this->application_cache_path . 'provider.php')) {
$this->build();
}

return $this->package_manifest = require $this->application_cache_path . 'provider.php';
}

/**
* Build cache package manifest from composer installed package.
*/
public function build(): void
{
$packages = [];
$provider = [];

// vendor\composer\installed.json
if (file_exists($file = $this->base_path . $this->vendor_path . 'installed.json')) {
$installed = file_get_contents($file);
$installed = json_decode($installed, true);

$packages = $installed['packages'] ?? [];
}

foreach ($packages as $package) {
$provider[$package['name']] = $package['extra']['savanna'] ?? [''];
}
array_filter($provider);

file_put_contents($this->application_cache_path . 'provider.php', '<?php return ' . var_export($provider, true) . ';' . PHP_EOL);
}
}
97 changes: 97 additions & 0 deletions tests/Integrate/PackageManifestTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

use PHPUnit\Framework\TestCase;
use System\Integrate\PackageManifest;

class PackageManifestTest extends TestCase
{
private string $base_path = __DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR;
private string $application_cache_path = __DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR;
private string $package_manifest = __DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'provider.php';

public function deleteAsset()
{
if (file_exists($this->package_manifest)) {
@unlink($this->package_manifest);
}
}

protected function setUp(): void
{
$this->deleteAsset();
}

protected function tearDown(): void
{
$this->deleteAsset();
}

/**
* @test
*/
public function itCanBuild()
{
$package_manifest = new PackageManifest($this->base_path, $this->application_cache_path, DIRECTORY_SEPARATOR . 'package' . DIRECTORY_SEPARATOR);
$package_manifest->build();

$this->assertTrue(file_exists($this->package_manifest));
}

/**
* @test
*/
public function itCanGetPackageManifest()
{
$package_manifest = new PackageManifest($this->base_path, $this->application_cache_path, DIRECTORY_SEPARATOR . 'package' . DIRECTORY_SEPARATOR);

$manifest = (fn () => $this->{'getPackageManifest'}())->call($package_manifest);

$this->assertEquals([
'packages/package1' => [
'providers' => [
'Package//Package1//ServiceProvider::class',
],
],
'packages/package2' => [
'providers' => [
'Package//Package2//ServiceProvider::class',
'Package//Package2//ServiceProvider2::class',
],
],
], $manifest);
}

/**
* @test
*/
public function itCanGetConfig()
{
$package_manifest = new PackageManifest($this->base_path, $this->application_cache_path, DIRECTORY_SEPARATOR . 'package' . DIRECTORY_SEPARATOR);

$config = (fn () => $this->{'config'}())->call($package_manifest);

$this->assertEquals([
'providers' => [
'Package//Package1//ServiceProvider::class',
'Package//Package2//ServiceProvider::class',
'Package//Package2//ServiceProvider2::class',
],
], $config);
}

/**
* @test
*/
public function itCanGetProviders()
{
$package_manifest = new PackageManifest($this->base_path, $this->application_cache_path, DIRECTORY_SEPARATOR . 'package' . DIRECTORY_SEPARATOR);

$config = $package_manifest->providers();

$this->assertEquals([
'Package//Package1//ServiceProvider::class',
'Package//Package2//ServiceProvider::class',
'Package//Package2//ServiceProvider2::class',
], $config);
}
}
1 change: 1 addition & 0 deletions tests/Integrate/assets/cache/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.php
25 changes: 25 additions & 0 deletions tests/Integrate/assets/package/installed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"packages": [
{
"name": "packages/package1",
"extra": {
"savanna": {
"providers": [
"Package//Package1//ServiceProvider::class"
]
}
}
},
{
"name": "packages/package2",
"extra": {
"savanna": {
"providers": [
"Package//Package2//ServiceProvider::class",
"Package//Package2//ServiceProvider2::class"
]
}
}
}
]
}

0 comments on commit ae26baa

Please sign in to comment.