fix p55
This commit is contained in:
@@ -12,6 +12,7 @@ final class AgentRunnerConfig
|
||||
public function __construct(
|
||||
private readonly array $config = [],
|
||||
private readonly ?DomainVocabularyConfig $vocabulary = null,
|
||||
private readonly ?GenreConfig $genreConfig = null,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -290,6 +291,27 @@ final class AgentRunnerConfig
|
||||
);
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private function genreStringList(string $path): array
|
||||
{
|
||||
return $this->genreConfig?->getValueStringList($path) ?? [];
|
||||
}
|
||||
|
||||
private function genreString(string $path): string
|
||||
{
|
||||
return $this->genreConfig?->getValueString($path) ?? '';
|
||||
}
|
||||
|
||||
private function genreBool(string $path): ?bool
|
||||
{
|
||||
return $this->genreConfig?->getValueBool($path);
|
||||
}
|
||||
|
||||
private function genreInt(string $path): ?int
|
||||
{
|
||||
return $this->genreConfig?->getValueInt($path);
|
||||
}
|
||||
|
||||
private function getRequiredInt(string $key): int
|
||||
{
|
||||
$value = $this->requiredValue($key);
|
||||
@@ -749,37 +771,44 @@ final class AgentRunnerConfig
|
||||
|
||||
public function isDirectShopResultAnswerEnabled(): bool
|
||||
{
|
||||
return $this->getRequiredBool('shop_runtime.direct_answer.enabled');
|
||||
return $this->genreBool('shop_query_runtime.direct_answer.enabled')
|
||||
?? $this->getRequiredBool('shop_runtime.direct_answer.enabled');
|
||||
}
|
||||
|
||||
public function getDirectShopResultAnswerMaxResults(): int
|
||||
{
|
||||
return $this->getRequiredInt('shop_runtime.direct_answer.max_results');
|
||||
return $this->genreInt('shop_query_runtime.direct_answer.max_results')
|
||||
?? $this->getRequiredInt('shop_runtime.direct_answer.max_results');
|
||||
}
|
||||
|
||||
public function getDirectShopResultAnswerIntro(): string
|
||||
{
|
||||
return $this->getRequiredString('shop_runtime.direct_answer.intro');
|
||||
return $this->genreString('shop_query_runtime.direct_answer.intro')
|
||||
?: $this->getRequiredString('shop_runtime.direct_answer.intro');
|
||||
}
|
||||
|
||||
public function getDirectShopResultAnswerNoResultsMessage(): string
|
||||
{
|
||||
return $this->getRequiredString('shop_runtime.direct_answer.no_results');
|
||||
return $this->genreString('shop_query_runtime.direct_answer.no_results')
|
||||
?: $this->getRequiredString('shop_runtime.direct_answer.no_results');
|
||||
}
|
||||
|
||||
public function getDirectShopResultAnswerSortedByLengthNote(): string
|
||||
{
|
||||
return $this->getRequiredString('shop_runtime.direct_answer.sorted_by_length_note');
|
||||
return $this->genreString('shop_query_runtime.direct_answer.sorted_by_length_note')
|
||||
?: $this->getRequiredString('shop_runtime.direct_answer.sorted_by_length_note');
|
||||
}
|
||||
|
||||
public function getDirectShopResultAnswerMinLengthFilterNote(): string
|
||||
{
|
||||
return $this->getRequiredString('shop_runtime.direct_answer.min_length_filter_note');
|
||||
return $this->genreString('shop_query_runtime.direct_answer.min_length_filter_note')
|
||||
?: $this->getRequiredString('shop_runtime.direct_answer.min_length_filter_note');
|
||||
}
|
||||
|
||||
public function getDirectShopResultAnswerMaxLengthFilterNote(): string
|
||||
{
|
||||
return $this->getRequiredString('shop_runtime.direct_answer.max_length_filter_note');
|
||||
return $this->genreString('shop_query_runtime.direct_answer.max_length_filter_note')
|
||||
?: $this->getRequiredString('shop_runtime.direct_answer.max_length_filter_note');
|
||||
}
|
||||
|
||||
public function getNoLlmFallbackMaxShopResults(): int
|
||||
@@ -1073,7 +1102,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopQueryContextUsageReferentialTerms(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.context_resolution.context_usage.referential_terms');
|
||||
return $this->genreStringList('context_resolution.referential_terms.terms')
|
||||
?: $this->getRequiredStringList('shop_runtime.context_resolution.context_usage.referential_terms');
|
||||
}
|
||||
|
||||
public function isShopQueryCurrentInputPreservationEnabled(): bool
|
||||
@@ -1129,7 +1159,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopQueryProductAttributeCleanupComparativeConstraintPatterns(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.attribute_cleanup.comparative_constraint_patterns');
|
||||
return $this->genreStringList('product_attributes.direct_attribute_cleanup.comparative_constraint_patterns')
|
||||
?: $this->getRequiredStringList('shop_runtime.attribute_cleanup.comparative_constraint_patterns');
|
||||
}
|
||||
|
||||
public function isShopQueryStopwordCleanupEnabled(): bool
|
||||
@@ -1147,7 +1178,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopQueryStopwordCleanupTerms(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.query_cleanup.stopword_cleanup.terms');
|
||||
return $this->genreStringList('shop_query_runtime.stopword_cleanup.terms')
|
||||
?: $this->getRequiredStringList('shop_runtime.query_cleanup.stopword_cleanup.terms');
|
||||
}
|
||||
|
||||
public function isDirectShopResultGuardEnabled(): bool
|
||||
@@ -1170,7 +1202,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getDirectShopResultGuardCompoundPrefixTerms(): array
|
||||
{
|
||||
return $this->getOptionalStringList('shop_runtime.result_identity.compound_prefix_match.terms');
|
||||
return $this->genreStringList('shop_query_runtime.compound_prefix_match.terms')
|
||||
?: $this->getOptionalStringList('shop_runtime.result_identity.compound_prefix_match.terms');
|
||||
}
|
||||
|
||||
public function isDirectShopResultGuardPrimaryIdentityRepairEnabled(): bool
|
||||
@@ -1188,7 +1221,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getDirectShopResultGuardPrimaryIdentityRepairStopTerms(): array
|
||||
{
|
||||
return $this->getOptionalStringList('shop_runtime.result_identity.primary_identity_repair.stop_terms');
|
||||
return $this->genreStringList('shop_query_runtime.primary_identity_repair.stop_terms')
|
||||
?: $this->getOptionalStringList('shop_runtime.result_identity.primary_identity_repair.stop_terms');
|
||||
}
|
||||
|
||||
public function isShopResultLengthSortEnabled(): bool
|
||||
@@ -1201,7 +1235,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopResultLengthSortTriggerPatterns(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.answer_constraints.length_sort.trigger_patterns');
|
||||
return $this->genreStringList('product_attributes.numeric_length_constraints.length_sort.trigger_patterns')
|
||||
?: $this->getRequiredStringList('shop_runtime.answer_constraints.length_sort.trigger_patterns');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1209,7 +1244,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopResultLengthSortValuePatterns(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.answer_constraints.length_sort.value_patterns');
|
||||
return $this->genreStringList('product_attributes.numeric_length_constraints.length_sort.value_patterns')
|
||||
?: $this->getRequiredStringList('shop_runtime.answer_constraints.length_sort.value_patterns');
|
||||
}
|
||||
|
||||
public function isShopResultLengthFilterEnabled(): bool
|
||||
@@ -1222,7 +1258,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopResultMinLengthFilterPatterns(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.answer_constraints.length_filter.min_patterns');
|
||||
return $this->genreStringList('product_attributes.numeric_length_constraints.length_filter.min_patterns')
|
||||
?: $this->getRequiredStringList('shop_runtime.answer_constraints.length_filter.min_patterns');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1230,7 +1267,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopResultMaxLengthFilterPatterns(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.answer_constraints.length_filter.max_patterns');
|
||||
return $this->genreStringList('product_attributes.numeric_length_constraints.length_filter.max_patterns')
|
||||
?: $this->getRequiredStringList('shop_runtime.answer_constraints.length_filter.max_patterns');
|
||||
}
|
||||
|
||||
public function getShopPromptIntro(): string
|
||||
@@ -1323,7 +1361,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopQueryMetaOnlyTerms(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.context_resolution.meta_query_guard.meta_only_terms');
|
||||
return $this->genreStringList('context_resolution.meta_query_guard.meta_only_terms')
|
||||
?: $this->getRequiredStringList('shop_runtime.context_resolution.meta_query_guard.meta_only_terms');
|
||||
}
|
||||
|
||||
public function isShopQueryContextFallbackEnabled(): bool
|
||||
@@ -1356,7 +1395,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopQueryContextFallbackFilterTerms(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.context_resolution.meta_query_guard.context_fallback_filter_terms');
|
||||
return $this->genreStringList('context_resolution.meta_query_guard.context_fallback_filter_terms')
|
||||
?: $this->getRequiredStringList('shop_runtime.context_resolution.meta_query_guard.context_fallback_filter_terms');
|
||||
}
|
||||
|
||||
public function isShopQueryContextAnchorEnrichmentEnabled(): bool
|
||||
@@ -1385,12 +1425,14 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopQueryContextAnchorEnrichmentPatterns(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.context_resolution.history_anchor_enrichment.anchor_patterns');
|
||||
return $this->genreStringList('context_resolution.history_anchor_enrichment.anchor_patterns')
|
||||
?: $this->getRequiredStringList('shop_runtime.context_resolution.history_anchor_enrichment.anchor_patterns');
|
||||
}
|
||||
|
||||
public function getShopQueryContextAnchorEnrichmentTemplate(): string
|
||||
{
|
||||
return $this->getRequiredString('shop_runtime.context_resolution.history_anchor_enrichment.template');
|
||||
return $this->genreString('context_resolution.history_anchor_enrichment.template')
|
||||
?: $this->getRequiredString('shop_runtime.context_resolution.history_anchor_enrichment.template');
|
||||
}
|
||||
public function isShopQueryRagAnchorEnrichmentEnabled(): bool
|
||||
{
|
||||
@@ -1437,7 +1479,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopQueryRagAnchorEnrichmentNumericFocusPatterns(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.context_resolution.rag_anchor_enrichment.numeric_focus_patterns');
|
||||
return $this->genreStringList('context_resolution.rag_anchor_enrichment.numeric_focus_patterns')
|
||||
?: $this->getRequiredStringList('shop_runtime.context_resolution.rag_anchor_enrichment.numeric_focus_patterns');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1445,7 +1488,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopQueryRagAnchorEnrichmentProductTitlePatterns(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.context_resolution.rag_anchor_enrichment.product_title_patterns');
|
||||
return $this->genreStringList('context_resolution.rag_anchor_enrichment.product_title_patterns')
|
||||
?: $this->getRequiredStringList('shop_runtime.context_resolution.rag_anchor_enrichment.product_title_patterns');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1453,7 +1497,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopQueryRagAnchorEnrichmentAnchorBonusPatterns(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.context_resolution.rag_anchor_enrichment.anchor_bonus_patterns');
|
||||
return $this->genreStringList('context_resolution.rag_anchor_enrichment.anchor_bonus_patterns')
|
||||
?: $this->getRequiredStringList('shop_runtime.context_resolution.rag_anchor_enrichment.anchor_bonus_patterns');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1461,7 +1506,8 @@ final class AgentRunnerConfig
|
||||
*/
|
||||
public function getShopQueryRagAnchorEnrichmentSubjectTerms(): array
|
||||
{
|
||||
return $this->getRequiredStringList('shop_runtime.context_resolution.rag_anchor_enrichment.subject_terms');
|
||||
return $this->genreStringList('context_resolution.rag_anchor_enrichment.subject_terms')
|
||||
?: $this->getRequiredStringList('shop_runtime.context_resolution.rag_anchor_enrichment.subject_terms');
|
||||
}
|
||||
|
||||
public function getShopQueryTranslationReplacements(string $language): array
|
||||
|
||||
@@ -9,26 +9,31 @@ final class CommerceIntentConfig
|
||||
/**
|
||||
* @param array<string, mixed> $config
|
||||
*/
|
||||
public function __construct(private readonly array $config = [])
|
||||
{
|
||||
public function __construct(
|
||||
private readonly array $config = [],
|
||||
private readonly ?GenreConfig $genreConfig = null,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
public function getStrongSignalsList(): array
|
||||
{
|
||||
return $this->requiredStringList('strong_signals');
|
||||
return $this->genreStringList('intent_and_routing.commerce_intent.strong_signals')
|
||||
?: $this->requiredStringList('strong_signals');
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
public function getAdvisorySignals(): array
|
||||
{
|
||||
return $this->requiredStringList('advisory_signals');
|
||||
return $this->genreStringList('intent_and_routing.commerce_intent.advisory_signals')
|
||||
?: $this->requiredStringList('advisory_signals');
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
public function getAdvisoryProductSelectionPatterns(): array
|
||||
{
|
||||
return $this->requiredStringList('advisory_product_selection_patterns');
|
||||
return $this->genreStringList('intent_and_routing.commerce_intent.advisory_product_selection_patterns')
|
||||
?: $this->requiredStringList('advisory_product_selection_patterns');
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
@@ -54,6 +59,12 @@ final class CommerceIntentConfig
|
||||
return $this->requiredStringList('technical_factual_knowledge.fact_patterns');
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private function genreStringList(string $path): array
|
||||
{
|
||||
return $this->genreConfig?->getValueStringList($path) ?? [];
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
public function getPriceTerms(): array
|
||||
{
|
||||
@@ -68,7 +79,8 @@ final class CommerceIntentConfig
|
||||
/** @return string[] */
|
||||
public function getColorTerms(): array
|
||||
{
|
||||
return $this->requiredStringList('color_terms');
|
||||
return $this->genreStringList('product_attributes.size_and_color_terms.color_terms')
|
||||
?: $this->requiredStringList('color_terms');
|
||||
}
|
||||
|
||||
public function getColorPattern(): string
|
||||
@@ -79,7 +91,8 @@ final class CommerceIntentConfig
|
||||
/** @return string[] */
|
||||
public function getSizeTokenTerms(): array
|
||||
{
|
||||
return $this->requiredStringList('size_token_terms');
|
||||
return $this->genreStringList('product_attributes.size_and_color_terms.size_token_terms')
|
||||
?: $this->requiredStringList('size_token_terms');
|
||||
}
|
||||
|
||||
public function getSizeTokenPattern(): string
|
||||
@@ -90,7 +103,8 @@ final class CommerceIntentConfig
|
||||
/** @return string[] */
|
||||
public function getSizeTerms(): array
|
||||
{
|
||||
return $this->requiredStringList('size_terms');
|
||||
return $this->genreStringList('product_attributes.size_and_color_terms.size_terms')
|
||||
?: $this->requiredStringList('size_terms');
|
||||
}
|
||||
|
||||
public function getSizePattern(): string
|
||||
@@ -114,7 +128,8 @@ final class CommerceIntentConfig
|
||||
/** @return string[] */
|
||||
public function getExplicitCommerceIntentPatterns(): array
|
||||
{
|
||||
return $this->requiredStringList('explicit_commerce_intent_patterns');
|
||||
return $this->genreStringList('intent_and_routing.commerce_intent.explicit_commerce_intent_patterns')
|
||||
?: $this->requiredStringList('explicit_commerce_intent_patterns');
|
||||
}
|
||||
|
||||
public function getSkuLikePattern(): string
|
||||
|
||||
@@ -14,6 +14,7 @@ final class CommerceQueryParserConfig
|
||||
public function __construct(
|
||||
private readonly array $config = [],
|
||||
private readonly ?DomainVocabularyConfig $vocabulary = null,
|
||||
private readonly ?GenreConfig $genreConfig = null,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -26,7 +27,8 @@ final class CommerceQueryParserConfig
|
||||
/** @return string[] */
|
||||
public function getKnownBrands(): array
|
||||
{
|
||||
return $this->stringList('known_brands');
|
||||
return $this->genreStringList('brands_and_canonical_terms.known_brands.terms')
|
||||
?: $this->stringList('known_brands');
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
@@ -61,6 +63,18 @@ final class CommerceQueryParserConfig
|
||||
return $this->stringList('search_control_tokens');
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private function genreStringList(string $path): array
|
||||
{
|
||||
return $this->genreConfig?->getValueStringList($path) ?? [];
|
||||
}
|
||||
|
||||
/** @return array<string, string> */
|
||||
private function genreStringMap(string $path): array
|
||||
{
|
||||
return $this->genreConfig?->getValueStringMap($path) ?? [];
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private function whitespacePreservingStringList(string $path): array
|
||||
{
|
||||
@@ -99,7 +113,8 @@ final class CommerceQueryParserConfig
|
||||
/** @return array<string, string> */
|
||||
public function getSearchTokenCanonicalMap(): array
|
||||
{
|
||||
return $this->stringMap('search_token_canonical_map');
|
||||
return $this->genreStringMap('brands_and_canonical_terms.canonical_terms.map')
|
||||
?: $this->stringMap('search_token_canonical_map');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,13 +6,57 @@ namespace App\Config;
|
||||
|
||||
final class DomainVocabularyConfig
|
||||
{
|
||||
public function __construct(private readonly array $config = [])
|
||||
{
|
||||
private const CLASS_GENRE_VALUE_PATHS = [
|
||||
'device' => 'product_roles.primary_product_terms.terms',
|
||||
'accessory' => 'product_roles.accessory_product_terms.terms',
|
||||
'requested_accessory_code_terms' => 'product_roles.requested_accessory_code_terms.terms',
|
||||
'direct_product_attribute_stop_terms' => 'product_attributes.direct_attribute_cleanup.stop_terms',
|
||||
'input_normalization_fuzzy_routing_terms' => 'intent_and_routing.fuzzy_routing_terms.terms',
|
||||
'agent_no_llm_main_device_request_keywords' => 'product_roles.no_llm_fallback_terms.main_device_request_keywords',
|
||||
'agent_no_llm_accessory_product_keywords' => 'product_roles.no_llm_fallback_terms.accessory_product_keywords',
|
||||
'agent_shop_current_input_preservation_terms' => 'shop_query_runtime.current_input_preservation_terms.terms',
|
||||
'agent_shop_context_anchor_trigger_terms' => 'context_resolution.history_anchor_enrichment.trigger_terms',
|
||||
];
|
||||
|
||||
private const VIEW_GENRE_VALUE_PATHS = [
|
||||
'shop.device_query' => 'product_roles.shop_views.device_query_terms',
|
||||
'shop.accessory_query' => 'product_roles.shop_views.accessory_query_terms',
|
||||
'shop.device_product' => 'product_roles.shop_views.device_product_terms',
|
||||
'shop.accessory_product' => 'product_roles.shop_views.accessory_product_terms',
|
||||
'shop.device_focus' => 'product_roles.shop_views.device_focus_terms',
|
||||
'shop.accessory_focus' => 'product_roles.shop_views.accessory_focus_terms',
|
||||
'prompt.main_device_request_keywords' => 'product_roles.prompt_views.main_device_request_keywords',
|
||||
'prompt.accessory_request_keywords' => 'product_roles.prompt_views.accessory_request_keywords',
|
||||
'prompt.main_device_product_keywords' => 'product_roles.prompt_views.main_device_product_keywords',
|
||||
'prompt.accessory_product_keywords' => 'product_roles.prompt_views.accessory_product_keywords',
|
||||
'search_repair.direct_product_type_terms' => 'product_attributes.direct_attribute_cleanup.product_type_terms',
|
||||
'search_repair.direct_product_attribute_stop_terms' => 'product_attributes.direct_attribute_cleanup.stop_terms',
|
||||
'search_repair.requested_accessory_code_terms' => 'product_roles.requested_accessory_code_terms.terms',
|
||||
'agent.rag_evidence_guard.accessory_lookup_guard_terms' => 'result_identity_and_answer_policy.measurement_evidence_guard_terms.accessory_lookup_guard_terms',
|
||||
'agent.rag_evidence_guard.accessory_lookup_passthrough_terms' => 'result_identity_and_answer_policy.measurement_evidence_guard_terms.accessory_lookup_passthrough_terms',
|
||||
'agent.rag_evidence_guard.generic_positive_context_terms' => 'result_identity_and_answer_policy.measurement_evidence_guard_terms.generic_positive_context_terms',
|
||||
'agent.rag_evidence_guard.generic_negative_context_terms' => 'result_identity_and_answer_policy.measurement_evidence_guard_terms.generic_negative_context_terms',
|
||||
];
|
||||
|
||||
private const MAP_GENRE_VALUE_PATHS = [
|
||||
'shop.accessory_focus_variants' => 'brands_and_canonical_terms.accessory_focus_variants.map',
|
||||
'agent.rag_evidence_guard.synonyms' => 'brands_and_canonical_terms.rag_evidence_synonyms.map',
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
private readonly array $config = [],
|
||||
private readonly ?GenreConfig $genreConfig = null,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
public function view(string $path, array $fallback = []): array
|
||||
{
|
||||
$genreTerms = $this->genreStringListForView($path);
|
||||
if ($genreTerms !== []) {
|
||||
return $genreTerms;
|
||||
}
|
||||
|
||||
$definition = $this->value('views.' . $path, null);
|
||||
if (!is_array($definition)) {
|
||||
return $this->uniqueStringList($fallback);
|
||||
@@ -35,12 +79,22 @@ final class DomainVocabularyConfig
|
||||
/** @return string[] */
|
||||
public function domainClass(string $name): array
|
||||
{
|
||||
$genreTerms = $this->genreStringListForClass($name);
|
||||
if ($genreTerms !== []) {
|
||||
return $genreTerms;
|
||||
}
|
||||
|
||||
return $this->stringList('classes.' . $name, []);
|
||||
}
|
||||
|
||||
/** @return array<string, string[]> */
|
||||
public function map(string $path, array $fallback = []): array
|
||||
{
|
||||
$genreMap = $this->genreStringListMapForMap($path);
|
||||
if ($genreMap !== []) {
|
||||
return $genreMap;
|
||||
}
|
||||
|
||||
$value = $this->value('maps.' . $path, null);
|
||||
if (!is_array($value)) {
|
||||
return $this->uniqueStringListMap($fallback);
|
||||
@@ -114,6 +168,41 @@ final class DomainVocabularyConfig
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private function genreStringListForClass(string $name): array
|
||||
{
|
||||
if ($this->genreConfig === null || !isset(self::CLASS_GENRE_VALUE_PATHS[$name])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->genreConfig->getValueStringList(self::CLASS_GENRE_VALUE_PATHS[$name]);
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private function genreStringListForView(string $path): array
|
||||
{
|
||||
if ($this->genreConfig === null || !isset(self::VIEW_GENRE_VALUE_PATHS[$path])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->genreConfig->getValueStringList(self::VIEW_GENRE_VALUE_PATHS[$path]);
|
||||
}
|
||||
|
||||
/** @return array<string, string[]> */
|
||||
private function genreStringListMapForMap(string $path): array
|
||||
{
|
||||
if ($this->genreConfig === null || !isset(self::MAP_GENRE_VALUE_PATHS[$path])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$value = $this->genreConfig->getValueArray(self::MAP_GENRE_VALUE_PATHS[$path]);
|
||||
if ($value === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->stringListMapWithAliases($value);
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private function stringList(string $path, array $fallback): array
|
||||
{
|
||||
|
||||
@@ -64,6 +64,87 @@ final class GenreConfig
|
||||
return is_array($groupValues) ? $groupValues : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a non-empty string list from the central single-genre value surface.
|
||||
*
|
||||
* The path is relative to `configuration_values`, for example
|
||||
* `product_roles.primary_product_terms.terms`.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getValueStringList(string $path): array
|
||||
{
|
||||
return $this->uniqueStringList($this->value('configuration_values.' . $path, []));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a non-empty scalar string map from the central single-genre value surface.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getValueStringMap(string $path): array
|
||||
{
|
||||
$value = $this->value('configuration_values.' . $path, []);
|
||||
|
||||
return is_array($value) ? $this->uniqueStringMap($value) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a raw map/list value from the central single-genre value surface.
|
||||
*
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
public function getValueArray(string $path): array
|
||||
{
|
||||
$value = $this->value('configuration_values.' . $path, []);
|
||||
|
||||
return is_array($value) ? $value : [];
|
||||
}
|
||||
|
||||
public function getValueString(string $path): string
|
||||
{
|
||||
$value = $this->value('configuration_values.' . $path, null);
|
||||
if (!is_scalar($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return trim((string) $value);
|
||||
}
|
||||
|
||||
public function getValueBool(string $path): ?bool
|
||||
{
|
||||
$value = $this->value('configuration_values.' . $path, null);
|
||||
if (is_bool($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (is_scalar($value)) {
|
||||
$normalized = strtolower(trim((string) $value));
|
||||
if (in_array($normalized, ['1', 'true', 'yes', 'on'], true)) {
|
||||
return true;
|
||||
}
|
||||
if (in_array($normalized, ['0', 'false', 'no', 'off'], true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getValueInt(string $path): ?int
|
||||
{
|
||||
$value = $this->value('configuration_values.' . $path, null);
|
||||
if (is_int($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (is_string($value) && preg_match('/^-?\d+$/', trim($value)) === 1) {
|
||||
return (int) trim($value);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
@@ -82,6 +163,47 @@ final class GenreConfig
|
||||
return trim((string) $value);
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private function uniqueStringList(mixed $value): array
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$out = [];
|
||||
foreach ($value as $item) {
|
||||
if (!is_scalar($item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$item = trim((string) $item);
|
||||
if ($item !== '' && !in_array($item, $out, true)) {
|
||||
$out[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/** @return array<string, string> */
|
||||
private function uniqueStringMap(array $value): array
|
||||
{
|
||||
$out = [];
|
||||
foreach ($value as $key => $mappedValue) {
|
||||
if (!is_scalar($key) || !is_scalar($mappedValue)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$cleanKey = trim((string) $key);
|
||||
$cleanValue = trim((string) $mappedValue);
|
||||
if ($cleanKey !== '' && $cleanValue !== '') {
|
||||
$out[$cleanKey] = $cleanValue;
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
private function value(string $path, mixed $fallback): mixed
|
||||
{
|
||||
$current = $this->config;
|
||||
|
||||
@@ -15,8 +15,10 @@ final readonly class QueryEnricherConfig
|
||||
/**
|
||||
* @param array<string, mixed> $config
|
||||
*/
|
||||
public function __construct(private array $config)
|
||||
{
|
||||
public function __construct(
|
||||
private array $config,
|
||||
private readonly ?GenreConfig $genreConfig = null,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,7 +41,10 @@ final readonly class QueryEnricherConfig
|
||||
public function getEnrichQueryList(): array
|
||||
{
|
||||
$normalized = [];
|
||||
$rules = $this->requiredArray('rules');
|
||||
$rules = $this->genreConfig?->getValueArray('brands_and_canonical_terms.query_enrichment_rules.rules') ?? [];
|
||||
if ($rules === []) {
|
||||
$rules = $this->requiredArray('rules');
|
||||
}
|
||||
|
||||
foreach ($rules as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
|
||||
Reference in New Issue
Block a user