renderer);
* $html .= $exclusionPartial->render($componentId, 'prefijo');
* ```
*
* @package ROITheme\Admin\Shared\Infrastructure\Ui
*/
final class ExclusionFormPartial
{
private const GROUP_NAME = '_exclusions';
public function __construct(
private readonly AdminDashboardRenderer $renderer
) {}
/**
* Renderiza la seccion de exclusiones
*
* @param string $componentId ID del componente (kebab-case)
* @param string $prefix Prefijo para IDs de campos (ej: 'cta' genera 'ctaExclusionsEnabled')
* @return string HTML de la seccion
*/
public function render(string $componentId, string $prefix): string
{
$html = '';
$html .= $this->buildExclusionHeader();
$html .= $this->buildExclusionToggle($componentId, $prefix);
$html .= $this->buildExclusionRules($componentId, $prefix);
return $html;
}
private function buildExclusionHeader(): string
{
$html = '
';
$html .= '';
$html .= ' ';
$html .= ' Reglas de exclusion avanzadas';
$html .= '
';
$html .= '';
$html .= ' Excluir este componente de categorias, posts o URLs especificos.';
$html .= '
';
return $html;
}
private function buildExclusionToggle(string $componentId, string $prefix): string
{
$enabled = $this->renderer->getFieldValue(
$componentId,
self::GROUP_NAME,
'exclusions_enabled',
false
);
$checked = $this->toBool($enabled);
$id = $prefix . 'ExclusionsEnabled';
$html = '';
$html .= '
';
$html .= sprintf(
' ',
esc_attr($id),
$checked ? 'checked' : ''
);
$html .= sprintf(
' ';
$html .= '
';
$html .= '
';
return $html;
}
private function buildExclusionRules(string $componentId, string $prefix): string
{
$enabled = $this->renderer->getFieldValue(
$componentId,
self::GROUP_NAME,
'exclusions_enabled',
false
);
$display = $this->toBool($enabled) ? 'block' : 'none';
$html = sprintf(
'',
esc_attr($prefix),
$display
);
$html .= $this->buildCategoryField($componentId, $prefix);
$html .= $this->buildPostIdsField($componentId, $prefix);
$html .= $this->buildUrlPatternsField($componentId, $prefix);
$html .= '
';
return $html;
}
private function buildCategoryField(string $componentId, string $prefix): string
{
$value = $this->renderer->getFieldValue(
$componentId,
self::GROUP_NAME,
'exclude_categories',
'[]'
);
$categories = $this->jsonToCommaList($value);
$id = $prefix . 'ExcludeCategories';
$html = '';
$html .= sprintf(
' ';
$html .= sprintf(
' ',
esc_attr($id),
esc_attr($categories)
);
$html .= ' Slugs de categorias separados por comas';
$html .= '
';
return $html;
}
private function buildPostIdsField(string $componentId, string $prefix): string
{
$value = $this->renderer->getFieldValue(
$componentId,
self::GROUP_NAME,
'exclude_post_ids',
'[]'
);
$postIds = $this->jsonToCommaList($value);
$id = $prefix . 'ExcludePostIds';
$html = '';
$html .= sprintf(
' ';
$html .= sprintf(
' ',
esc_attr($id),
esc_attr($postIds)
);
$html .= ' IDs de posts o paginas separados por comas';
$html .= '
';
return $html;
}
private function buildUrlPatternsField(string $componentId, string $prefix): string
{
$value = $this->renderer->getFieldValue(
$componentId,
self::GROUP_NAME,
'exclude_url_patterns',
'[]'
);
$patterns = $this->jsonToLineList($value);
$id = $prefix . 'ExcludeUrlPatterns';
$html = '';
$html .= sprintf(
' ';
$html .= sprintf(
' ',
esc_attr($id),
esc_textarea($patterns)
);
$html .= ' Un patron por linea. Soporta texto simple o regex (ej: /^\/blog\/\d+$/)';
$html .= '
';
return $html;
}
/**
* Convierte JSON array o array a lista separada por comas
*
* @param string|array $value Valor desde BD (puede ser JSON string o array ya deserializado)
*/
private function jsonToCommaList(string|array $value): string
{
// Si ya es array, usarlo directamente
if (is_array($value)) {
return empty($value) ? '' : implode(', ', $value);
}
// Si es string, intentar decodificar JSON
$decoded = json_decode($value, true);
if (!is_array($decoded) || empty($decoded)) {
return '';
}
return implode(', ', $decoded);
}
/**
* Convierte JSON array o array a lista separada por lineas
*
* @param string|array $value Valor desde BD (puede ser JSON string o array ya deserializado)
*/
private function jsonToLineList(string|array $value): string
{
// Si ya es array, usarlo directamente
if (is_array($value)) {
return empty($value) ? '' : implode("\n", $value);
}
// Si es string, intentar decodificar JSON
$decoded = json_decode($value, true);
if (!is_array($decoded) || empty($decoded)) {
return '';
}
return implode("\n", $decoded);
}
private function toBool(mixed $value): bool
{
return $value === true || $value === '1' || $value === 1;
}
}