Agregar estructura completa del tema APUS con Bootstrap 5 y optimizaciones de rendimiento
Se implementa tema WordPress personalizado para Análisis de Precios Unitarios con funcionalidades avanzadas: - Sistema de templates (front-page, single, archive, page, 404, search) - Integración de Bootstrap 5.3.8 con estructura modular de assets - Panel de opciones del tema con Customizer API - Optimizaciones de rendimiento (Critical CSS, Image Optimization, Performance) - Funcionalidades SEO y compatibilidad con Rank Math - Sistema de posts relacionados y tabla de contenidos - Badge de categorías y manejo de AdSense diferido - Tipografías Google Fonts configurables - Documentación completa del tema y guías de uso 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
294
wp-content/themes/apus-theme/inc/related-posts.php
Normal file
294
wp-content/themes/apus-theme/inc/related-posts.php
Normal file
@@ -0,0 +1,294 @@
|
||||
<?php
|
||||
/**
|
||||
* Related Posts Functionality
|
||||
*
|
||||
* Provides configurable related posts functionality with Bootstrap grid support.
|
||||
*
|
||||
* @package Apus_Theme
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get related posts based on categories
|
||||
*
|
||||
* @param int $post_id The post ID to get related posts for
|
||||
* @return WP_Query|false Query object with related posts or false if none found
|
||||
*/
|
||||
function apus_get_related_posts($post_id) {
|
||||
// Get post categories
|
||||
$categories = wp_get_post_categories($post_id);
|
||||
|
||||
if (empty($categories)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get number of posts to display (default: 3)
|
||||
$posts_per_page = get_option('apus_related_posts_count', 3);
|
||||
|
||||
// Query arguments
|
||||
$args = array(
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => $posts_per_page,
|
||||
'post__not_in' => array($post_id),
|
||||
'category__in' => $categories,
|
||||
'orderby' => 'rand',
|
||||
'no_found_rows' => true,
|
||||
'update_post_meta_cache' => false,
|
||||
'update_post_term_cache' => false,
|
||||
);
|
||||
|
||||
// Allow filtering of query args
|
||||
$args = apply_filters('apus_related_posts_args', $args, $post_id);
|
||||
|
||||
// Get related posts
|
||||
$related_query = new WP_Query($args);
|
||||
|
||||
return $related_query->have_posts() ? $related_query : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display related posts section
|
||||
*
|
||||
* @param int|null $post_id Optional. Post ID. Default is current post.
|
||||
* @return void
|
||||
*/
|
||||
function apus_display_related_posts($post_id = null) {
|
||||
// Get post ID
|
||||
if (!$post_id) {
|
||||
$post_id = get_the_ID();
|
||||
}
|
||||
|
||||
// Check if related posts are enabled
|
||||
$enabled = get_option('apus_related_posts_enabled', true);
|
||||
if (!$enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get related posts
|
||||
$related_query = apus_get_related_posts($post_id);
|
||||
|
||||
if (!$related_query) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get configuration options
|
||||
$title = get_option('apus_related_posts_title', __('Related Posts', 'apus-theme'));
|
||||
$columns = get_option('apus_related_posts_columns', 3);
|
||||
$show_excerpt = get_option('apus_related_posts_show_excerpt', true);
|
||||
$show_date = get_option('apus_related_posts_show_date', true);
|
||||
$show_category = get_option('apus_related_posts_show_category', true);
|
||||
$excerpt_length = get_option('apus_related_posts_excerpt_length', 20);
|
||||
$background_colors = get_option('apus_related_posts_bg_colors', array(
|
||||
'#1a73e8', // Blue
|
||||
'#e91e63', // Pink
|
||||
'#4caf50', // Green
|
||||
'#ff9800', // Orange
|
||||
'#9c27b0', // Purple
|
||||
'#00bcd4', // Cyan
|
||||
));
|
||||
|
||||
// Calculate Bootstrap column class
|
||||
$col_class = apus_get_column_class($columns);
|
||||
|
||||
// Start output
|
||||
?>
|
||||
<section class="related-posts-section">
|
||||
<div class="related-posts-container">
|
||||
|
||||
<?php if ($title) : ?>
|
||||
<h2 class="related-posts-title"><?php echo esc_html($title); ?></h2>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="row g-4">
|
||||
<?php
|
||||
$color_index = 0;
|
||||
while ($related_query->have_posts()) :
|
||||
$related_query->the_post();
|
||||
$has_thumbnail = has_post_thumbnail();
|
||||
|
||||
// Get background color for posts without image
|
||||
$bg_color = $background_colors[$color_index % count($background_colors)];
|
||||
$color_index++;
|
||||
?>
|
||||
|
||||
<div class="<?php echo esc_attr($col_class); ?>">
|
||||
<article class="related-post-card <?php echo $has_thumbnail ? 'has-thumbnail' : 'no-thumbnail'; ?>">
|
||||
|
||||
<a href="<?php the_permalink(); ?>" class="related-post-link">
|
||||
|
||||
<?php if ($has_thumbnail) : ?>
|
||||
<!-- Card with Image -->
|
||||
<div class="related-post-thumbnail">
|
||||
<?php
|
||||
the_post_thumbnail('apus-thumbnail', array(
|
||||
'alt' => the_title_attribute(array('echo' => false)),
|
||||
'loading' => 'lazy',
|
||||
));
|
||||
?>
|
||||
|
||||
<?php if ($show_category) : ?>
|
||||
<?php
|
||||
$categories = get_the_category();
|
||||
if (!empty($categories)) :
|
||||
$category = $categories[0];
|
||||
?>
|
||||
<span class="related-post-category">
|
||||
<?php echo esc_html($category->name); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<!-- Card without Image - Color Background -->
|
||||
<div class="related-post-no-image" style="background-color: <?php echo esc_attr($bg_color); ?>;">
|
||||
<div class="related-post-no-image-content">
|
||||
<h3 class="related-post-no-image-title">
|
||||
<?php the_title(); ?>
|
||||
</h3>
|
||||
|
||||
<?php if ($show_category) : ?>
|
||||
<?php
|
||||
$categories = get_the_category();
|
||||
if (!empty($categories)) :
|
||||
$category = $categories[0];
|
||||
?>
|
||||
<span class="related-post-category no-image">
|
||||
<?php echo esc_html($category->name); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="related-post-content">
|
||||
|
||||
<?php if ($has_thumbnail) : ?>
|
||||
<h3 class="related-post-title">
|
||||
<?php the_title(); ?>
|
||||
</h3>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($show_excerpt && $excerpt_length > 0) : ?>
|
||||
<div class="related-post-excerpt">
|
||||
<?php echo wp_trim_words(get_the_excerpt(), $excerpt_length, '...'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($show_date) : ?>
|
||||
<div class="related-post-meta">
|
||||
<time class="related-post-date" datetime="<?php echo esc_attr(get_the_date('c')); ?>">
|
||||
<?php echo esc_html(get_the_date()); ?>
|
||||
</time>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
|
||||
</a>
|
||||
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<?php endwhile; ?>
|
||||
</div><!-- .row -->
|
||||
|
||||
</div><!-- .related-posts-container -->
|
||||
</section><!-- .related-posts-section -->
|
||||
|
||||
<?php
|
||||
// Reset post data
|
||||
wp_reset_postdata();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Bootstrap column class based on number of columns
|
||||
*
|
||||
* @param int $columns Number of columns (1-4)
|
||||
* @return string Bootstrap column classes
|
||||
*/
|
||||
function apus_get_column_class($columns) {
|
||||
$columns = absint($columns);
|
||||
|
||||
switch ($columns) {
|
||||
case 1:
|
||||
return 'col-12';
|
||||
case 2:
|
||||
return 'col-12 col-md-6';
|
||||
case 3:
|
||||
return 'col-12 col-sm-6 col-lg-4';
|
||||
case 4:
|
||||
return 'col-12 col-sm-6 col-lg-3';
|
||||
default:
|
||||
return 'col-12 col-sm-6 col-lg-4'; // Default to 3 columns
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook related posts display after post content
|
||||
*/
|
||||
function apus_hook_related_posts() {
|
||||
if (is_single() && !is_attachment()) {
|
||||
apus_display_related_posts();
|
||||
}
|
||||
}
|
||||
add_action('apus_after_post_content', 'apus_hook_related_posts');
|
||||
|
||||
/**
|
||||
* Enqueue related posts styles
|
||||
*/
|
||||
function apus_enqueue_related_posts_styles() {
|
||||
if (is_single() && !is_attachment()) {
|
||||
$enabled = get_option('apus_related_posts_enabled', true);
|
||||
|
||||
if ($enabled) {
|
||||
wp_enqueue_style(
|
||||
'apus-related-posts',
|
||||
get_template_directory_uri() . '/assets/css/related-posts.css',
|
||||
array('apus-bootstrap'),
|
||||
APUS_VERSION,
|
||||
'all'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'apus_enqueue_related_posts_styles');
|
||||
|
||||
/**
|
||||
* Register related posts settings
|
||||
* These can be configured via theme options or customizer
|
||||
*/
|
||||
function apus_related_posts_default_options() {
|
||||
// Set default options if they don't exist
|
||||
$defaults = array(
|
||||
'apus_related_posts_enabled' => true,
|
||||
'apus_related_posts_title' => __('Related Posts', 'apus-theme'),
|
||||
'apus_related_posts_count' => 3,
|
||||
'apus_related_posts_columns' => 3,
|
||||
'apus_related_posts_show_excerpt' => true,
|
||||
'apus_related_posts_excerpt_length' => 20,
|
||||
'apus_related_posts_show_date' => true,
|
||||
'apus_related_posts_show_category' => true,
|
||||
'apus_related_posts_bg_colors' => array(
|
||||
'#1a73e8', // Blue
|
||||
'#e91e63', // Pink
|
||||
'#4caf50', // Green
|
||||
'#ff9800', // Orange
|
||||
'#9c27b0', // Purple
|
||||
'#00bcd4', // Cyan
|
||||
),
|
||||
);
|
||||
|
||||
foreach ($defaults as $option => $value) {
|
||||
if (get_option($option) === false) {
|
||||
add_option($option, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action('after_setup_theme', 'apus_related_posts_default_options');
|
||||
Reference in New Issue
Block a user