$guidance * @return array{ * key:string, * scope:array, * severity:string, * status:string, * title:string, * reason:string, * impact:string, * primary_action:array{ * key:string, * label:string, * type:string, * url:?string, * icon:string, * kind:string, * action_name:?string, * capability:?string, * requires_confirmation:bool, * audit_event:?string, * operation_run_type:?string, * disabled_reason:?string * }, * secondary_actions:list, * source_refs:list, * evidence_refs:list, * technical_details:array * } */ public static function fromGuidance( EnvironmentReview $review, array $guidance, string $sourceSurface, array $context = [], ): array { $scope = array_filter([ 'type' => 'review_pack', 'workspace_id' => (int) $review->workspace_id, 'managed_environment_id' => (int) $review->managed_environment_id, 'environment_review_id' => (int) $review->getKey(), 'review_pack_id' => $review->currentExportReviewPack instanceof ReviewPack ? (int) $review->currentExportReviewPack->getKey() : '', 'source_surface' => $sourceSurface, ], static fn (mixed $value): bool => $value !== null && $value !== ''); $mappedActions = ReviewOutputResolveActionMapper::map( review: $review, guidance: $guidance, sourceSurface: $sourceSurface, urls: is_array($context['urls'] ?? null) ? $context['urls'] : [], execution: is_array($context['execution'] ?? null) ? $context['execution'] : [], ); return ResolutionCase::make( key: self::caseKey((string) ($guidance['state'] ?? ReviewPackOutputResolutionGuidance::STATE_UNKNOWN)), scope: $scope, severity: self::severity((string) ($guidance['state'] ?? ReviewPackOutputResolutionGuidance::STATE_UNKNOWN)), status: self::status((string) ($guidance['state'] ?? ReviewPackOutputResolutionGuidance::STATE_UNKNOWN)), title: (string) ($guidance['label'] ?? __('localization.review.requires_review')), reason: (string) ($guidance['primary_reason'] ?? __('localization.review.review_pack_with_limitations_description')), impact: (string) ($guidance['impact'] ?? __('localization.review.published_with_limitations_impact')), primaryAction: $mappedActions['primary_action'], secondaryActions: $mappedActions['secondary_actions'], sourceRefs: self::sourceRefs($review), evidenceRefs: self::evidenceRefs($review), technicalDetails: self::technicalDetails($guidance), ); } /** * @param array $guidance * @return list */ private static function secondaryActions(array $guidance): array { $secondaryActions = is_array($guidance['secondary_actions'] ?? null) ? $guidance['secondary_actions'] : []; return array_values(array_map( static fn (array $action, int $index): array => ResolutionAction::fromArray( $action, self::caseKey((string) ($guidance['state'] ?? ReviewPackOutputResolutionGuidance::STATE_UNKNOWN)).'.secondary_action_'.$index, __('localization.review.review_output_limitations'), ), array_values(array_filter($secondaryActions, static fn (mixed $action): bool => is_array($action))), array_keys(array_values(array_filter($secondaryActions, static fn (mixed $action): bool => is_array($action)))), )); } /** * @return list */ private static function sourceRefs(EnvironmentReview $review): array { $refs = [ [ 'type' => 'environment_review', 'id' => (int) $review->getKey(), ], ]; if ($review->currentExportReviewPack instanceof ReviewPack) { $refs[] = [ 'type' => 'review_pack', 'id' => (int) $review->currentExportReviewPack->getKey(), ]; } if ($review->operationRun !== null) { $refs[] = [ 'type' => 'operation_run', 'id' => (int) $review->operationRun->getKey(), ]; } return $refs; } /** * @return list */ private static function evidenceRefs(EnvironmentReview $review): array { if (! $review->evidenceSnapshot instanceof EvidenceSnapshot) { return []; } return [[ 'type' => 'evidence_snapshot', 'id' => (int) $review->evidenceSnapshot->getKey(), ]]; } /** * @param array $guidance * @return array */ private static function technicalDetails(array $guidance): array { return array_filter( is_array($guidance['technical_details'] ?? null) ? $guidance['technical_details'] : [], static fn (mixed $value): bool => is_string($value) && $value !== '', ); } private static function caseKey(string $state): string { return 'review_output.'.$state; } private static function severity(string $state): string { return match ($state) { ReviewPackOutputResolutionGuidance::STATE_CUSTOMER_SAFE_READY => 'success', ReviewPackOutputResolutionGuidance::STATE_PUBLICATION_BLOCKED => 'critical', default => 'warning', }; } private static function status(string $state): string { return match ($state) { ReviewPackOutputResolutionGuidance::STATE_CUSTOMER_SAFE_READY => 'ready', ReviewPackOutputResolutionGuidance::STATE_PUBLICATION_BLOCKED, ReviewPackOutputResolutionGuidance::STATE_EXPORT_NOT_READY => 'blocked', ReviewPackOutputResolutionGuidance::STATE_UNKNOWN => 'unknown', default => 'action_required', }; } }