fix(exclusions): Corregir Renderers que ignoraban sistema de exclusiones
Plan 99.11 - Correcciones críticas: - FooterRenderer: Añadir PageVisibilityHelper::shouldShow() - HeroSectionRenderer: Añadir PageVisibilityHelper::shouldShow() - AdsensePlacementRenderer: Añadir PageVisibilityHelper::shouldShow() Mejoras adicionales: - UrlPatternExclusion: Soporte wildcards (*sct* → regex) - ExclusionFormPartial: UI mejorada con placeholders - ComponentConfiguration: Grupo _exclusions validado - 12 FormBuilders: Integración UI de exclusiones - 12 FieldMappers: Mapeo campos de exclusión Verificado: Footer oculto en post con categoría excluida SCT 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,9 @@ final readonly class ComponentConfiguration
|
||||
|
||||
// Sistema de visibilidad por página
|
||||
'_page_visibility', // Visibilidad por tipo de página (home, posts, pages, archives, search)
|
||||
|
||||
// Sistema de exclusiones (Plan 99.11)
|
||||
'_exclusions', // Reglas de exclusión por categoría, post ID, URL pattern
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -86,10 +86,21 @@ final class UrlPatternExclusion extends ExclusionRule
|
||||
}
|
||||
|
||||
/**
|
||||
* Evalua coincidencia por substring
|
||||
* Evalua coincidencia por substring o wildcard
|
||||
*
|
||||
* Soporta wildcards simples:
|
||||
* - `*sct*` coincide con URLs que contengan "sct"
|
||||
* - `*` se convierte a `.*` en regex
|
||||
* - Sin wildcards: busca substring literal
|
||||
*/
|
||||
private function matchesSubstring(string $pattern, string $requestUri, string $url): bool
|
||||
{
|
||||
// Detectar si tiene wildcards (*)
|
||||
if (str_contains($pattern, '*')) {
|
||||
return $this->matchesWildcard($pattern, $requestUri, $url);
|
||||
}
|
||||
|
||||
// Substring literal
|
||||
if ($requestUri !== '' && str_contains($requestUri, $pattern)) {
|
||||
return true;
|
||||
}
|
||||
@@ -101,6 +112,31 @@ final class UrlPatternExclusion extends ExclusionRule
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evalua coincidencia con patron wildcard
|
||||
*
|
||||
* Convierte wildcards (*) a regex (.*)
|
||||
*/
|
||||
private function matchesWildcard(string $pattern, string $requestUri, string $url): bool
|
||||
{
|
||||
// Convertir wildcard a regex:
|
||||
// 1. Escapar caracteres especiales de regex (excepto *)
|
||||
// 2. Convertir * a .*
|
||||
$regexPattern = preg_quote($pattern, '#');
|
||||
$regexPattern = str_replace('\\*', '.*', $regexPattern);
|
||||
$regexPattern = '#' . $regexPattern . '#i';
|
||||
|
||||
if ($requestUri !== '' && preg_match($regexPattern, $requestUri) === 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($url !== '' && preg_match($regexPattern, $url) === 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function hasValues(): bool
|
||||
{
|
||||
return !empty($this->urlPatterns);
|
||||
|
||||
@@ -109,28 +109,67 @@ final class WordPressComponentSettingsRepository implements ComponentSettingsRep
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* Implementa UPSERT: si el registro no existe, lo crea; si existe, lo actualiza.
|
||||
* Esto es necesario para grupos especiales como _page_visibility y _exclusions
|
||||
* que no vienen del schema JSON.
|
||||
*/
|
||||
public function saveFieldValue(string $componentName, string $groupName, string $attributeName, mixed $value): bool
|
||||
{
|
||||
// Serializar valor
|
||||
$serializedValue = $this->serializeValue($value);
|
||||
|
||||
// Intentar actualizar
|
||||
$result = $this->wpdb->update(
|
||||
$this->tableName,
|
||||
['attribute_value' => $serializedValue],
|
||||
[
|
||||
'component_name' => $componentName,
|
||||
'group_name' => $groupName,
|
||||
'attribute_name' => $attributeName
|
||||
],
|
||||
['%s'],
|
||||
['%s', '%s', '%s']
|
||||
);
|
||||
// Verificar si el registro existe
|
||||
$exists = $this->fieldExists($componentName, $groupName, $attributeName);
|
||||
|
||||
if ($exists) {
|
||||
// UPDATE
|
||||
$result = $this->wpdb->update(
|
||||
$this->tableName,
|
||||
['attribute_value' => $serializedValue],
|
||||
[
|
||||
'component_name' => $componentName,
|
||||
'group_name' => $groupName,
|
||||
'attribute_name' => $attributeName
|
||||
],
|
||||
['%s'],
|
||||
['%s', '%s', '%s']
|
||||
);
|
||||
} else {
|
||||
// INSERT - crear nuevo registro
|
||||
$result = $this->wpdb->insert(
|
||||
$this->tableName,
|
||||
[
|
||||
'component_name' => $componentName,
|
||||
'group_name' => $groupName,
|
||||
'attribute_name' => $attributeName,
|
||||
'attribute_value' => $serializedValue
|
||||
],
|
||||
['%s', '%s', '%s', '%s']
|
||||
);
|
||||
}
|
||||
|
||||
return $result !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifica si un campo existe en la BD
|
||||
*/
|
||||
private function fieldExists(string $componentName, string $groupName, string $attributeName): bool
|
||||
{
|
||||
$sql = $this->wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM {$this->tableName}
|
||||
WHERE component_name = %s
|
||||
AND group_name = %s
|
||||
AND attribute_name = %s",
|
||||
$componentName,
|
||||
$groupName,
|
||||
$attributeName
|
||||
);
|
||||
|
||||
return (int) $this->wpdb->get_var($sql) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user