$config */ public function __construct( private readonly array $config = [], ) { } /** * @return string[] */ public function getConversationProductPatterns(): array { return $this->stringList('conversation_product_patterns'); } /** * @return array */ public function getFocusTermPatterns(): array { return $this->stringMap('focus_term_patterns'); } /** * @return string[] */ private function stringList(string $path): array { $value = $this->value($path); if (!is_array($value)) { throw $this->invalid($path, 'must be a list of non-empty strings'); } $out = []; foreach ($value as $item) { if (!is_scalar($item)) { continue; } $item = trim((string) $item); if ($item !== '' && !in_array($item, $out, true)) { $out[] = $item; } } if ($out === []) { throw $this->invalid($path, 'must contain at least one non-empty string'); } return $out; } /** * @return array */ private function stringMap(string $path): array { $value = $this->value($path); if (!is_array($value)) { throw $this->invalid($path, 'must be a map of non-empty strings'); } $out = []; foreach ($value as $key => $item) { if (!is_scalar($key) || !is_scalar($item)) { continue; } $cleanKey = trim((string) $key); $cleanValue = trim((string) $item); if ($cleanKey !== '' && $cleanValue !== '') { $out[$cleanKey] = $cleanValue; } } if ($out === []) { throw $this->invalid($path, 'must contain at least one non-empty mapping'); } return $out; } private function value(string $path): mixed { $current = $this->config; foreach (explode('.', $path) as $segment) { if (!is_array($current) || !array_key_exists($segment, $current)) { throw $this->missing($path); } $current = $current[$segment]; } return $current; } private function missing(string $path): InvalidArgumentException { return new InvalidArgumentException(sprintf('RetrieX commerce reference resolver config "%s" is missing.', $path)); } private function invalid(string $path, string $reason): InvalidArgumentException { return new InvalidArgumentException(sprintf('RetrieX commerce reference resolver config "%s" %s.', $path, $reason)); } }