Files
michaelschiemer/src/Framework/Composer/ValueObjects/ComposerLock.php
2025-11-24 21:28:25 +01:00

142 lines
3.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\Composer\ValueObjects;
use App\Framework\Composer\Exception\ComposerLockException;
/**
* Immutable Value Object representing composer.lock data
*/
final readonly class ComposerLock
{
/**
* @param array<array<string, mixed>> $packages
* @param array<array<string, mixed>> $packagesDev
* @param array<string, mixed> $platform
* @param array<string, mixed> $platformDev
*/
public function __construct(
public array $packages = [],
public array $packagesDev = [],
public array $platform = [],
public array $platformDev = [],
public ?string $contentHash = null
) {
}
/**
* Create ComposerLock from file path
*/
public static function fromFile(string $path): self
{
if (! file_exists($path)) {
throw ComposerLockException::fileNotFound($path);
}
$content = @file_get_contents($path);
if ($content === false) {
throw ComposerLockException::couldNotRead($path, new \RuntimeException('file_get_contents failed'));
}
$data = json_decode($content, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw ComposerLockException::invalidJson($path, new \JsonException(json_last_error_msg()));
}
return self::fromArray($data);
}
/**
* Create ComposerLock from array data
*
* @param array<string, mixed> $data
*/
public static function fromArray(array $data): self
{
return new self(
packages: $data['packages'] ?? [],
packagesDev: $data['packages-dev'] ?? [],
platform: $data['platform'] ?? [],
platformDev: $data['platform-dev'] ?? [],
contentHash: $data['content-hash'] ?? null
);
}
/**
* Get all packages (production + dev) as flat array
*
* @return array<array<string, mixed>>
*/
public function getAllPackages(): array
{
return array_merge($this->packages, $this->packagesDev);
}
/**
* Get package by name
*
* @return array<string, mixed>|null
*/
public function getPackage(string $name): ?array
{
// Check production packages first
foreach ($this->packages as $package) {
if (isset($package['name']) && $package['name'] === $name) {
return $package;
}
}
// Check dev packages
foreach ($this->packagesDev as $package) {
if (isset($package['name']) && $package['name'] === $name) {
return $package;
}
}
return null;
}
/**
* Check if package exists
*/
public function hasPackage(string $name): bool
{
return $this->getPackage($name) !== null;
}
/**
* Get packages with their type (production or dev)
*
* @return array<array{name: string, version: string, type: 'production'|'dev'}>
*/
public function getPackagesWithType(): array
{
$result = [];
foreach ($this->packages as $package) {
if (isset($package['name']) && isset($package['version'])) {
$result[] = [
'name' => $package['name'],
'version' => $package['version'],
'type' => 'production',
];
}
}
foreach ($this->packagesDev as $package) {
if (isset($package['name']) && isset($package['version'])) {
$result[] = [
'name' => $package['name'],
'version' => $package['version'],
'type' => 'dev',
];
}
}
return $result;
}
}