>, settings_table?: array, warnings: array} */ public function normalize(?array $snapshot, string $policyType, ?string $platform = null): array { $snapshot = $snapshot ?? []; $normalized = $this->defaultNormalizer->normalize($snapshot, $policyType, $platform); if ($snapshot === []) { return $normalized; } $normalized['settings'][] = $this->buildFeatureUpdateBlock($snapshot); $normalized['settings'] = array_values(array_filter($normalized['settings'])); return $normalized; } /** * @return array */ public function flattenForDiff(?array $snapshot, string $policyType, ?string $platform = null): array { $snapshot = $snapshot ?? []; $normalized = $this->normalize($snapshot, $policyType, $platform); return $this->defaultNormalizer->flattenNormalizedForDiff($normalized); } private function buildFeatureUpdateBlock(array $snapshot): ?array { $entries = []; $displayName = Arr::get($snapshot, 'displayName'); if (is_string($displayName) && $displayName !== '') { $entries[] = ['key' => 'Name', 'value' => $displayName]; } $version = Arr::get($snapshot, 'featureUpdateVersion'); if (is_string($version) && $version !== '') { $entries[] = ['key' => 'Feature update version', 'value' => $version]; } $rollout = Arr::get($snapshot, 'rolloutSettings'); if (is_array($rollout)) { $start = $this->formatDateTime($rollout['offerStartDateTimeInUTC'] ?? null); $end = $this->formatDateTime($rollout['offerEndDateTimeInUTC'] ?? null); $interval = $rollout['offerIntervalInDays'] ?? null; if ($start !== null) { $entries[] = ['key' => 'Rollout start', 'value' => $start]; } if ($end !== null) { $entries[] = ['key' => 'Rollout end', 'value' => $end]; } if ($interval !== null) { $entries[] = ['key' => 'Rollout interval (days)', 'value' => $interval]; } } if ($entries === []) { return null; } return [ 'type' => 'keyValue', 'title' => 'Feature Update Profile', 'entries' => $entries, ]; } private function formatDateTime(mixed $value): ?string { if (! is_string($value) || $value === '') { return null; } try { return CarbonImmutable::parse($value)->toDateTimeString(); } catch (\Throwable) { return $value; } } }