diff --git a/Admin/CtaBoxSidebar/Infrastructure/FieldMapping/CtaBoxSidebarFieldMapper.php b/Admin/CtaBoxSidebar/Infrastructure/FieldMapping/CtaBoxSidebarFieldMapper.php index 0a544154..fb749230 100644 --- a/Admin/CtaBoxSidebar/Infrastructure/FieldMapping/CtaBoxSidebarFieldMapper.php +++ b/Admin/CtaBoxSidebar/Infrastructure/FieldMapping/CtaBoxSidebarFieldMapper.php @@ -38,6 +38,12 @@ final class CtaBoxSidebarFieldMapper implements FieldMapperInterface 'ctaVisibilityArchives' => ['group' => '_page_visibility', 'attribute' => 'show_on_archives'], 'ctaVisibilitySearch' => ['group' => '_page_visibility', 'attribute' => 'show_on_search'], + // Exclusions (grupo especial _exclusions - Plan 99.11) + 'ctaExclusionsEnabled' => ['group' => '_exclusions', 'attribute' => 'exclusions_enabled'], + 'ctaExcludeCategories' => ['group' => '_exclusions', 'attribute' => 'exclude_categories', 'type' => 'json_array'], + 'ctaExcludePostIds' => ['group' => '_exclusions', 'attribute' => 'exclude_post_ids', 'type' => 'json_array_int'], + 'ctaExcludeUrlPatterns' => ['group' => '_exclusions', 'attribute' => 'exclude_url_patterns', 'type' => 'json_array_lines'], + // Content 'ctaTitle' => ['group' => 'content', 'attribute' => 'title'], 'ctaDescription' => ['group' => 'content', 'attribute' => 'description'], diff --git a/Admin/CtaBoxSidebar/Infrastructure/Ui/CtaBoxSidebarFormBuilder.php b/Admin/CtaBoxSidebar/Infrastructure/Ui/CtaBoxSidebarFormBuilder.php index 08c7840c..5cb18c47 100644 --- a/Admin/CtaBoxSidebar/Infrastructure/Ui/CtaBoxSidebarFormBuilder.php +++ b/Admin/CtaBoxSidebar/Infrastructure/Ui/CtaBoxSidebarFormBuilder.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ROITheme\Admin\CtaBoxSidebar\Infrastructure\Ui; use ROITheme\Admin\Infrastructure\Ui\AdminDashboardRenderer; +use ROITheme\Admin\Shared\Infrastructure\Ui\ExclusionFormPartial; /** * FormBuilder para el CTA Box Sidebar @@ -130,6 +131,13 @@ final class CtaBoxSidebarFormBuilder $html .= ' '; $html .= ' '; + // ============================================= + // Reglas de exclusion avanzadas + // Grupo especial: _exclusions (Plan 99.11) + // ============================================= + $exclusionPartial = new ExclusionFormPartial($this->renderer); + $html .= $exclusionPartial->render($componentId, 'cta'); + $html .= ' '; $html .= ''; diff --git a/Admin/Infrastructure/Services/AdminAssetEnqueuer.php b/Admin/Infrastructure/Services/AdminAssetEnqueuer.php index 936c1aad..60cf84c4 100644 --- a/Admin/Infrastructure/Services/AdminAssetEnqueuer.php +++ b/Admin/Infrastructure/Services/AdminAssetEnqueuer.php @@ -107,6 +107,15 @@ final class AdminAssetEnqueuer true ); + // Script de toggle para exclusiones (Plan 99.11) + wp_enqueue_script( + 'roi-exclusion-toggle', + $this->themeUri . '/Admin/Shared/Infrastructure/Ui/Assets/Js/exclusion-toggle.js', + ['roi-admin-dashboard'], + filemtime(get_template_directory() . '/Admin/Shared/Infrastructure/Ui/Assets/Js/exclusion-toggle.js'), + true + ); + // Pasar variables al JavaScript wp_localize_script( 'roi-admin-dashboard', diff --git a/Admin/Shared/Infrastructure/Api/WordPress/AdminAjaxHandler.php b/Admin/Shared/Infrastructure/Api/WordPress/AdminAjaxHandler.php index f149c328..81734865 100644 --- a/Admin/Shared/Infrastructure/Api/WordPress/AdminAjaxHandler.php +++ b/Admin/Shared/Infrastructure/Api/WordPress/AdminAjaxHandler.php @@ -5,6 +5,7 @@ namespace ROITheme\Admin\Shared\Infrastructure\Api\WordPress; use ROITheme\Shared\Application\UseCases\SaveComponentSettings\SaveComponentSettingsUseCase; use ROITheme\Admin\Shared\Infrastructure\FieldMapping\FieldMapperRegistry; +use ROITheme\Admin\Shared\Infrastructure\Services\ExclusionFieldProcessor; /** * Handler para peticiones AJAX del panel de administracion @@ -73,10 +74,16 @@ final class AdminAjaxHandler /** * Mapea settings de field IDs a grupos/atributos + * + * Soporta tipos especiales para campos de exclusion: + * - json_array: Convierte "a, b, c" a ["a", "b", "c"] + * - json_array_int: Convierte "1, 2, 3" a [1, 2, 3] + * - json_array_lines: Convierte lineas a array */ private function mapSettings(array $settings, array $fieldMapping): array { $mappedSettings = []; + $fieldProcessor = new ExclusionFieldProcessor(); foreach ($settings as $fieldId => $value) { if (!isset($fieldMapping[$fieldId])) { @@ -86,11 +93,17 @@ final class AdminAjaxHandler $mapping = $fieldMapping[$fieldId]; $groupName = $mapping['group']; $attributeName = $mapping['attribute']; + $type = $mapping['type'] ?? null; if (!isset($mappedSettings[$groupName])) { $mappedSettings[$groupName] = []; } + // Procesar valor segun tipo + if ($type !== null && is_string($value)) { + $value = $fieldProcessor->process($value, $type); + } + $mappedSettings[$groupName][$attributeName] = $value; }