Add object-oriented license client library (v0.0.2)

- Add LicenseClient with PSR-3 logging and PSR-6 caching support
- Add DTO classes: LicenseInfo, LicenseStatus, ActivationResult
- Add LicenseState enum for license status values
- Add comprehensive exception hierarchy for error handling
- Add PSR dependencies (psr/log, psr/cache, psr/http-client)
- Update README with usage examples
- Update CHANGELOG for v0.0.2

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-22 15:51:05 +01:00
parent a702c262ca
commit 9e0cf0825f
20 changed files with 730 additions and 6 deletions

View File

@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Magdev\WcLicensedProductClient\Dto;
final readonly class ActivationResult
{
public function __construct(
public bool $success,
public string $message,
) {
}
public static function fromArray(array $data): self
{
return new self(
success: $data['success'],
message: $data['message'],
);
}
}

34
src/Dto/LicenseInfo.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace Magdev\WcLicensedProductClient\Dto;
final readonly class LicenseInfo
{
public function __construct(
public int $productId,
public ?\DateTimeImmutable $expiresAt = null,
public ?int $versionId = null,
) {
}
public static function fromArray(array $data): self
{
$expiresAt = null;
if (isset($data['expires_at']) && $data['expires_at'] !== null) {
$expiresAt = new \DateTimeImmutable($data['expires_at']);
}
return new self(
productId: $data['product_id'],
expiresAt: $expiresAt,
versionId: $data['version_id'] ?? null,
);
}
public function isLifetime(): bool
{
return $this->expiresAt === null;
}
}

53
src/Dto/LicenseStatus.php Normal file
View File

@@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace Magdev\WcLicensedProductClient\Dto;
enum LicenseState: string
{
case Active = 'active';
case Inactive = 'inactive';
case Expired = 'expired';
case Revoked = 'revoked';
}
final readonly class LicenseStatus
{
public function __construct(
public bool $valid,
public LicenseState $status,
public string $domain,
public ?\DateTimeImmutable $expiresAt,
public int $activationsCount,
public int $maxActivations,
) {
}
public static function fromArray(array $data): self
{
$expiresAt = null;
if (isset($data['expires_at']) && $data['expires_at'] !== null) {
$expiresAt = new \DateTimeImmutable($data['expires_at']);
}
return new self(
valid: $data['valid'],
status: LicenseState::from($data['status']),
domain: $data['domain'],
expiresAt: $expiresAt,
activationsCount: $data['activations_count'],
maxActivations: $data['max_activations'],
);
}
public function isLifetime(): bool
{
return $this->expiresAt === null;
}
public function hasAvailableActivations(): bool
{
return $this->activationsCount < $this->maxActivations;
}
}