*/ public static function values(): array { return array_map( static fn (self $lifecycle): string => $lifecycle->value, self::cases(), ); } public static function fromTenant(Tenant $tenant): self { if ($tenant->trashed()) { return self::Archived; } return self::fromValue($tenant->status); } public static function fromValue(mixed $value, self $default = self::Active): self { return self::tryFromValue($value) ?? $default; } public static function tryFromValue(mixed $value): ?self { $normalized = self::normalize($value); return $normalized === null ? null : self::tryFrom($normalized); } public static function normalize(mixed $value): ?string { if ($value === null) { return null; } if ($value instanceof BackedEnum) { $value = $value->value; } if ($value instanceof Stringable) { $value = (string) $value; } if (! is_string($value)) { return null; } $normalized = strtolower(trim($value)); $normalized = str_replace([' ', '-'], '_', $normalized); return $normalized !== '' ? $normalized : null; } public function label(): string { return match ($this) { self::Draft => 'Draft', self::Onboarding => 'Onboarding', self::Active => 'Active', self::Archived => 'Archived', }; } public function isSelectableInStandardLane(): bool { return $this === self::Active; } public function isAdministrativelyDiscoverable(): bool { return true; } public function isViewableInLane(TenantInteractionLane $lane): bool { return match ($lane) { TenantInteractionLane::StandardActiveOperating => $this->isSelectableInStandardLane(), TenantInteractionLane::OnboardingWorkflow => in_array($this, [self::Draft, self::Onboarding], true), TenantInteractionLane::AdministrativeManagement, TenantInteractionLane::CanonicalWorkspaceRecord => true, }; } public function supportsQuestion(TenantOperabilityQuestion $question, TenantInteractionLane $lane): bool { return match ($question) { TenantOperabilityQuestion::SelectorEligibility, TenantOperabilityQuestion::RememberedContextValidity => $lane === TenantInteractionLane::StandardActiveOperating && $this->isSelectableInStandardLane(), TenantOperabilityQuestion::TenantBoundViewability => $lane === TenantInteractionLane::AdministrativeManagement, TenantOperabilityQuestion::CanonicalLinkedRecordViewability => $lane === TenantInteractionLane::CanonicalWorkspaceRecord, TenantOperabilityQuestion::ArchiveEligibility => $lane === TenantInteractionLane::AdministrativeManagement && $this->canArchive(), TenantOperabilityQuestion::RestoreEligibility => $lane === TenantInteractionLane::AdministrativeManagement && $this->canRestore(), TenantOperabilityQuestion::ResumeOnboardingEligibility => in_array($lane, [TenantInteractionLane::AdministrativeManagement, TenantInteractionLane::OnboardingWorkflow], true) && $this->canResumeOnboarding(), TenantOperabilityQuestion::OnboardingCompletionEligibility => $lane === TenantInteractionLane::OnboardingWorkflow && in_array($this, [self::Draft, self::Onboarding], true), TenantOperabilityQuestion::VerificationReadinessEligibility => match ($lane) { TenantInteractionLane::StandardActiveOperating => false, TenantInteractionLane::OnboardingWorkflow => in_array($this, [self::Draft, self::Onboarding], true), TenantInteractionLane::AdministrativeManagement => $this === self::Active, TenantInteractionLane::CanonicalWorkspaceRecord => false, }, TenantOperabilityQuestion::AdministrativeDiscoverability => $this->isAdministrativelyDiscoverable(), }; } public function canSelectAsContext(): bool { return $this->isSelectableInStandardLane(); } public function canViewTenantSurface(): bool { return $this->isAdministrativelyDiscoverable(); } public function canOperate(): bool { return $this === self::Active; } public function canArchive(): bool { return $this === self::Active; } public function canRestore(): bool { return $this === self::Archived; } public function canResumeOnboarding(): bool { return in_array($this, [self::Draft, self::Onboarding], true); } public function canReferenceInWorkspaceMonitoring(): bool { return true; } public function allowsManagementAction(string $actionKey): bool { return match ($actionKey) { 'resume_onboarding' => $this->canResumeOnboarding(), 'archive' => $this->canArchive(), 'restore' => $this->canRestore(), default => false, }; } }