feat(visibility): sistema de visibilidad por tipo de página

- Añadir PageVisibility use case y repositorio
- Implementar PageTypeDetector para detectar home/single/page/archive
- Actualizar FieldMappers con soporte show_on_[page_type]
- Extender FormBuilders con UI de visibilidad por página
- Refactorizar Renderers para evaluar visibilidad dinámica
- Limpiar schemas removiendo campos de visibilidad legacy
- Añadir MigrationCommand para migrar configuraciones existentes
- Implementar adsense-loader.js para carga lazy de ads
- Actualizar front-page.php con nueva estructura
- Extender DIContainer con nuevos servicios

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
FrankZamora
2025-12-03 09:16:34 -06:00
parent 7fb5eda108
commit 8735962f52
66 changed files with 2614 additions and 573 deletions

View File

@@ -95,6 +95,16 @@ final class AdsensePlacementFieldMapper implements FieldMapperInterface
'adsense-placementVignetteReshowEnabled' => ['group' => 'vignette_ads', 'attribute' => 'vignette_reshow_enabled'],
'adsense-placementVignetteReshowTime' => ['group' => 'vignette_ads', 'attribute' => 'vignette_reshow_time'],
'adsense-placementVignetteMaxPerSession' => ['group' => 'vignette_ads', 'attribute' => 'vignette_max_per_session'],
// SEARCH RESULTS (ROI APU Search)
'adsense-placementSearchAdsEnabled' => ['group' => 'search_results', 'attribute' => 'search_ads_enabled'],
'adsense-placementSearchTopAdEnabled' => ['group' => 'search_results', 'attribute' => 'search_top_ad_enabled'],
'adsense-placementSearchTopAdFormat' => ['group' => 'search_results', 'attribute' => 'search_top_ad_format'],
'adsense-placementSearchBetweenEnabled' => ['group' => 'search_results', 'attribute' => 'search_between_enabled'],
'adsense-placementSearchBetweenMax' => ['group' => 'search_results', 'attribute' => 'search_between_max'],
'adsense-placementSearchBetweenFormat' => ['group' => 'search_results', 'attribute' => 'search_between_format'],
'adsense-placementSearchBetweenPosition' => ['group' => 'search_results', 'attribute' => 'search_between_position'],
'adsense-placementSearchBetweenEvery' => ['group' => 'search_results', 'attribute' => 'search_between_every'],
];
}
}

View File

@@ -57,6 +57,7 @@ final class AdsensePlacementFormBuilder
$html .= $this->buildRailAdsGroup($componentId);
$html .= $this->buildAnchorAdsGroup($componentId);
$html .= $this->buildVignetteAdsGroup($componentId);
$html .= $this->buildSearchResultsGroup($componentId);
$html .= ' </div>';
$html .= '</div>';
@@ -708,6 +709,101 @@ final class AdsensePlacementFormBuilder
return $html;
}
/**
* Seccion para anuncios en resultados de busqueda (ROI APU Search)
*/
private function buildSearchResultsGroup(string $cid): string
{
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #fd7e14;">';
$html .= ' <div class="card-body">';
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
$html .= ' <i class="bi bi-search me-2" style="color: #fd7e14;"></i>';
$html .= ' Resultados de Busqueda';
$html .= ' <span class="badge bg-secondary ms-2">ROI APU Search</span>';
$html .= ' </h5>';
$html .= ' <p class="small text-muted mb-3">Insertar anuncios en los resultados del buscador de Analisis de Precios Unitarios.</p>';
// Master switch
$searchAdsEnabled = $this->renderer->getFieldValue($cid, 'search_results', 'search_ads_enabled', false);
$html .= $this->buildSwitch($cid . 'SearchAdsEnabled', 'Activar ads en busqueda', $searchAdsEnabled, 'bi-power');
// Anuncio superior
$html .= '<div class="border rounded p-3 mb-3" style="background: #fff8f0;">';
$html .= '<div class="d-flex align-items-center gap-2 mb-2">';
$html .= ' <span class="badge" style="background: #fd7e14;">ANUNCIO SUPERIOR</span>';
$html .= ' <small class="text-muted">Debajo del campo de busqueda</small>';
$html .= '</div>';
$html .= '<div class="row g-2">';
$html .= ' <div class="col-md-6">';
$topEnabled = $this->renderer->getFieldValue($cid, 'search_results', 'search_top_ad_enabled', true);
$html .= $this->buildSwitch($cid . 'SearchTopAdEnabled', 'Activar', $topEnabled);
$html .= ' </div>';
$html .= ' <div class="col-md-6">';
$topFormat = $this->renderer->getFieldValue($cid, 'search_results', 'search_top_ad_format', 'auto');
$html .= $this->buildSelect($cid . 'SearchTopAdFormat', 'Formato',
(string)$topFormat,
['auto' => 'Auto (responsive)', 'display' => 'Display (fijo)', 'in-article' => 'In-Article (fluid)']
);
$html .= ' </div>';
$html .= '</div>';
$html .= '</div>';
// Anuncios entre resultados
$html .= '<div class="border rounded p-3" style="background: #fff8f0;">';
$html .= '<div class="d-flex align-items-center gap-2 mb-2">';
$html .= ' <span class="badge" style="background: #fd7e14;">ENTRE RESULTADOS</span>';
$html .= ' <small class="text-muted">Intercalados con los resultados</small>';
$html .= '</div>';
$html .= '<div class="row g-2 mb-2">';
$html .= ' <div class="col-md-6">';
$betweenEnabled = $this->renderer->getFieldValue($cid, 'search_results', 'search_between_enabled', true);
$html .= $this->buildSwitch($cid . 'SearchBetweenEnabled', 'Activar', $betweenEnabled);
$html .= ' </div>';
$html .= ' <div class="col-md-6">';
$betweenMax = $this->renderer->getFieldValue($cid, 'search_results', 'search_between_max', '1');
$html .= $this->buildSelect($cid . 'SearchBetweenMax', 'Maximo ads',
(string)$betweenMax,
['1' => '1 anuncio', '2' => '2 anuncios', '3' => '3 anuncios (max)']
);
$html .= ' </div>';
$html .= '</div>';
$html .= '<div class="row g-2 mb-2">';
$html .= ' <div class="col-md-6">';
$betweenFormat = $this->renderer->getFieldValue($cid, 'search_results', 'search_between_format', 'in-article');
$html .= $this->buildSelect($cid . 'SearchBetweenFormat', 'Formato',
(string)$betweenFormat,
['in-article' => 'In-Article (fluid)', 'auto' => 'Auto (responsive)', 'autorelaxed' => 'Autorelaxed (feed)']
);
$html .= ' </div>';
$html .= ' <div class="col-md-6">';
$betweenPosition = $this->renderer->getFieldValue($cid, 'search_results', 'search_between_position', 'random');
$html .= $this->buildSelect($cid . 'SearchBetweenPosition', 'Posicion',
(string)$betweenPosition,
['random' => 'Aleatorio', 'fixed' => 'Fijo (cada N)', 'first_half' => 'Primera mitad']
);
$html .= ' </div>';
$html .= '</div>';
$html .= '<div class="row g-2">';
$html .= ' <div class="col-md-6">';
$betweenEvery = $this->renderer->getFieldValue($cid, 'search_results', 'search_between_every', '5');
$html .= $this->buildSelect($cid . 'SearchBetweenEvery', 'Cada N resultados (si es fijo)',
(string)$betweenEvery,
['3' => 'Cada 3', '4' => 'Cada 4', '5' => 'Cada 5', '6' => 'Cada 6', '7' => 'Cada 7', '8' => 'Cada 8', '10' => 'Cada 10']
);
$html .= ' </div>';
$html .= '</div>';
$html .= '</div>';
$html .= ' </div>';
$html .= '</div>';
return $html;
}
private function buildExclusionsGroup(string $cid): string
{
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #6c757d;">';

View File

@@ -26,7 +26,13 @@ final class ContactFormFieldMapper implements FieldMapperInterface
'contactFormEnabled' => ['group' => 'visibility', 'attribute' => 'is_enabled'],
'contactFormShowOnDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
'contactFormShowOnMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
'contactFormShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
// Page Visibility (grupo especial _page_visibility)
'contactFormVisibilityHome' => ['group' => '_page_visibility', 'attribute' => 'show_on_home'],
'contactFormVisibilityPosts' => ['group' => '_page_visibility', 'attribute' => 'show_on_posts'],
'contactFormVisibilityPages' => ['group' => '_page_visibility', 'attribute' => 'show_on_pages'],
'contactFormVisibilityArchives' => ['group' => '_page_visibility', 'attribute' => 'show_on_archives'],
'contactFormVisibilitySearch' => ['group' => '_page_visibility', 'attribute' => 'show_on_search'],
// Content
'contactFormSectionTitle' => ['group' => 'content', 'attribute' => 'section_title'],

View File

@@ -93,17 +93,38 @@ final class ContactFormFormBuilder
$showOnMobile = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_mobile', true);
$html .= $this->buildSwitch('contactFormShowOnMobile', 'Mostrar en movil', 'bi-phone', $showOnMobile);
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'all');
$html .= ' <div class="mb-0 mt-3">';
$html .= ' <label for="contactFormShowOnPages" class="form-label small mb-1 fw-semibold">';
$html .= ' <i class="bi bi-file-earmark-text me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en';
$html .= ' </label>';
$html .= ' <select id="contactFormShowOnPages" class="form-select form-select-sm">';
$html .= ' <option value="all"' . ($showOnPages === 'all' ? ' selected' : '') . '>Todos</option>';
$html .= ' <option value="posts"' . ($showOnPages === 'posts' ? ' selected' : '') . '>Solo posts</option>';
$html .= ' <option value="pages"' . ($showOnPages === 'pages' ? ' selected' : '') . '>Solo paginas</option>';
$html .= ' </select>';
// =============================================
// Checkboxes de visibilidad por tipo de página
// Grupo especial: _page_visibility
// =============================================
$html .= ' <hr class="my-3">';
$html .= ' <p class="small fw-semibold mb-2">';
$html .= ' <i class="bi bi-eye me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en tipos de pagina';
$html .= ' </p>';
$showOnHome = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_home', true);
$showOnPosts = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_posts', true);
$showOnPages = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_pages', true);
$showOnArchives = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_archives', false);
$showOnSearch = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_search', false);
$html .= ' <div class="row g-2">';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('contactFormVisibilityHome', 'Home', 'bi-house', $showOnHome);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('contactFormVisibilityPosts', 'Posts', 'bi-file-earmark-text', $showOnPosts);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('contactFormVisibilityPages', 'Paginas', 'bi-file-earmark', $showOnPages);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('contactFormVisibilityArchives', 'Archivos', 'bi-archive', $showOnArchives);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('contactFormVisibilitySearch', 'Busqueda', 'bi-search', $showOnSearch);
$html .= ' </div>';
$html .= ' </div>';
$html .= ' </div>';
@@ -598,4 +619,26 @@ final class ContactFormFormBuilder
return $html;
}
private function buildPageVisibilityCheckbox(string $id, string $label, string $icon, mixed $checked): string
{
$checked = $checked === true || $checked === '1' || $checked === 1;
$html = ' <div class="form-check form-check-checkbox mb-2">';
$html .= sprintf(
' <input class="form-check-input" type="checkbox" id="%s" %s>',
esc_attr($id),
$checked ? 'checked' : ''
);
$html .= sprintf(
' <label class="form-check-label small" for="%s">',
esc_attr($id)
);
$html .= sprintf(' <i class="bi %s me-1" style="color: #FF8600;"></i>', esc_attr($icon));
$html .= sprintf(' %s', esc_html($label));
$html .= ' </label>';
$html .= ' </div>';
return $html;
}
}

View File

@@ -30,7 +30,13 @@ final class CtaBoxSidebarFieldMapper implements FieldMapperInterface
'ctaEnabled' => ['group' => 'visibility', 'attribute' => 'is_enabled'],
'ctaShowOnDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
'ctaShowOnMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
'ctaShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
// Page Visibility (grupo especial _page_visibility)
'ctaVisibilityHome' => ['group' => '_page_visibility', 'attribute' => 'show_on_home'],
'ctaVisibilityPosts' => ['group' => '_page_visibility', 'attribute' => 'show_on_posts'],
'ctaVisibilityPages' => ['group' => '_page_visibility', 'attribute' => 'show_on_pages'],
'ctaVisibilityArchives' => ['group' => '_page_visibility', 'attribute' => 'show_on_archives'],
'ctaVisibilitySearch' => ['group' => '_page_visibility', 'attribute' => 'show_on_search'],
// Content
'ctaTitle' => ['group' => 'content', 'attribute' => 'title'],

View File

@@ -94,18 +94,40 @@ final class CtaBoxSidebarFormBuilder
$showOnMobile = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_mobile', false);
$html .= $this->buildSwitch('ctaShowOnMobile', 'Mostrar en movil', 'bi-phone', $showOnMobile);
// show_on_pages
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'posts');
$html .= ' <div class="mb-0 mt-3">';
$html .= ' <label for="ctaShowOnPages" class="form-label small mb-1 fw-semibold">';
$html .= ' <i class="bi bi-file-earmark-text me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en';
$html .= ' </label>';
$html .= ' <select id="ctaShowOnPages" class="form-select form-select-sm">';
$html .= ' <option value="all"' . ($showOnPages === 'all' ? ' selected' : '') . '>Todos</option>';
$html .= ' <option value="posts"' . ($showOnPages === 'posts' ? ' selected' : '') . '>Solo posts</option>';
$html .= ' <option value="pages"' . ($showOnPages === 'pages' ? ' selected' : '') . '>Solo paginas</option>';
$html .= ' </select>';
// =============================================
// Checkboxes de visibilidad por tipo de página
// Grupo especial: _page_visibility
// =============================================
$html .= ' <hr class="my-3">';
$html .= ' <p class="small fw-semibold mb-2">';
$html .= ' <i class="bi bi-eye me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en tipos de pagina';
$html .= ' </p>';
// Obtener valores de _page_visibility (grupo especial)
$showOnHome = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_home', true);
$showOnPosts = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_posts', true);
$showOnPages = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_pages', true);
$showOnArchives = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_archives', false);
$showOnSearch = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_search', false);
// Grid 3 columnas según Design System
$html .= ' <div class="row g-2">';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaVisibilityHome', 'Home', 'bi-house', $showOnHome);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaVisibilityPosts', 'Posts', 'bi-file-earmark-text', $showOnPosts);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaVisibilityPages', 'Paginas', 'bi-file-earmark', $showOnPages);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaVisibilityArchives', 'Archivos', 'bi-archive', $showOnArchives);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaVisibilitySearch', 'Busqueda', 'bi-search', $showOnSearch);
$html .= ' </div>';
$html .= ' </div>';
$html .= ' </div>';
@@ -515,4 +537,29 @@ final class CtaBoxSidebarFormBuilder
return $html;
}
/**
* Genera un checkbox de visibilidad por tipo de pagina
*
* Sigue Design System: form-check-checkbox es obligatorio
*/
private function buildPageVisibilityCheckbox(string $id, string $label, string $icon, bool $checked): string
{
$html = ' <div class="form-check form-check-checkbox mb-2">';
$html .= sprintf(
' <input class="form-check-input" type="checkbox" id="%s" %s>',
esc_attr($id),
$checked ? 'checked' : ''
);
$html .= sprintf(
' <label class="form-check-label small" for="%s">',
esc_attr($id)
);
$html .= sprintf(' <i class="bi %s me-1" style="color: #FF8600;"></i>', esc_attr($icon));
$html .= sprintf(' %s', esc_html($label));
$html .= ' </label>';
$html .= ' </div>';
return $html;
}
}

View File

@@ -26,7 +26,13 @@ final class CtaLetsTalkFieldMapper implements FieldMapperInterface
'ctaLetsTalkEnabled' => ['group' => 'visibility', 'attribute' => 'is_enabled'],
'ctaLetsTalkShowDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
'ctaLetsTalkShowMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
'ctaLetsTalkShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
// Page Visibility (grupo especial _page_visibility)
'ctaLetsTalkVisibilityHome' => ['group' => '_page_visibility', 'attribute' => 'show_on_home'],
'ctaLetsTalkVisibilityPosts' => ['group' => '_page_visibility', 'attribute' => 'show_on_posts'],
'ctaLetsTalkVisibilityPages' => ['group' => '_page_visibility', 'attribute' => 'show_on_pages'],
'ctaLetsTalkVisibilityArchives' => ['group' => '_page_visibility', 'attribute' => 'show_on_archives'],
'ctaLetsTalkVisibilitySearch' => ['group' => '_page_visibility', 'attribute' => 'show_on_search'],
// Content
'ctaLetsTalkButtonText' => ['group' => 'content', 'attribute' => 'button_text'],

View File

@@ -120,16 +120,38 @@ final class CtaLetsTalkFormBuilder
$html .= ' </div>';
$html .= ' </div>';
// Select: Show on Pages
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'all');
$html .= ' <div class="mb-0">';
$html .= ' <label for="ctaLetsTalkShowOnPages" class="form-label small mb-1 fw-semibold">Mostrar en</label>';
$html .= ' <select id="ctaLetsTalkShowOnPages" name="visibility[show_on_pages]" class="form-select form-select-sm">';
$html .= ' <option value="all" ' . selected($showOnPages, 'all', false) . '>Todas las páginas</option>';
$html .= ' <option value="home" ' . selected($showOnPages, 'home', false) . '>Solo página de inicio</option>';
$html .= ' <option value="posts" ' . selected($showOnPages, 'posts', false) . '>Solo posts individuales</option>';
$html .= ' <option value="pages" ' . selected($showOnPages, 'pages', false) . '>Solo páginas</option>';
$html .= ' </select>';
// =============================================
// Checkboxes de visibilidad por tipo de página
// Grupo especial: _page_visibility
// =============================================
$html .= ' <hr class="my-3">';
$html .= ' <p class="small fw-semibold mb-2">';
$html .= ' <i class="bi bi-eye me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en tipos de pagina';
$html .= ' </p>';
$showOnHome = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_home', true);
$showOnPosts = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_posts', true);
$showOnPages = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_pages', true);
$showOnArchives = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_archives', false);
$showOnSearch = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_search', false);
$html .= ' <div class="row g-2">';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaLetsTalkVisibilityHome', 'Home', 'bi-house', $showOnHome);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaLetsTalkVisibilityPosts', 'Posts', 'bi-file-earmark-text', $showOnPosts);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaLetsTalkVisibilityPages', 'Paginas', 'bi-file-earmark', $showOnPages);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaLetsTalkVisibilityArchives', 'Archivos', 'bi-archive', $showOnArchives);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaLetsTalkVisibilitySearch', 'Busqueda', 'bi-search', $showOnSearch);
$html .= ' </div>';
$html .= ' </div>';
$html .= ' </div>';
@@ -447,4 +469,26 @@ final class CtaLetsTalkFormBuilder
return $html;
}
private function buildPageVisibilityCheckbox(string $id, string $label, string $icon, mixed $checked): string
{
$checked = $checked === true || $checked === '1' || $checked === 1;
$html = ' <div class="form-check form-check-checkbox mb-2">';
$html .= sprintf(
' <input class="form-check-input" type="checkbox" id="%s" %s>',
esc_attr($id),
$checked ? 'checked' : ''
);
$html .= sprintf(
' <label class="form-check-label small" for="%s">',
esc_attr($id)
);
$html .= sprintf(' <i class="bi %s me-1" style="color: #FF8600;"></i>', esc_attr($icon));
$html .= sprintf(' %s', esc_html($label));
$html .= ' </label>';
$html .= ' </div>';
return $html;
}
}

View File

@@ -26,7 +26,13 @@ final class CtaPostFieldMapper implements FieldMapperInterface
'ctaPostEnabled' => ['group' => 'visibility', 'attribute' => 'is_enabled'],
'ctaPostShowOnDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
'ctaPostShowOnMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
'ctaPostShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
// Page Visibility (grupo especial _page_visibility)
'ctaPostVisibilityHome' => ['group' => '_page_visibility', 'attribute' => 'show_on_home'],
'ctaPostVisibilityPosts' => ['group' => '_page_visibility', 'attribute' => 'show_on_posts'],
'ctaPostVisibilityPages' => ['group' => '_page_visibility', 'attribute' => 'show_on_pages'],
'ctaPostVisibilityArchives' => ['group' => '_page_visibility', 'attribute' => 'show_on_archives'],
'ctaPostVisibilitySearch' => ['group' => '_page_visibility', 'attribute' => 'show_on_search'],
// Content
'ctaPostTitle' => ['group' => 'content', 'attribute' => 'title'],

View File

@@ -85,17 +85,38 @@ final class CtaPostFormBuilder
$showOnMobile = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_mobile', true);
$html .= $this->buildSwitch('ctaPostShowOnMobile', 'Mostrar en movil', 'bi-phone', $showOnMobile);
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'posts');
$html .= ' <div class="mb-0 mt-3">';
$html .= ' <label for="ctaPostShowOnPages" class="form-label small mb-1 fw-semibold">';
$html .= ' <i class="bi bi-file-earmark-text me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en';
$html .= ' </label>';
$html .= ' <select id="ctaPostShowOnPages" class="form-select form-select-sm">';
$html .= ' <option value="all"' . ($showOnPages === 'all' ? ' selected' : '') . '>Todos</option>';
$html .= ' <option value="posts"' . ($showOnPages === 'posts' ? ' selected' : '') . '>Solo posts</option>';
$html .= ' <option value="pages"' . ($showOnPages === 'pages' ? ' selected' : '') . '>Solo paginas</option>';
$html .= ' </select>';
// =============================================
// Checkboxes de visibilidad por tipo de página
// Grupo especial: _page_visibility
// =============================================
$html .= ' <hr class="my-3">';
$html .= ' <p class="small fw-semibold mb-2">';
$html .= ' <i class="bi bi-eye me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en tipos de pagina';
$html .= ' </p>';
$showOnHome = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_home', true);
$showOnPosts = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_posts', true);
$showOnPages = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_pages', true);
$showOnArchives = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_archives', false);
$showOnSearch = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_search', false);
$html .= ' <div class="row g-2">';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaPostVisibilityHome', 'Home', 'bi-house', $showOnHome);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaPostVisibilityPosts', 'Posts', 'bi-file-earmark-text', $showOnPosts);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaPostVisibilityPages', 'Paginas', 'bi-file-earmark', $showOnPages);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaPostVisibilityArchives', 'Archivos', 'bi-archive', $showOnArchives);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('ctaPostVisibilitySearch', 'Busqueda', 'bi-search', $showOnSearch);
$html .= ' </div>';
$html .= ' </div>';
$html .= ' </div>';
@@ -437,4 +458,26 @@ final class CtaPostFormBuilder
return $html;
}
private function buildPageVisibilityCheckbox(string $id, string $label, string $icon, mixed $checked): string
{
$checked = $checked === true || $checked === '1' || $checked === 1;
$html = ' <div class="form-check form-check-checkbox mb-2">';
$html .= sprintf(
' <input class="form-check-input" type="checkbox" id="%s" %s>',
esc_attr($id),
$checked ? 'checked' : ''
);
$html .= sprintf(
' <label class="form-check-label small" for="%s">',
esc_attr($id)
);
$html .= sprintf(' <i class="bi %s me-1" style="color: #FF8600;"></i>', esc_attr($icon));
$html .= sprintf(' %s', esc_html($label));
$html .= ' </label>';
$html .= ' </div>';
return $html;
}
}

View File

@@ -26,7 +26,13 @@ final class FeaturedImageFieldMapper implements FieldMapperInterface
'featuredImageEnabled' => ['group' => 'visibility', 'attribute' => 'is_enabled'],
'featuredImageShowOnDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
'featuredImageShowOnMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
'featuredImageShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
// Page Visibility (grupo especial _page_visibility)
'featuredImageVisibilityHome' => ['group' => '_page_visibility', 'attribute' => 'show_on_home'],
'featuredImageVisibilityPosts' => ['group' => '_page_visibility', 'attribute' => 'show_on_posts'],
'featuredImageVisibilityPages' => ['group' => '_page_visibility', 'attribute' => 'show_on_pages'],
'featuredImageVisibilityArchives' => ['group' => '_page_visibility', 'attribute' => 'show_on_archives'],
'featuredImageVisibilitySearch' => ['group' => '_page_visibility', 'attribute' => 'show_on_search'],
// Content
'featuredImageSize' => ['group' => 'content', 'attribute' => 'image_size'],

View File

@@ -100,17 +100,38 @@ final class FeaturedImageFormBuilder
$html .= ' </div>';
$html .= ' </div>';
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'posts');
$html .= ' <div class="mb-0 mt-3">';
$html .= ' <label for="featuredImageShowOnPages" class="form-label small mb-1 fw-semibold">';
$html .= ' <i class="bi bi-file-earmark-text me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en';
$html .= ' </label>';
$html .= ' <select id="featuredImageShowOnPages" class="form-select form-select-sm">';
$html .= ' <option value="all" ' . selected($showOnPages, 'all', false) . '>Todas las paginas</option>';
$html .= ' <option value="posts" ' . selected($showOnPages, 'posts', false) . '>Solo posts individuales</option>';
$html .= ' <option value="pages" ' . selected($showOnPages, 'pages', false) . '>Solo paginas</option>';
$html .= ' </select>';
// =============================================
// Checkboxes de visibilidad por tipo de página
// Grupo especial: _page_visibility
// =============================================
$html .= ' <hr class="my-3">';
$html .= ' <p class="small fw-semibold mb-2">';
$html .= ' <i class="bi bi-eye me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en tipos de pagina';
$html .= ' </p>';
$showOnHome = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_home', false);
$showOnPosts = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_posts', true);
$showOnPages = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_pages', true);
$showOnArchives = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_archives', false);
$showOnSearch = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_search', false);
$html .= ' <div class="row g-2">';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('featuredImageVisibilityHome', 'Home', 'bi-house', $showOnHome);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('featuredImageVisibilityPosts', 'Posts', 'bi-file-earmark-text', $showOnPosts);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('featuredImageVisibilityPages', 'Paginas', 'bi-file-earmark', $showOnPages);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('featuredImageVisibilityArchives', 'Archivos', 'bi-archive', $showOnArchives);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('featuredImageVisibilitySearch', 'Busqueda', 'bi-search', $showOnSearch);
$html .= ' </div>';
$html .= ' </div>';
$html .= ' </div>';
@@ -119,6 +140,28 @@ final class FeaturedImageFormBuilder
return $html;
}
private function buildPageVisibilityCheckbox(string $id, string $label, string $icon, mixed $checked): string
{
$checked = $checked === true || $checked === '1' || $checked === 1;
$html = ' <div class="form-check form-check-checkbox mb-2">';
$html .= sprintf(
' <input class="form-check-input" type="checkbox" id="%s" %s>',
esc_attr($id),
$checked ? 'checked' : ''
);
$html .= sprintf(
' <label class="form-check-label small" for="%s">',
esc_attr($id)
);
$html .= sprintf(' <i class="bi %s me-1" style="color: #FF8600;"></i>', esc_attr($icon));
$html .= sprintf(' %s', esc_html($label));
$html .= ' </label>';
$html .= ' </div>';
return $html;
}
private function buildContentGroup(string $componentId): string
{
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">';

View File

@@ -26,9 +26,15 @@ final class HeroFieldMapper implements FieldMapperInterface
'heroEnabled' => ['group' => 'visibility', 'attribute' => 'is_enabled'],
'heroShowOnDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
'heroShowOnMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
'heroShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
'heroIsCritical' => ['group' => 'visibility', 'attribute' => 'is_critical'],
// Page Visibility (grupo especial _page_visibility)
'heroVisibilityHome' => ['group' => '_page_visibility', 'attribute' => 'show_on_home'],
'heroVisibilityPosts' => ['group' => '_page_visibility', 'attribute' => 'show_on_posts'],
'heroVisibilityPages' => ['group' => '_page_visibility', 'attribute' => 'show_on_pages'],
'heroVisibilityArchives' => ['group' => '_page_visibility', 'attribute' => 'show_on_archives'],
'heroVisibilitySearch' => ['group' => '_page_visibility', 'attribute' => 'show_on_search'],
// Content
'heroShowCategories' => ['group' => 'content', 'attribute' => 'show_categories'],
'heroShowBadgeIcon' => ['group' => 'content', 'attribute' => 'show_badge_icon'],

View File

@@ -102,18 +102,38 @@ final class HeroFormBuilder
$html .= ' </div>';
$html .= ' </div>';
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'posts');
$html .= ' <div class="mb-2 mt-3">';
$html .= ' <label for="heroShowOnPages" class="form-label small mb-1 fw-semibold">';
$html .= ' <i class="bi bi-file-earmark-text me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en';
$html .= ' </label>';
$html .= ' <select id="heroShowOnPages" class="form-select form-select-sm">';
$html .= ' <option value="all" ' . selected($showOnPages, 'all', false) . '>Todas las páginas</option>';
$html .= ' <option value="posts" ' . selected($showOnPages, 'posts', false) . '>Solo posts individuales</option>';
$html .= ' <option value="pages" ' . selected($showOnPages, 'pages', false) . '>Solo páginas</option>';
$html .= ' <option value="home" ' . selected($showOnPages, 'home', false) . '>Solo página de inicio</option>';
$html .= ' </select>';
// =============================================
// Checkboxes de visibilidad por tipo de página
// Grupo especial: _page_visibility
// =============================================
$html .= ' <hr class="my-3">';
$html .= ' <p class="small fw-semibold mb-2">';
$html .= ' <i class="bi bi-eye me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en tipos de pagina';
$html .= ' </p>';
$showOnHome = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_home', false);
$showOnPosts = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_posts', true);
$showOnPages = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_pages', true);
$showOnArchives = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_archives', false);
$showOnSearch = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_search', false);
$html .= ' <div class="row g-2">';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('heroVisibilityHome', 'Home', 'bi-house', $showOnHome);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('heroVisibilityPosts', 'Posts', 'bi-file-earmark-text', $showOnPosts);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('heroVisibilityPages', 'Paginas', 'bi-file-earmark', $showOnPages);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('heroVisibilityArchives', 'Archivos', 'bi-archive', $showOnArchives);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('heroVisibilitySearch', 'Busqueda', 'bi-search', $showOnSearch);
$html .= ' </div>';
$html .= ' </div>';
// Switch: CSS Crítico
@@ -427,4 +447,26 @@ final class HeroFormBuilder
return $html;
}
private function buildPageVisibilityCheckbox(string $id, string $label, string $icon, mixed $checked): string
{
$checked = $checked === true || $checked === '1' || $checked === 1;
$html = ' <div class="form-check form-check-checkbox mb-2">';
$html .= sprintf(
' <input class="form-check-input" type="checkbox" id="%s" %s>',
esc_attr($id),
$checked ? 'checked' : ''
);
$html .= sprintf(
' <label class="form-check-label small" for="%s">',
esc_attr($id)
);
$html .= sprintf(' <i class="bi %s me-1" style="color: #FF8600;"></i>', esc_attr($icon));
$html .= sprintf(' %s', esc_html($label));
$html .= ' </label>';
$html .= ' </div>';
return $html;
}
}

View File

@@ -26,10 +26,16 @@ final class NavbarFieldMapper implements FieldMapperInterface
'navbarEnabled' => ['group' => 'visibility', 'attribute' => 'is_enabled'],
'navbarShowMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
'navbarShowDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
'navbarShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
'navbarSticky' => ['group' => 'visibility', 'attribute' => 'sticky_enabled'],
'navbarIsCritical' => ['group' => 'visibility', 'attribute' => 'is_critical'],
// Page Visibility (grupo especial _page_visibility)
'navbarVisibilityHome' => ['group' => '_page_visibility', 'attribute' => 'show_on_home'],
'navbarVisibilityPosts' => ['group' => '_page_visibility', 'attribute' => 'show_on_posts'],
'navbarVisibilityPages' => ['group' => '_page_visibility', 'attribute' => 'show_on_pages'],
'navbarVisibilityArchives' => ['group' => '_page_visibility', 'attribute' => 'show_on_archives'],
'navbarVisibilitySearch' => ['group' => '_page_visibility', 'attribute' => 'show_on_search'],
// Layout
'navbarContainerType' => ['group' => 'layout', 'attribute' => 'container_type'],
'navbarPaddingVertical' => ['group' => 'layout', 'attribute' => 'padding_vertical'],

View File

@@ -105,16 +105,38 @@ final class NavbarFormBuilder
$html .= ' </div>';
$html .= ' </div>';
// Select: Show on Pages
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'all');
$html .= ' <div class="mb-2">';
$html .= ' <label for="navbarShowOnPages" class="form-label small mb-1 fw-semibold">Mostrar en</label>';
$html .= ' <select id="navbarShowOnPages" name="visibility[show_on_pages]" class="form-select form-select-sm">';
$html .= ' <option value="all" ' . selected($showOnPages, 'all', false) . '>Todas las páginas</option>';
$html .= ' <option value="home" ' . selected($showOnPages, 'home', false) . '>Solo página de inicio</option>';
$html .= ' <option value="posts" ' . selected($showOnPages, 'posts', false) . '>Solo posts individuales</option>';
$html .= ' <option value="pages" ' . selected($showOnPages, 'pages', false) . '>Solo páginas</option>';
$html .= ' </select>';
// =============================================
// Checkboxes de visibilidad por tipo de página
// Grupo especial: _page_visibility
// =============================================
$html .= ' <hr class="my-3">';
$html .= ' <p class="small fw-semibold mb-2">';
$html .= ' <i class="bi bi-eye me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en tipos de pagina';
$html .= ' </p>';
$showOnHome = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_home', true);
$showOnPosts = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_posts', true);
$showOnPages = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_pages', true);
$showOnArchives = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_archives', true);
$showOnSearch = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_search', true);
$html .= ' <div class="row g-2">';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('navbarVisibilityHome', 'Home', 'bi-house', $showOnHome);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('navbarVisibilityPosts', 'Posts', 'bi-file-earmark-text', $showOnPosts);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('navbarVisibilityPages', 'Paginas', 'bi-file-earmark', $showOnPages);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('navbarVisibilityArchives', 'Archivos', 'bi-archive', $showOnArchives);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('navbarVisibilitySearch', 'Busqueda', 'bi-search', $showOnSearch);
$html .= ' </div>';
$html .= ' </div>';
// Switch: Sticky
@@ -527,4 +549,26 @@ final class NavbarFormBuilder
return $html;
}
private function buildPageVisibilityCheckbox(string $id, string $label, string $icon, mixed $checked): string
{
$checked = $checked === true || $checked === '1' || $checked === 1;
$html = ' <div class="form-check form-check-checkbox mb-2">';
$html .= sprintf(
' <input class="form-check-input" type="checkbox" id="%s" %s>',
esc_attr($id),
$checked ? 'checked' : ''
);
$html .= sprintf(
' <label class="form-check-label small" for="%s">',
esc_attr($id)
);
$html .= sprintf(' <i class="bi %s me-1" style="color: #FF8600;"></i>', esc_attr($icon));
$html .= sprintf(' %s', esc_html($label));
$html .= ' </label>';
$html .= ' </div>';
return $html;
}
}

View File

@@ -29,7 +29,13 @@ final class RelatedPostFieldMapper implements FieldMapperInterface
'relatedPostEnabled' => ['group' => 'visibility', 'attribute' => 'is_enabled'],
'relatedPostShowOnDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
'relatedPostShowOnMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
'relatedPostShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
// Page Visibility (grupo especial _page_visibility)
'relatedPostVisibilityHome' => ['group' => '_page_visibility', 'attribute' => 'show_on_home'],
'relatedPostVisibilityPosts' => ['group' => '_page_visibility', 'attribute' => 'show_on_posts'],
'relatedPostVisibilityPages' => ['group' => '_page_visibility', 'attribute' => 'show_on_pages'],
'relatedPostVisibilityArchives' => ['group' => '_page_visibility', 'attribute' => 'show_on_archives'],
'relatedPostVisibilitySearch' => ['group' => '_page_visibility', 'attribute' => 'show_on_search'],
// Content
'relatedPostSectionTitle' => ['group' => 'content', 'attribute' => 'section_title'],

View File

@@ -86,17 +86,38 @@ final class RelatedPostFormBuilder
$showOnMobile = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_mobile', true);
$html .= $this->buildSwitch('relatedPostShowOnMobile', 'Mostrar en movil', 'bi-phone', $showOnMobile);
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'posts');
$html .= ' <div class="mb-0 mt-3">';
$html .= ' <label for="relatedPostShowOnPages" class="form-label small mb-1 fw-semibold">';
$html .= ' <i class="bi bi-file-earmark-text me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en';
$html .= ' </label>';
$html .= ' <select id="relatedPostShowOnPages" class="form-select form-select-sm">';
$html .= ' <option value="all"' . ($showOnPages === 'all' ? ' selected' : '') . '>Todos</option>';
$html .= ' <option value="posts"' . ($showOnPages === 'posts' ? ' selected' : '') . '>Solo posts</option>';
$html .= ' <option value="pages"' . ($showOnPages === 'pages' ? ' selected' : '') . '>Solo paginas</option>';
$html .= ' </select>';
// =============================================
// Checkboxes de visibilidad por tipo de página
// Grupo especial: _page_visibility
// =============================================
$html .= ' <hr class="my-3">';
$html .= ' <p class="small fw-semibold mb-2">';
$html .= ' <i class="bi bi-eye me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en tipos de pagina';
$html .= ' </p>';
$showOnHome = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_home', true);
$showOnPosts = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_posts', true);
$showOnPages = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_pages', true);
$showOnArchives = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_archives', false);
$showOnSearch = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_search', false);
$html .= ' <div class="row g-2">';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('relatedPostVisibilityHome', 'Home', 'bi-house', $showOnHome);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('relatedPostVisibilityPosts', 'Posts', 'bi-file-earmark-text', $showOnPosts);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('relatedPostVisibilityPages', 'Paginas', 'bi-file-earmark', $showOnPages);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('relatedPostVisibilityArchives', 'Archivos', 'bi-archive', $showOnArchives);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('relatedPostVisibilitySearch', 'Busqueda', 'bi-search', $showOnSearch);
$html .= ' </div>';
$html .= ' </div>';
$html .= ' </div>';
@@ -498,4 +519,26 @@ final class RelatedPostFormBuilder
return $html;
}
private function buildPageVisibilityCheckbox(string $id, string $label, string $icon, mixed $checked): string
{
$checked = $checked === true || $checked === '1' || $checked === 1;
$html = ' <div class="form-check form-check-checkbox mb-2">';
$html .= sprintf(
' <input class="form-check-input" type="checkbox" id="%s" %s>',
esc_attr($id),
$checked ? 'checked' : ''
);
$html .= sprintf(
' <label class="form-check-label small" for="%s">',
esc_attr($id)
);
$html .= sprintf(' <i class="bi %s me-1" style="color: #FF8600;"></i>', esc_attr($icon));
$html .= sprintf(' %s', esc_html($label));
$html .= ' </label>';
$html .= ' </div>';
return $html;
}
}

View File

@@ -26,7 +26,13 @@ final class SocialShareFieldMapper implements FieldMapperInterface
'socialShareEnabled' => ['group' => 'visibility', 'attribute' => 'is_enabled'],
'socialShareShowOnDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
'socialShareShowOnMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
'socialShareShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
// Page Visibility (grupo especial _page_visibility)
'socialShareVisibilityHome' => ['group' => '_page_visibility', 'attribute' => 'show_on_home'],
'socialShareVisibilityPosts' => ['group' => '_page_visibility', 'attribute' => 'show_on_posts'],
'socialShareVisibilityPages' => ['group' => '_page_visibility', 'attribute' => 'show_on_pages'],
'socialShareVisibilityArchives' => ['group' => '_page_visibility', 'attribute' => 'show_on_archives'],
'socialShareVisibilitySearch' => ['group' => '_page_visibility', 'attribute' => 'show_on_search'],
// Content
'socialShareShowLabel' => ['group' => 'content', 'attribute' => 'show_label'],

View File

@@ -94,18 +94,38 @@ final class SocialShareFormBuilder
$showOnMobile = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_mobile', true);
$html .= $this->buildSwitch('socialShareShowOnMobile', 'Mostrar en movil', 'bi-phone', $showOnMobile);
// show_on_pages
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'posts');
$html .= ' <div class="mb-0 mt-3">';
$html .= ' <label for="socialShareShowOnPages" class="form-label small mb-1 fw-semibold">';
$html .= ' <i class="bi bi-file-earmark-text me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en';
$html .= ' </label>';
$html .= ' <select id="socialShareShowOnPages" class="form-select form-select-sm">';
$html .= ' <option value="all"' . ($showOnPages === 'all' ? ' selected' : '') . '>Todos</option>';
$html .= ' <option value="posts"' . ($showOnPages === 'posts' ? ' selected' : '') . '>Solo posts</option>';
$html .= ' <option value="pages"' . ($showOnPages === 'pages' ? ' selected' : '') . '>Solo paginas</option>';
$html .= ' </select>';
// =============================================
// Checkboxes de visibilidad por tipo de página
// Grupo especial: _page_visibility
// =============================================
$html .= ' <hr class="my-3">';
$html .= ' <p class="small fw-semibold mb-2">';
$html .= ' <i class="bi bi-eye me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en tipos de pagina';
$html .= ' </p>';
$showOnHome = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_home', true);
$showOnPosts = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_posts', true);
$showOnPages = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_pages', true);
$showOnArchives = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_archives', false);
$showOnSearch = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_search', false);
$html .= ' <div class="row g-2">';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('socialShareVisibilityHome', 'Home', 'bi-house', $showOnHome);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('socialShareVisibilityPosts', 'Posts', 'bi-file-earmark-text', $showOnPosts);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('socialShareVisibilityPages', 'Paginas', 'bi-file-earmark', $showOnPages);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('socialShareVisibilityArchives', 'Archivos', 'bi-archive', $showOnArchives);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('socialShareVisibilitySearch', 'Busqueda', 'bi-search', $showOnSearch);
$html .= ' </div>';
$html .= ' </div>';
$html .= ' </div>';
@@ -526,4 +546,26 @@ final class SocialShareFormBuilder
return $html;
}
private function buildPageVisibilityCheckbox(string $id, string $label, string $icon, mixed $checked): string
{
$checked = $checked === true || $checked === '1' || $checked === 1;
$html = ' <div class="form-check form-check-checkbox mb-2">';
$html .= sprintf(
' <input class="form-check-input" type="checkbox" id="%s" %s>',
esc_attr($id),
$checked ? 'checked' : ''
);
$html .= sprintf(
' <label class="form-check-label small" for="%s">',
esc_attr($id)
);
$html .= sprintf(' <i class="bi %s me-1" style="color: #FF8600;"></i>', esc_attr($icon));
$html .= sprintf(' %s', esc_html($label));
$html .= ' </label>';
$html .= ' </div>';
return $html;
}
}

View File

@@ -26,7 +26,13 @@ final class TableOfContentsFieldMapper implements FieldMapperInterface
'tocEnabled' => ['group' => 'visibility', 'attribute' => 'is_enabled'],
'tocShowOnDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
'tocShowOnMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
'tocShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
// Page Visibility (grupo especial _page_visibility)
'tocVisibilityHome' => ['group' => '_page_visibility', 'attribute' => 'show_on_home'],
'tocVisibilityPosts' => ['group' => '_page_visibility', 'attribute' => 'show_on_posts'],
'tocVisibilityPages' => ['group' => '_page_visibility', 'attribute' => 'show_on_pages'],
'tocVisibilityArchives' => ['group' => '_page_visibility', 'attribute' => 'show_on_archives'],
'tocVisibilitySearch' => ['group' => '_page_visibility', 'attribute' => 'show_on_search'],
// Content
'tocTitle' => ['group' => 'content', 'attribute' => 'title'],

View File

@@ -94,18 +94,38 @@ final class TableOfContentsFormBuilder
$showOnMobile = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_mobile', false);
$html .= $this->buildSwitch('tocShowOnMobile', 'Mostrar en movil', 'bi-phone', $showOnMobile);
// show_on_pages
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'posts');
$html .= ' <div class="mb-0 mt-3">';
$html .= ' <label for="tocShowOnPages" class="form-label small mb-1 fw-semibold">';
$html .= ' <i class="bi bi-file-earmark-text me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en';
$html .= ' </label>';
$html .= ' <select id="tocShowOnPages" class="form-select form-select-sm">';
$html .= ' <option value="all" ' . selected($showOnPages, 'all', false) . '>Todas las paginas</option>';
$html .= ' <option value="posts" ' . selected($showOnPages, 'posts', false) . '>Solo posts</option>';
$html .= ' <option value="pages" ' . selected($showOnPages, 'pages', false) . '>Solo paginas</option>';
$html .= ' </select>';
// =============================================
// Checkboxes de visibilidad por tipo de página
// Grupo especial: _page_visibility
// =============================================
$html .= ' <hr class="my-3">';
$html .= ' <p class="small fw-semibold mb-2">';
$html .= ' <i class="bi bi-eye me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en tipos de pagina';
$html .= ' </p>';
$showOnHome = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_home', false);
$showOnPosts = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_posts', true);
$showOnPages = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_pages', true);
$showOnArchives = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_archives', false);
$showOnSearch = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_search', false);
$html .= ' <div class="row g-2">';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('tocVisibilityHome', 'Home', 'bi-house', $showOnHome);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('tocVisibilityPosts', 'Posts', 'bi-file-earmark-text', $showOnPosts);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('tocVisibilityPages', 'Paginas', 'bi-file-earmark', $showOnPages);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('tocVisibilityArchives', 'Archivos', 'bi-archive', $showOnArchives);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('tocVisibilitySearch', 'Busqueda', 'bi-search', $showOnSearch);
$html .= ' </div>';
$html .= ' </div>';
$html .= ' </div>';
@@ -585,4 +605,26 @@ final class TableOfContentsFormBuilder
return $html;
}
private function buildPageVisibilityCheckbox(string $id, string $label, string $icon, mixed $checked): string
{
$checked = $checked === true || $checked === '1' || $checked === 1;
$html = ' <div class="form-check form-check-checkbox mb-2">';
$html .= sprintf(
' <input class="form-check-input" type="checkbox" id="%s" %s>',
esc_attr($id),
$checked ? 'checked' : ''
);
$html .= sprintf(
' <label class="form-check-label small" for="%s">',
esc_attr($id)
);
$html .= sprintf(' <i class="bi %s me-1" style="color: #FF8600;"></i>', esc_attr($icon));
$html .= sprintf(' %s', esc_html($label));
$html .= ' </label>';
$html .= ' </div>';
return $html;
}
}

View File

@@ -26,9 +26,15 @@ final class TopNotificationBarFieldMapper implements FieldMapperInterface
'topBarEnabled' => ['group' => 'visibility', 'attribute' => 'is_enabled'],
'topBarShowOnMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
'topBarShowOnDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
'topBarShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
'topBarIsCritical' => ['group' => 'visibility', 'attribute' => 'is_critical'],
// Page Visibility (grupo especial _page_visibility)
'topBarVisibilityHome' => ['group' => '_page_visibility', 'attribute' => 'show_on_home'],
'topBarVisibilityPosts' => ['group' => '_page_visibility', 'attribute' => 'show_on_posts'],
'topBarVisibilityPages' => ['group' => '_page_visibility', 'attribute' => 'show_on_pages'],
'topBarVisibilityArchives' => ['group' => '_page_visibility', 'attribute' => 'show_on_archives'],
'topBarVisibilitySearch' => ['group' => '_page_visibility', 'attribute' => 'show_on_search'],
// Content
'topBarIconClass' => ['group' => 'content', 'attribute' => 'icon_class'],
'topBarLabelText' => ['group' => 'content', 'attribute' => 'label_text'],

View File

@@ -105,19 +105,38 @@ final class TopNotificationBarFormBuilder
$html .= ' </div>';
$html .= ' </div>';
// Select: Show on Pages
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'all');
$html .= ' <div class="mb-2 mt-3">';
$html .= ' <label for="topBarShowOnPages" class="form-label small mb-1 fw-semibold" style="color: #495057;">';
$html .= ' <i class="bi bi-file-earmark-text me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en';
$html .= ' </label>';
$html .= ' <select id="topBarShowOnPages" class="form-select form-select-sm">';
$html .= ' <option value="all" ' . selected($showOnPages, 'all', false) . '>Todas las páginas</option>';
$html .= ' <option value="home" ' . selected($showOnPages, 'home', false) . '>Solo página de inicio</option>';
$html .= ' <option value="posts" ' . selected($showOnPages, 'posts', false) . '>Solo posts individuales</option>';
$html .= ' <option value="pages" ' . selected($showOnPages, 'pages', false) . '>Solo páginas</option>';
$html .= ' </select>';
// =============================================
// Checkboxes de visibilidad por tipo de página
// Grupo especial: _page_visibility
// =============================================
$html .= ' <hr class="my-3">';
$html .= ' <p class="small fw-semibold mb-2">';
$html .= ' <i class="bi bi-eye me-1" style="color: #FF8600;"></i>';
$html .= ' Mostrar en tipos de pagina';
$html .= ' </p>';
$showOnHome = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_home', true);
$showOnPosts = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_posts', true);
$showOnPages = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_pages', true);
$showOnArchives = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_archives', false);
$showOnSearch = $this->renderer->getFieldValue($componentId, '_page_visibility', 'show_on_search', false);
$html .= ' <div class="row g-2">';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('topBarVisibilityHome', 'Home', 'bi-house', $showOnHome);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('topBarVisibilityPosts', 'Posts', 'bi-file-earmark-text', $showOnPosts);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('topBarVisibilityPages', 'Paginas', 'bi-file-earmark', $showOnPages);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('topBarVisibilityArchives', 'Archivos', 'bi-archive', $showOnArchives);
$html .= ' </div>';
$html .= ' <div class="col-md-4">';
$html .= $this->buildPageVisibilityCheckbox('topBarVisibilitySearch', 'Busqueda', 'bi-search', $showOnSearch);
$html .= ' </div>';
$html .= ' </div>';
// Switch: CSS Crítico
@@ -319,4 +338,26 @@ final class TopNotificationBarFormBuilder
return $html;
}
private function buildPageVisibilityCheckbox(string $id, string $label, string $icon, mixed $checked): string
{
$checked = $checked === true || $checked === '1' || $checked === 1;
$html = ' <div class="form-check form-check-checkbox mb-2">';
$html .= sprintf(
' <input class="form-check-input" type="checkbox" id="%s" %s>',
esc_attr($id),
$checked ? 'checked' : ''
);
$html .= sprintf(
' <label class="form-check-label small" for="%s">',
esc_attr($id)
);
$html .= sprintf(' <i class="bi %s me-1" style="color: #FF8600;"></i>', esc_attr($icon));
$html .= sprintf(' %s', esc_html($label));
$html .= ' </label>';
$html .= ' </div>';
return $html;
}
}