$owner) { if (is_int($key)) { $errors[] = '_attribute_ownership must be keyed by stable attribute key'; break; } $attributeKey = AttributeIdentity::slug((string) $key); if ($attributeKey === '') { $errors[] = 'each attribute ownership entry needs a stable key'; break; } if (isset($seenAttributeKeys[$attributeKey])) { $errors[] = 'attribute ownership contains the duplicate stable key ' . $attributeKey; break; } $seenAttributeKeys[$attributeKey] = true; if (!in_array($owner, ['source', 'merchant'], true)) { $errors[] = 'attribute ownership for ' . $attributeKey . ' must be source or merchant'; break; } } } } if (!empty($canonical['_normalization_pending'])) { $errors[] = 'category or attribute normalization requires approval'; } $urls = array_filter($canonical['images'] ?? [], static fn ($url): bool => !wp_http_validate_url((string) $url)); if ($urls) { $errors[] = 'one or more image URLs are invalid'; } return apply_filters('crocoai_dbridge_validation_result', ['errors' => $errors, 'warnings' => $warnings], $canonical); } }