Skip to content

Commit

Permalink
Update storage signature, add storage of package metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
bennothommo committed Apr 9, 2024
1 parent 7838979 commit 62c32fc
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 76 deletions.
13 changes: 12 additions & 1 deletion src/Composer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Winter\Packager\Package\Package;
use Winter\Packager\Package\Packagist;
use Winter\Packager\Package\VersionedPackage;
use Winter\Packager\Storage\Storage;

/**
* Represents a Composer instance.
Expand Down Expand Up @@ -467,8 +468,18 @@ public static function newConstraint(mixed ...$arguments): Constraint
*
* `Name or Reference <[email protected]>`
*/
public static function setAgent(string $agent): void
public function setAgent(string $agent): static
{
Packagist::setAgent($agent);
return $this;
}

/**
* Sets the metadata storage for Packagist requests.
*/
public function setStorage(Storage $storage): static
{
Packagist::setStorage($storage);
return $this;
}
}
57 changes: 39 additions & 18 deletions src/Package/Packagist.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Winter\Packager\Exceptions\PackagistException;
use Winter\Packager\Storage\Storage;

/**
* Packagist class.
Expand All @@ -27,13 +28,22 @@ class Packagist

protected static string $agent = 'Winter Packager <[email protected]>';

protected static ?Storage $storage = null;

/**
* Get information on a package in the Packagist API.
*
* @return array<string, mixed>
*/
public static function getPackage(string $namespace, string $name, ?string $version = null): array
{
public static function getPackage(
string $namespace,
string $name,
?string $version = null
): array {
if (!is_null(static::$storage) && static::$storage->has($namespace, $name, $version)) {
return static::$storage->get($namespace, $name, $version);
}

$client = static::getClient();
$request = static::newRepoRequest($namespace . '/' . $name . '.json');

Expand All @@ -49,29 +59,32 @@ public static function getPackage(string $namespace, string $name, ?string $vers

$body = json_decode($response->getBody()->getContents(), true);

if (is_null($version)) {
if (!isset($body['packages'][$namespace . '/' . $name][0])) {
throw new PackagistException('Package information not found');
}
} else {
if (!isset($body['packages'][$namespace . '/' . $name])) {
throw new PackagistException('Package information not found');
}
if (!isset($body['packages'][$namespace . '/' . $name])) {
throw new PackagistException('Package information not found');
}

$versions = MetadataMinifier::expand($body['packages'][$namespace . '/' . $name]);
$parser = new VersionParser;
$packageVersionNormalized = $parser->normalize($version);
$versions = [];
foreach (MetadataMinifier::expand($body['packages'][$namespace . '/' . $name]) as $packageVersion) {
$versions[$packageVersion['version_normalized']] = $packageVersion;

foreach ($versions as $packageVersion) {
if ($packageVersion['version_normalized'] === $packageVersionNormalized) {
return $packageVersion;
}
// Store metadata
if (!is_null(static::$storage)) {
static::$storage->set($namespace, $name, $packageVersion['version_normalized'], $packageVersion);
}
}

if (is_null($version)) {
return reset($versions);
}

$parser = new VersionParser;
$versionNormalized = $parser->normalize($version);

if (!array_key_exists($versionNormalized, $versions)) {
throw new PackagistException('Package version not found');
}

return $body['packages'][$namespace . '/' . $name][0];
return $versions[$versionNormalized];
}

public static function getClient(): ClientInterface
Expand Down Expand Up @@ -104,6 +117,14 @@ public static function setAgent(string $agent): void
static::$agent = trim($name) . ' <' . trim($email) . '>';
}

/**
* Sets the storage for metadata.
*/
public static function setStorage(?Storage $storage = null): void
{
static::$storage = $storage;
}

public static function newApiRequest(string $url = ''): RequestInterface
{
$request = Psr17FactoryDiscovery::findRequestFactory()->createRequest('GET', self::PACKAGIST_API_URL . ltrim($url, '/'));
Expand Down
31 changes: 18 additions & 13 deletions src/Storage/Memory.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,58 +37,58 @@ public function __construct(?VersionParser $versionParser = null)
/**
* {@inheritDoc}
*/
public function get(string $package, ?string $version = null): ?array
public function get(string $namespace, string $name, ?string $version = null): ?array
{
if (isset($version)) {
$versionNormalized = $this->versionParser->normalize($version);

return $this->packages[$package][$versionNormalized] ?? null;
return $this->packages[$this->packageName($namespace, $name)][$versionNormalized] ?? null;
}

return $this->packages[$package] ?? null;
return $this->packages[$this->packageName($namespace, $name)] ?? null;
}

/**
* {@inheritDoc}
*/
public function set(string $package, string $version, array $packageData): void
public function set(string $namespace, string $name, string $version, array $packageData): void
{
if (!isset($this->packages[$package])) {
$this->packages[$package] = [];
if (!isset($this->packages[$this->packageName($namespace, $name)])) {
$this->packages[$this->packageName($namespace, $name)] = [];
}

$versionNormalized = $this->versionParser->normalize($version);

$this->packages[$package][$versionNormalized] = $packageData;
$this->packages[$this->packageName($namespace, $name)][$versionNormalized] = $packageData;
}

/**
* {@inheritDoc}
*/
public function forget(string $package, ?string $version = null): void
public function forget(string $namespace, string $name, ?string $version = null): void
{
if (isset($version)) {
$versionNormalized = $this->versionParser->normalize($version);

unset($this->packages[$package][$versionNormalized]);
unset($this->packages[$this->packageName($namespace, $name)][$versionNormalized]);
return;
}

unset($this->packages[$package]);
unset($this->packages[$this->packageName($namespace, $name)]);
}

/**
* {@inheritDoc}
*/
public function has(string $package, ?string $version = null): bool
public function has(string $namespace, string $name, ?string $version = null): bool
{
if (isset($version)) {
$versionNormalized = $this->versionParser->normalize($version);

return isset($this->packages[$package][$versionNormalized]);
return isset($this->packages[$this->packageName($namespace, $name)][$versionNormalized]);
}

return isset($this->packages[$package]);
return isset($this->packages[$this->packageName($namespace, $name)]);
}

/**
Expand All @@ -98,4 +98,9 @@ public function clear(): void
{
$this->packages = [];
}

protected function packageName(string $namespace, string $name): string
{
return $namespace . '/' . $name;
}
}
8 changes: 4 additions & 4 deletions src/Storage/Storage.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ interface Storage
*
* @return array<string|int, mixed>|null
*/
public function get(string $package, ?string $version = null): ?array;
public function get(string $namespace, string $name, ?string $version = null): ?array;

/**
* Sets the package metadata for the given package name and version.
*
* @param array<string, mixed> $packageData
*/
public function set(string $packageName, string $version, array $packageData): void;
public function set(string $namespace, string $name, string $version, array $packageData): void;

/**
* Forgets the package metadata for the given package name.
Expand All @@ -39,12 +39,12 @@ public function set(string $packageName, string $version, array $packageData): v
*
* This should be a no-op if the package metadata does not exist.
*/
public function forget(string $package, ?string $version = null): void;
public function forget(string $namespace, string $name, ?string $version = null): void;

/**
* Determines if the package metadata exists in storage, optionally with the specified version.
*/
public function has(string $package, ?string $version = null): bool;
public function has(string $namespace, string $name, ?string $version = null): bool;

/**
* Clears all package metadata.
Expand Down
45 changes: 45 additions & 0 deletions tests/Cases/Package/PackageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Winter\Packager\Tests\Cases\Package;

use Winter\Packager\Composer;
use Winter\Packager\Package\Packagist;
use Winter\Packager\Tests\ComposerTestCase;

/**
Expand Down Expand Up @@ -53,4 +54,48 @@ public function itCanConvertAVersionedPackageToADetailedPackage()
$this->assertEquals('pages', $package->getExtras()['installer-name']);
$this->assertEquals('2.0.3.0', $package->getVersionNormalized());
}

/**
* @test
* @testdox it can store and retrieve a package from storage
* @covers \Winter\Packager\Package\VersionedPackage::toDetailed
*/
public function itCanStoreAndRetrieveAPackageFromStorage()
{
$proxy = new \Winter\Packager\Storage\Memory;
$storage = $this->getMockBuilder(\Winter\Packager\Storage\Memory::class)
->setProxyTarget($proxy)
->enableProxyingToOriginalMethods()
->getMock();

Packagist::setStorage($storage);

$storage->expects($this->atLeastOnce())
->method('set')
->with('winter', 'wn-pages-plugin', $this->anything(), $this->anything());

$package = Composer::newVersionedPackage('winter', 'wn-pages-plugin', '', 'v2.0.3');
$package = $package->toDetailed();

$storage->expects($this->once())
->method('has')
->with('winter', 'wn-pages-plugin', 'v2.0.3');

$storage->expects($this->once())
->method('get')
->with('winter', 'wn-pages-plugin', 'v2.0.3');

$package = Composer::newVersionedPackage('winter', 'wn-pages-plugin', '', 'v2.0.3');
$package = $package->toDetailed();

$this->assertInstanceOf(\Winter\Packager\Package\DetailedVersionedPackage::class, $package);
$this->assertEquals('winter', $package->getNamespace());
$this->assertEquals('wn-pages-plugin', $package->getName());
$this->assertEquals('winter-plugin', $package->getType());
$this->assertEquals('https://github.com/wintercms/wn-pages-plugin', $package->getHomepage());
$this->assertArrayHasKey('installer-name', $package->getExtras());
$this->assertArrayNotHasKey('winter', $package->getExtras());
$this->assertEquals('pages', $package->getExtras()['installer-name']);
$this->assertEquals('2.0.3.0', $package->getVersionNormalized());
}
}
Loading

0 comments on commit 62c32fc

Please sign in to comment.