getData(); if (!$this->isEnabled($data)) { return ''; } if (!PageVisibilityHelper::shouldShow(self::COMPONENT_NAME)) { return ''; } $visibilityClass = $this->getVisibilityClass($data); if ($visibilityClass === null) { return ''; } $css = $this->generateCSS($data); $html = $this->buildHTML($data, $visibilityClass); return sprintf("\n%s", $css, $html); } public function supports(string $componentType): bool { return $componentType === self::COMPONENT_NAME; } private function isEnabled(array $data): bool { $value = $data['visibility']['is_enabled'] ?? false; return $value === true || $value === '1' || $value === 1; } private function getVisibilityClass(array $data): ?string { $showDesktop = $data['visibility']['show_on_desktop'] ?? true; $showDesktop = $showDesktop === true || $showDesktop === '1' || $showDesktop === 1; $showMobile = $data['visibility']['show_on_mobile'] ?? true; $showMobile = $showMobile === true || $showMobile === '1' || $showMobile === 1; if (!$showDesktop && !$showMobile) { return null; } if (!$showDesktop && $showMobile) { return 'd-lg-none'; } if ($showDesktop && !$showMobile) { return 'd-none d-lg-block'; } return ''; } private function generateCSS(array $data): string { $colors = $data['colors'] ?? []; $spacing = $data['spacing'] ?? []; $effects = $data['visual_effects'] ?? []; $typography = $data['typography'] ?? []; $visibility = $data['visibility'] ?? []; $cssRules = []; // Variables de colores del tema (defaults del template) $colorNavyPrimary = $colors['section_title_color'] ?? '#0E2337'; $colorOrangePrimary = $colors['card_hover_border_color'] ?? '#FF8600'; $colorNeutral50 = '#f9fafb'; $colorNeutral100 = '#e5e7eb'; $colorNeutral600 = $colors['card_border_color'] ?? '#6b7280'; // Container - margin 3rem 0 $cssRules[] = $this->cssGenerator->generate('.related-posts', [ 'margin' => '3rem 0', ]); // Section title - color navy, font-weight 700, margin-bottom 2rem $cssRules[] = $this->cssGenerator->generate('.related-posts h2', [ 'color' => $colorNavyPrimary, 'font-weight' => '700', 'margin-bottom' => '2rem', ]); // Card styles - cursor pointer, border, border-left 4px $cardBgColor = $colors['card_bg_color'] ?? '#ffffff'; $cardHoverBgColor = $colors['card_hover_bg_color'] ?? $colorNeutral50; $cssRules[] = ".related-posts .card { cursor: pointer; background: {$cardBgColor} !important; border: 1px solid {$colorNeutral100} !important; border-left: 4px solid {$colorNeutral600} !important; transition: all 0.3s ease; height: 100%; }"; // Card hover - background change, shadow, border-left orange $cssRules[] = ".related-posts .card:hover { background: {$cardHoverBgColor} !important; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1) !important; border-left-color: {$colorOrangePrimary} !important; }"; // Card body - padding 1.5rem $cssRules[] = $this->cssGenerator->generate('.related-posts .card-body', [ 'padding' => '1.5rem !important', ]); // Card title - color navy, font-weight 600, font-size 0.95rem $cardTitleColor = $colors['card_title_color'] ?? $colorNavyPrimary; $cssRules[] = ".related-posts .card-title { color: {$cardTitleColor} !important; font-weight: 600; font-size: 0.95rem; line-height: 1.4; }"; // Link hover - title changes to orange $cssRules[] = ".related-posts a:hover .card-title { color: {$colorOrangePrimary} !important; }"; // Pagination styles - matching template exactly $cssRules[] = ".related-posts .page-link { color: {$colorNeutral600}; border: 1px solid {$colorNeutral100}; padding: 0.5rem 1rem; margin: 0 0.25rem; border-radius: 4px; font-weight: 500; transition: all 0.3s ease; }"; $cssRules[] = ".related-posts .page-link:hover { background-color: rgba(255, 133, 0, 0.1); border-color: {$colorOrangePrimary}; color: {$colorOrangePrimary}; }"; $cssRules[] = ".related-posts .page-item.active .page-link { background-color: {$colorOrangePrimary}; border-color: {$colorOrangePrimary}; color: #ffffff; }"; // Responsive visibility $showOnDesktop = $visibility['show_on_desktop'] ?? true; $showOnDesktop = $showOnDesktop === true || $showOnDesktop === '1' || $showOnDesktop === 1; $showOnMobile = $visibility['show_on_mobile'] ?? true; $showOnMobile = $showOnMobile === true || $showOnMobile === '1' || $showOnMobile === 1; if (!$showOnMobile) { $cssRules[] = "@media (max-width: 991.98px) { .related-posts { display: none !important; } }"; } if (!$showOnDesktop) { $cssRules[] = "@media (min-width: 992px) { .related-posts { display: none !important; } }"; } return implode("\n", $cssRules); } private function buildHTML(array $data, string $visibilityClass): string { $content = $data['content'] ?? []; $layout = $data['layout'] ?? []; $sectionTitle = $content['section_title'] ?? 'Descubre Mas Contenido'; $postsPerPage = (int)($content['posts_per_page'] ?? 12); $orderby = $content['orderby'] ?? 'rand'; $order = $content['order'] ?? 'DESC'; $showPagination = $content['show_pagination'] ?? true; $showPagination = $showPagination === true || $showPagination === '1' || $showPagination === 1; // Layout columns (cast to string to handle boolean conversion from DB) $colsDesktop = (string)($layout['columns_desktop'] ?? '3'); $colsTablet = (string)($layout['columns_tablet'] ?? '2'); $colsMobile = (string)($layout['columns_mobile'] ?? '1'); // Handle '1' stored as boolean true in DB if ($colsDesktop === '1' || $colsDesktop === '') $colsDesktop = '3'; if ($colsTablet === '1' || $colsTablet === '') $colsTablet = '2'; if ($colsMobile === '1' || $colsMobile === '') $colsMobile = '1'; // Bootstrap column classes $colClass = $this->getColumnClass($colsDesktop, $colsTablet, $colsMobile); // Query related posts $posts = $this->getRelatedPosts($postsPerPage, $orderby, $order); if (empty($posts)) { return ''; } $containerClass = 'my-5 related-posts'; if (!empty($visibilityClass)) { $containerClass .= ' ' . $visibilityClass; } $html = sprintf('
', esc_attr($containerClass)); $html .= sprintf( '

%s

', esc_html($sectionTitle) ); $html .= '
'; foreach ($posts as $post) { $html .= $this->buildCardHTML($post, $colClass); } $html .= '
'; if ($showPagination) { $html .= $this->buildPaginationHTML($data); } $html .= '
'; // Reset post data wp_reset_postdata(); return $html; } private function getColumnClass(string $desktop, string $tablet, string $mobile): string { $desktopCols = 12 / (int)$desktop; $tabletCols = 12 / (int)$tablet; $mobileCols = 12 / (int)$mobile; // Template original usa col-md-4 (3 columnas desde tablet) // col-{mobile} col-md-{tablet/desktop} return sprintf('col-%d col-md-%d', $mobileCols, $desktopCols); } private function getRelatedPosts(int $perPage, string $orderby, string $order): array { $currentPostId = get_the_ID(); $args = [ 'post_type' => 'post', 'posts_per_page' => $perPage, 'post__not_in' => $currentPostId ? [$currentPostId] : [], 'orderby' => $orderby, 'order' => $order, 'no_found_rows' => true, ]; $query = new \WP_Query($args); return $query->posts; } private function buildCardHTML(\WP_Post $post, string $colClass): string { $permalink = get_permalink($post); $title = get_the_title($post); $html = sprintf('
', esc_attr($colClass)); $html .= sprintf( '', esc_url($permalink) ); $html .= '
'; $html .= '
'; $html .= sprintf( '%s', esc_html($title) ); $html .= '
'; $html .= '
'; $html .= '
'; $html .= '
'; return $html; } private function buildPaginationHTML(array $data): string { $content = $data['content'] ?? []; $textFirst = $content['pagination_text_first'] ?? 'Inicio'; $textLast = $content['pagination_text_last'] ?? 'Fin'; $textMore = $content['pagination_text_more'] ?? 'Ver mas'; $html = ''; return $html; } }