}> */ public static function between(PresetBook $before, PresetBook $after): array { $old = $before->data(); $new = $after->data(); $rows = []; foreach ([PresetScope::MODULE, PresetScope::GROUP] as $kind) { $names = array_unique(array_merge(array_keys($old[$kind] ?? []), array_keys($new[$kind] ?? []))); sort($names); foreach ($names as $name) { $was = $old[$kind][$name] ?? ['default' => '', 'items' => []]; $is = $new[$kind][$name] ?? ['default' => '', 'items' => []]; array_push($rows, ...self::items($kind, (string) $name, $was['items'], $is['items'])); array_push($rows, ...self::defaults($kind, (string) $name, $was, $is)); } } return $rows; } /** * @param array> $was * @param array> $is * @return list> */ private static function items(string $kind, string $scope, array $was, array $is): array { $ids = array_unique(array_merge(array_keys($was), array_keys($is))); sort($ids); $rows = []; foreach ($ids as $id) { $key = (string) $id; $before = $was[$key] ?? null; $after = $is[$key] ?? null; if ($before === null || $after === null) { $rows[] = self::row($kind, $scope, $key, $after ?? $before, $before === null ? 'added' : 'removed'); continue; } $fields = self::changedFields($before, $after); if ($fields !== []) { $rows[] = self::row($kind, $scope, $key, $after, 'changed') + ['fields' => $fields]; } } return $rows; } /** * @param array{default: string, items: array>} $was * @param array{default: string, items: array>} $is * @return list> */ private static function defaults(string $kind, string $scope, array $was, array $is): array { if ($was['default'] === $is['default']) { return []; } if ($is['default'] === '') { $gone = $was['items'][$was['default']] ?? null; return [self::row($kind, $scope, $was['default'], $gone, 'default_cleared')]; } $item = $is['items'][$is['default']] ?? null; return [self::row($kind, $scope, $is['default'], $item, 'default_set')]; } /** * @param array $before * @param array $after * @return list */ private static function changedFields(array $before, array $after): array { $keys = array_diff(array_unique(array_merge(array_keys($before), array_keys($after))), self::DERIVED); $fields = []; foreach ($keys as $key) { $was = $before[$key] ?? null; $is = $after[$key] ?? null; if ($was != $is) { // phpcs:ignore Universal.Operators.StrictComparisons $fields[] = (string) $key; } } sort($fields); return $fields; } /** * @param array|null $item * @return array{kind: string, scope: string, id: string, name: string, action: string} */ private static function row(string $kind, string $scope, string $id, ?array $item, string $action): array { return [ 'kind' => $kind, 'scope' => $scope, 'id' => $id, 'name' => is_string($item['name'] ?? null) ? $item['name'] : $id, 'action' => $action, ]; } }