TenantAtlas/apps/platform/app/Support/Rbac/Actions/UiActionContext.php
Ahmed Darrazi 9e435ea91f
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m2s
feat: implement explicit UiActionContext contract
2026-06-07 13:12:02 +02:00

161 lines
4.4 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Support\Rbac\Actions;
use App\Models\ManagedEnvironment;
use App\Models\Workspace;
use Illuminate\Database\Eloquent\Model;
use RuntimeException;
final readonly class UiActionContext
{
public const string CONTEXT_MISSING = 'context_missing';
public const string WORKSPACE_MISSING = 'workspace_missing';
public const string ENVIRONMENT_MISSING = 'environment_missing';
private function __construct(
public UiActionScope $scope,
public UiActionContextSource $source,
private ?Workspace $workspace = null,
private ?ManagedEnvironment $environment = null,
private ?Model $record = null,
private ?string $missingReason = null,
) {}
public static function forWorkspace(?Workspace $workspace, UiActionContextSource $source = UiActionContextSource::Explicit): self
{
if (! $workspace instanceof Workspace) {
return self::missing(self::WORKSPACE_MISSING, $source);
}
return new self(
scope: UiActionScope::Workspace,
source: $source,
workspace: $workspace,
);
}
public static function forEnvironment(?ManagedEnvironment $environment, UiActionContextSource $source = UiActionContextSource::Explicit): self
{
if (! $environment instanceof ManagedEnvironment) {
return self::missing(self::ENVIRONMENT_MISSING, $source);
}
return new self(
scope: UiActionScope::Environment,
source: $source,
workspace: $environment->workspace,
environment: $environment,
);
}
public static function forRecord(Model $record, UiActionContextSource $source = UiActionContextSource::Record): self
{
$environment = self::environmentFromRecord($record);
return new self(
scope: UiActionScope::Record,
source: $source,
workspace: $environment?->workspace,
environment: $environment,
record: $record,
);
}
public static function forSystem(UiActionContextSource $source = UiActionContextSource::Explicit): self
{
return new self(
scope: UiActionScope::System,
source: $source,
);
}
public static function missing(
string $reason = self::CONTEXT_MISSING,
UiActionContextSource $source = UiActionContextSource::Missing,
): self {
return new self(
scope: UiActionScope::Missing,
source: $source,
missingReason: $reason === '' ? self::CONTEXT_MISSING : $reason,
);
}
public function isMissing(): bool
{
return $this->scope === UiActionScope::Missing || $this->missingReason !== null;
}
public function missingReason(): ?string
{
return $this->missingReason;
}
public function workspace(): ?Workspace
{
return $this->workspace;
}
public function environment(): ?ManagedEnvironment
{
return $this->environment;
}
public function tenant(): ?ManagedEnvironment
{
return $this->environment();
}
public function record(): ?Model
{
return $this->record;
}
public function requireWorkspace(): Workspace
{
if ($this->workspace instanceof Workspace) {
return $this->workspace;
}
throw new RuntimeException($this->missingReason ?? self::WORKSPACE_MISSING);
}
public function requireEnvironment(): ManagedEnvironment
{
if ($this->environment instanceof ManagedEnvironment) {
return $this->environment;
}
throw new RuntimeException($this->missingReason ?? self::ENVIRONMENT_MISSING);
}
private static function environmentFromRecord(Model $record): ?ManagedEnvironment
{
if ($record instanceof ManagedEnvironment) {
return $record;
}
if (method_exists($record, 'relationLoaded') && $record->relationLoaded('tenant')) {
$tenant = $record->getRelation('tenant');
if ($tenant instanceof ManagedEnvironment) {
return $tenant;
}
}
if (method_exists($record, 'tenant')) {
$tenant = $record->getAttribute('tenant');
if ($tenant instanceof ManagedEnvironment) {
return $tenant;
}
}
return null;
}
}