php-tenant/Services/EntitlementResult.php
Snider d0ad2737cb refactor: rename namespace from Core\Mod\Tenant to Core\Tenant
Simplifies the namespace hierarchy by removing the intermediate Mod
segment. Updates all 118 files including models, services, controllers,
middleware, tests, and composer.json autoload configuration.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 16:30:46 +00:00

174 lines
3.9 KiB
PHP

<?php
namespace Core\Tenant\Services;
/**
* Value object representing the result of an entitlement check.
*/
class EntitlementResult
{
public function __construct(
public readonly bool $allowed,
public readonly ?string $reason = null,
public readonly ?int $limit = null,
public readonly ?int $used = null,
public readonly ?int $remaining = null,
public readonly ?string $featureCode = null,
public readonly array $metadata = [],
) {}
/**
* Create an allowed result.
*/
public static function allowed(
?int $limit = null,
?int $used = null,
?string $featureCode = null,
array $metadata = []
): self {
return new self(
allowed: true,
limit: $limit,
used: $used,
remaining: $limit !== null ? max(0, $limit - ($used ?? 0)) : null,
featureCode: $featureCode,
metadata: $metadata,
);
}
/**
* Create a denied result.
*/
public static function denied(
string $reason,
?int $limit = null,
?int $used = null,
?string $featureCode = null,
array $metadata = []
): self {
return new self(
allowed: false,
reason: $reason,
limit: $limit,
used: $used,
remaining: $limit !== null ? max(0, $limit - ($used ?? 0)) : null,
featureCode: $featureCode,
metadata: $metadata,
);
}
/**
* Create an unlimited result (feature has no limit).
*/
public static function unlimited(?string $featureCode = null, array $metadata = []): self
{
return new self(
allowed: true,
featureCode: $featureCode,
metadata: array_merge($metadata, ['unlimited' => true]),
);
}
/**
* Check if the request is allowed.
*/
public function isAllowed(): bool
{
return $this->allowed;
}
/**
* Check if the request is denied.
*/
public function isDenied(): bool
{
return ! $this->allowed;
}
/**
* Get the denial message.
*/
public function getMessage(): ?string
{
return $this->reason;
}
/**
* Check if this is an unlimited feature.
*/
public function isUnlimited(): bool
{
return $this->metadata['unlimited'] ?? false;
}
/**
* Get usage percentage (0-100).
*/
public function getUsagePercentage(): ?float
{
if ($this->limit === null || $this->limit === 0) {
return null;
}
return min(100, ($this->used ?? 0) / $this->limit * 100);
}
/**
* Check if usage is near the limit (> 80%).
*/
public function isNearLimit(): bool
{
$percentage = $this->getUsagePercentage();
return $percentage !== null && $percentage >= 80;
}
/**
* Check if usage is at the limit.
*/
public function isAtLimit(): bool
{
return $this->remaining === 0;
}
/**
* Get the limit value.
*/
public function getLimit(): ?int
{
return $this->limit;
}
/**
* Get the used value.
*/
public function getUsed(): ?int
{
return $this->used;
}
/**
* Get the remaining value.
*/
public function getRemaining(): ?int
{
return $this->remaining;
}
/**
* Convert to array for JSON responses.
*/
public function toArray(): array
{
return [
'allowed' => $this->allowed,
'reason' => $this->reason,
'limit' => $this->limit,
'used' => $this->used,
'remaining' => $this->remaining,
'feature_code' => $this->featureCode,
'unlimited' => $this->isUnlimited(),
'usage_percentage' => $this->getUsagePercentage(),
];
}
}