$strategies */ public function __construct( private readonly array $strategies = [], ) {} /** * @return list */ public function all(): array { if ($this->strategies !== []) { return $this->strategies; } return [app(IntuneCompareStrategy::class)]; } public function find(CompareStrategyKey|string|null $strategyKey): ?CompareStrategy { if ($strategyKey === null) { return null; } $normalizedKey = CompareStrategyKey::from($strategyKey); foreach ($this->all() as $strategy) { if ($strategy->key()->equals($normalizedKey)) { return $strategy; } } return null; } public function resolve(CompareStrategyKey|string $strategyKey): CompareStrategy { $strategy = $this->find($strategyKey); if ($strategy instanceof CompareStrategy) { return $strategy; } throw new InvalidArgumentException('Unknown compare strategy ['.CompareStrategyKey::from($strategyKey)->value.'].'); } public function select(BaselineScope $scope): CompareStrategySelection { $entries = $this->entriesForScope($scope); if ($entries === []) { return CompareStrategySelection::unsupported( matchedScopeEntries: [], rejectedScopeEntries: [], diagnostics: [], operatorReason: 'No governed subjects were selected for compare.', ); } $matchedScopeEntries = []; $rejectedScopeEntries = []; $matchedStrategyKeys = []; $entryMatches = []; foreach ($entries as $entry) { $matchingKeys = $this->matchingStrategyKeysForEntry($entry); $entryFingerprint = $this->entryFingerprint($entry); $entryMatches[$entryFingerprint] = $matchingKeys; if ($matchingKeys === []) { $rejectedScopeEntries[] = $entry; continue; } $matchedScopeEntries[] = $entry; $matchedStrategyKeys = array_values(array_unique(array_merge($matchedStrategyKeys, $matchingKeys))); } sort($matchedStrategyKeys, SORT_STRING); if ($rejectedScopeEntries !== []) { return CompareStrategySelection::unsupported( matchedScopeEntries: $matchedScopeEntries, rejectedScopeEntries: $rejectedScopeEntries, diagnostics: [ 'matched_strategy_keys' => $matchedStrategyKeys, 'entry_matches' => $entryMatches, ], ); } if (count($matchedStrategyKeys) !== 1) { return CompareStrategySelection::mixed( matchedScopeEntries: $matchedScopeEntries, diagnostics: [ 'matched_strategy_keys' => $matchedStrategyKeys, 'entry_matches' => $entryMatches, ], ); } return CompareStrategySelection::supported( strategyKey: $matchedStrategyKeys[0], matchedScopeEntries: $matchedScopeEntries, diagnostics: [ 'matched_strategy_keys' => $matchedStrategyKeys, 'entry_matches' => $entryMatches, ], ); } /** * @param array{domain_key?: mixed, subject_class?: mixed, subject_type_keys?: mixed, filters?: mixed} $entry * @return list */ private function matchingStrategyKeysForEntry(array $entry): array { $matches = []; foreach ($this->all() as $strategy) { foreach ($strategy->capabilities() as $capability) { if (! $capability->supportsEntry($entry)) { continue; } $matches[] = $strategy->key()->value; break; } } $matches = array_values(array_unique($matches)); sort($matches, SORT_STRING); return $matches; } /** * @return list, filters: array}> */ private function entriesForScope(BaselineScope $scope): array { if ($scope->entries !== []) { return $scope->entries; } $entries = []; if ($scope->policyTypes !== []) { $entries[] = [ 'domain_key' => GovernanceDomainKey::Intune->value, 'subject_class' => GovernanceSubjectClass::Policy->value, 'subject_type_keys' => $scope->policyTypes, 'filters' => [], ]; } if ($scope->foundationTypes !== []) { $entries[] = [ 'domain_key' => GovernanceDomainKey::PlatformFoundation->value, 'subject_class' => GovernanceSubjectClass::ConfigurationResource->value, 'subject_type_keys' => $scope->foundationTypes, 'filters' => [], ]; } return $entries; } /** * @param array{domain_key?: mixed, subject_class?: mixed, subject_type_keys?: mixed, filters?: mixed} $entry */ private function entryFingerprint(array $entry): string { $subjectTypeKeys = is_array($entry['subject_type_keys'] ?? null) ? array_values(array_filter($entry['subject_type_keys'], 'is_string')) : []; sort($subjectTypeKeys, SORT_STRING); return implode('|', [ trim((string) ($entry['domain_key'] ?? '')), trim((string) ($entry['subject_class'] ?? '')), implode(',', $subjectTypeKeys), ]); } }