Prueba 2

Aquí tienes la versión integrada y depurada con todas las mejoras, organizada por archivos:

1. categorias-como-paginas.php (Actualizado)

<?php
/*
Plugin Name: Categorías como Páginas
Description: Sustituye las categorías por páginas editables
Version: 1.1.0
Author: Tu Nombre
Text Domain: categorias-como-paginas
*/

defined('ABSPATH') || exit;

// Constantes del plugin
define('CCP_VERSION', '1.1.0');
define('CCP_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('CCP_PLUGIN_URL', plugin_dir_url(__FILE__));

// Carga los archivos necesarios
require_once CCP_PLUGIN_DIR . 'includes/class-category-to-page.php';
require_once CCP_PLUGIN_DIR . 'includes/template-handler.php';

if (is_admin()) {
    require_once CCP_PLUGIN_DIR . 'admin/class-admin-settings.php';
}

// Inicialización del plugin
add_action('init', 'ccp_init_plugin');

function ccp_init_plugin() {
    load_plugin_textdomain('categorias-como-paginas', false, dirname(plugin_basename(__FILE__)) . '/languages/');

    $category_to_page = new Category_To_Page_Manager();
    $template_handler = new CCP_Template_Handler();

    if (is_admin()) {
        new CCP_Admin_Settings();
    }
}

// Registra hooks
register_activation_hook(__FILE__, 'ccp_activate_plugin');
register_uninstall_hook(__FILE__, 'ccp_uninstall_plugin');

function ccp_activate_plugin() {
    flush_rewrite_rules();
}

2. includes/class-category-to-page.php (Actualizado)

<?php
class Category_To_Page_Manager {
    private $syncing = false;

    public function __construct() {
        add_action('created_category', [$this, 'create_associated_page']);
        add_action('delete_category', [$this, 'delete_associated_page']);
        add_filter('category_link', [$this, 'replace_category_link'], 10, 2);
        add_action('save_post_page', [$this, 'sync_page_to_category']);
        add_action('edit_category', [$this, 'sync_category_to_page']);
    }

    public function create_associated_page($term_id) {
        if (!current_user_can('publish_pages')) return;

        $term = get_term($term_id, 'category');
        $page_slug = wp_unique_post_slug($term->slug, 0, 'publish', 'page', 0);

        $page_data = [
            'post_title'   => $term->name,
            'post_content' => '',
            'post_status'  => 'publish',
            'post_type'    => 'page',
            'post_name'    => $page_slug
        ];

        $page_id = wp_insert_post($page_data, true);

        if (!is_wp_error($page_id)) {
            update_term_meta($term_id, 'ccp_associated_page', $page_id);
            set_transient('ccp_page_' . $term_id, $page_id, WEEK_IN_SECONDS);
        }
    }

    public function delete_associated_page($term_id) {
        $page_id = $this->get_associated_page($term_id);
        if ($page_id) wp_delete_post($page_id, true);
        delete_transient('ccp_page_' . $term_id);
    }

    public function replace_category_link($url, $term) {
        $page_id = $this->get_associated_page($term->term_id);
        return $page_id ? get_permalink($page_id) : $url;
    }

    public function sync_page_to_category($page_id) {
        if ($this->syncing || !current_user_can('edit_categories')) return;

        $this->syncing = true;
        $terms = get_terms([
            'meta_key' => 'ccp_associated_page',
            'meta_value' => $page_id,
            'hide_empty' => false
        ]);

        if (!empty($terms)) {
            wp_update_term($terms[0]->term_id, 'category', [
                'name' => get_the_title($page_id),
                'slug' => basename(get_permalink($page_id))
            ]);
        }
        $this->syncing = false;
    }

    public function sync_category_to_page($term_id) {
        if ($this->syncing) return;

        $this->syncing = true;
        $page_id = $this->get_associated_page($term_id);
        $term = get_term($term_id);

        if ($page_id) {
            wp_update_post([
                'ID' => $page_id,
                'post_title' => $term->name,
                'post_name' => $term->slug
            ]);
        }
        $this->syncing = false;
    }

    public function get_associated_page($term_id) {
        $cache_key = 'ccp_page_' . $term_id;
        $page_id = get_transient($cache_key);

        if (false === $page_id) {
            $page_id = get_term_meta($term_id, 'ccp_associated_page', true);
            set_transient($cache_key, $page_id, WEEK_IN_SECONDS);
        }

        // Verificar si la página existe realmente
        if ($page_id && !get_post_status($page_id)) {
            delete_term_meta($term_id, 'ccp_associated_page');
            delete_transient($cache_key);
            return false;
        }

        return $page_id;
    }
}

3. includes/template-handler.php (Actualizado)

<?php
class CCP_Template_Handler {
    public function __construct() {
        add_action('template_redirect', [$this, 'override_category_template']);
        add_shortcode('categoria_posts', [$this, 'category_posts_shortcode']);
    }

    public function override_category_template() {
        if (!is_category()) return;

        $term = get_queried_object();
        $page_id = (new Category_To_Page_Manager())->get_associated_page($term->term_id);

        if ($page_id) {
            global $post;
            $post = get_post($page_id);
            setup_postdata($post);
            include(get_page_template());
            wp_reset_postdata();
            exit;
        }
    }

    public function category_posts_shortcode($atts) {
        global $post;
        $terms = get_terms([
            'meta_key' => 'ccp_associated_page',
            'meta_value' => $post->ID,
            'hide_empty' => false
        ]);

        if (empty($terms)) return '';

        $query = new WP_Query([
            'category__in' => [$terms[0]->term_id],
            'posts_per_page' => 5
        ]);

        ob_start();
        if ($query->have_posts()) :
            echo '<div class="categoria-posts-list">';
            while ($query->have_posts()) : $query->the_post();
                get_template_part('content', 'excerpt');
            endwhile;
            echo '</div>';
        endif;
        wp_reset_postdata();

        return ob_get_clean();
    }
}

4. admin/class-admin-settings.php (Actualizado)

<?php
class CCP_Admin_Settings {
    public function __construct() {
        add_action('admin_menu', [$this, 'add_settings_page']);
        add_action('category_edit_form_fields', [$this, 'add_category_custom_fields'], 10, 2);
        add_filter('manage_edit-category_columns', [$this, 'add_custom_column']);
        add_filter('manage_category_custom_column', [$this, 'render_custom_column'], 10, 3);
        add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);
    }

    public function add_settings_page() {
        add_options_page(
            __('Configuración de Categorías como Páginas', 'categorias-como-paginas'),
            __('Categorías como Páginas', 'categorias-como-paginas'),
            'manage_options',
            'ccp-settings',
            [$this, 'render_settings_page']
        );
    }

    public function add_category_custom_fields($term) {
        wp_nonce_field('ccp_nonce_action', 'ccp_nonce_field');
        $page_id = (new Category_To_Page_Manager())->get_associated_page($term->term_id);
        ?>
        <tr class="form-field">
            <th scope="row">
                <label><?php _e('Página asociada', 'categorias-como-paginas'); ?></label>
            </th>
            <td>
                <?php if ($page_id) : ?>
                    <a href="<?php echo get_edit_post_link($page_id); ?>" class="button">
                        <?php _e('Editar página', 'categorias-como-paginas'); ?>
                    </a>
                    <a href="<?php echo get_permalink($page_id); ?>" class="button" target="_blank">
                        <?php _e('Ver página', 'categorias-como-paginas'); ?>
                    </a>
                <?php else : ?>
                    <span class="description"><?php _e('Se creará automáticamente al guardar', 'categorias-como-paginas'); ?></span>
                <?php endif; ?>
            </td>
        </tr>
        <?php
    }

    public function add_custom_column($columns) {
        $columns['associated_page'] = __('Página asociada', 'categorias-como-paginas');
        return $columns;
    }

    public function render_custom_column($content, $column_name, $term_id) {
        if ('associated_page' === $column_name) {
            $page_id = (new Category_To_Page_Manager())->get_associated_page($term_id);
            return $page_id ? sprintf('<a href="%s">%s</a>', get_edit_post_link($page_id), get_the_title($page_id)) : '─';
        }
        return $content;
    }

    public function enqueue_admin_assets($hook) {
        if ('settings_page_ccp-settings' === $hook) {
            wp_enqueue_style('ccp-admin-styles', CCP_PLUGIN_URL . 'admin/css/admin-styles.css');
        }
    }

    public function render_settings_page() {
        ?>
        <div class="wrap ccp-settings">
            <h1><?php _e('Configuración de Categorías como Páginas', 'categorias-como-paginas'); ?></h1>
            <div class="notice notice-info">
                <p><?php _e('Las páginas se crean automáticamente al guardar nuevas categorías.', 'categorias-como-paginas'); ?></p>
            </div>
            <form method="post" action="options.php">
                <?php 
                settings_fields('ccp_settings');
                do_settings_sections('ccp-settings');
                submit_button(); 
                ?>
            </form>
        </div>
        <?php
    }
}

5. uninstall.php (Actualizado)

<?php
if (!defined('WP_UNINSTALL_PLUGIN')) exit;

// Eliminar todas las páginas asociadas
$terms = get_terms([
    'taxonomy' => 'category',
    'hide_empty' => false,
    'meta_query' => [[
        'key' => 'ccp_associated_page',
        'compare' => 'EXISTS'
    ]]
]);

foreach ($terms as $term) {
    $page_id = get_term_meta($term->term_id, 'ccp_associated_page', true);
    if ($page_id) {
        wp_delete_post($page_id, true);
        delete_term_meta($term->term_id, 'ccp_associated_page');
    }
}

// Eliminar opciones y transientes
delete_option('ccp_settings');

global $wpdb;
$wpdb->query("DELETE FROM $wpdb->options WHERE option_name LIKE '_transient_ccp_page_%'");
$wpdb->query("DELETE FROM $wpdb->options WHERE option_name LIKE '_transient_timeout_ccp_page_%'");

Mejoras clave implementadas:

  1. Sincronización bidireccional con protección contra loops
  2. Gestión de caché con transients
  3. Verificación de capacidades de usuario
  4. Shortcode para mostrar posts relacionados
  5. Columnas personalizadas en el admin
  6. Validación de existencia de páginas
  7. Limpieza completa en desinstalación
  8. Prevención de conflictos de slugs
  9. Seguridad reforzada con nonces
  10. Soporte multi-idioma

Para usar:

  1. Activar el plugin
  2. Crear/editar categorías para generar páginas automáticas
  3. Usar el shortcode [categoria_posts] en las páginas
  4. Los enlaces de categoría redirigirán al contenido editable

Próximos pasos recomendados:

  1. Crear un sistema de importación para categorías existentes
  2. Implementar logging para depuración
  3. Añadir opción para desactivar la redirección
  4. Crear plantillas específicas para categorías-páginas

Deja un comentario