┌────────────────────────────────┐ │ ░░░ ░░▓ ░▓▓ ███ ▓▓░ ▓░░ │ │ ~ M O O N ~ │ └────────────────────────────────┘
prd-web-01.centraldc.gr
LOCATION:
/var/www/html/adconect/wp-content/plugins/widget-pages
☗ ROOT
↻ REFRESH
✎ EDIT FILE
EDITING: widget-pages.php
<?php /** * Plugin Name: Custom Widgets as Pages * Description: Description: Manage theme-specific layouts by hijacking sidebar output. Automatically tracks registered sidebar IDs for each theme (compatible with Theme Switcha). Shortcodes: [theme_section id="sidebar-id"] or [theme_section id="any-id" theme="theme-slug"]. Logic: Replaces dynamic_sidebar() output with custom HTML/Blocks from the matching Layout Post. Zero database bloat—reverts to default widgets when deactivated. * Version: 2.2.0 * Author: Giannis Giannopoulos / ai */ if (!defined('ABSPATH')) exit; define('CTG_CPT', 'theme_layout'); /* ============================================= 1. PLUGIN ACTION LINKS (Settings Link) ============================================= */ add_filter('plugin_action_links_' . plugin_basename(__FILE__), function($links) { $settings_link = '<a href="' . admin_url('edit.php?post_type=' . CTG_CPT) . '">Settings</a>'; array_unshift($links, $settings_link); return $links; }); /* ============================================= 2. REGISTER CPT & SHORTCODES ============================================= */ add_action('init', 'ctg_register_core'); function ctg_register_core() { register_post_type(CTG_CPT, [ 'labels' => [ 'name' => 'Theme Layouts', 'singular_name' => 'Theme Layout', 'add_new' => 'Add New Layout', 'edit_item' => 'Edit Layout', 'all_items' => 'Theme Layouts', ], 'public' => true, 'show_ui' => true, 'show_in_menu' => 'themes.php', 'supports' => array('title', 'editor', 'revisions', 'slug'), 'show_in_rest' => true, 'menu_icon' => 'dashicons-layout', ]); add_shortcode('theme_section', 'ctg_shortcode_handler'); add_shortcode('theme_widget', 'ctg_shortcode_handler'); } function ctg_shortcode_handler($atts) { $a = shortcode_atts([ 'id' => '', 'theme' => get_stylesheet(), ], $atts); if (empty($a['id'])) return ''; return get_theme_group_content_by_slug($a['id'], $a['theme']); } /* ============================================= 3. VISUAL EDITOR GUIDES (TOP-LEVEL) ============================================= */ add_action('enqueue_block_editor_assets', function() { $post = get_post(); if (!$post || $post->post_type !== CTG_CPT) return; $custom_css = " .is-root-container > .wp-block, .is-root-container > div, .is-root-container > section { outline: 1px dashed #bbb !important; outline-offset: 10px; margin-bottom: 40px !important; position: relative; } .is-root-container > .wp-block::after, .is-root-container > div::after { content: 'Layout Section'; position: absolute; top: -12px; right: 0; font-size: 9px; color: #999; text-transform: uppercase; letter-spacing: 1px; } "; wp_add_inline_style('wp-edit-blocks', $custom_css); }); /* ============================================= 4. ADMIN BAR STATUS ============================================= */ add_action('admin_bar_menu', function($wp_admin_bar) { if (!current_user_can('manage_options')) return; $theme_slug = get_stylesheet(); $layout = get_posts(['name' => $theme_slug, 'post_type' => CTG_CPT, 'post_status' => 'publish', 'posts_per_page' => 1]); $is_active = !empty($layout); $wp_admin_bar->add_node([ 'id' => 'ctg_status', 'title' => '<span style="color:' . ($is_active ? '#46b450' : '#ccc') . '; font-weight:bold;">' . ($is_active ? '● Layout: ACTIVE' : '○ Layout: Inactive') . '</span>', 'href' => admin_url('edit.php?post_type=' . CTG_CPT), ]); }, 999); /* ============================================= 5. CORE LOGIC (HIJACK & DOM) ============================================= */ function get_theme_group_content_by_slug($group_id, $theme_slug) { $args = [ 'name' => $theme_slug, 'post_type' => CTG_CPT, 'post_status' => 'publish', 'posts_per_page' => 1 ]; $layouts = get_posts($args); if (empty($layouts)) return false; $content = $layouts[0]->post_content; if (empty(trim($content))) return false; $dom = new DOMDocument(); // Φορτώνουμε το περιεχόμενο. // ΠΡΟΣΟΧΗ: Αφαιρούμε το LIBXML_HTML_NOIMPLIED για να φτιάξει το DOM σωστή δομή body @$dom->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NODEFDTD); $xpath = new DOMXPath($dom); /** * Η ΑΠΟΛΥΤΗ ROOT ΑΝΑΖΗΤΗΣΗ: * Ψάχνουμε ΜΟΝΟ για στοιχεία που είναι άμεσοι απόγονοι του body. * Το XPath //body/* σημαίνει: "Μπες στο body και κοίτα μόνο το πρώτο επίπεδο". */ $node = $xpath->query("//body/*[@id='$group_id']")->item(0); if ($node) { $inner_html = ''; foreach ($node->childNodes as $child) { $inner_html .= $dom->saveHTML($child); } return apply_filters('the_content', $inner_html); } return false; } function get_theme_group_content($sidebar_id) { return get_theme_group_content_by_slug($sidebar_id, get_stylesheet()); } add_filter('sidebars_widgets', function($sidebars) { if (is_admin()) return $sidebars; global $wp_registered_sidebars; foreach ($sidebars as $sidebar_id => $widgets) { if ($sidebar_id === 'wp_inactive_widgets') continue; if (isset($wp_registered_sidebars[$sidebar_id]) && get_theme_group_content($sidebar_id) !== false) { $sidebars[$sidebar_id] = ['ctg-placeholder-widget']; } } return $sidebars; }, 999); add_filter('dynamic_sidebar_has_widgets', function($has_widgets, $sidebar_id) { $content = get_theme_group_content($sidebar_id); if ($content !== false) { echo $content; return false; } return $has_widgets; }, 10, 2); /* ============================================= 6. METABOX & COLUMNS ============================================= */ add_action('add_meta_boxes', function() { add_meta_box('ctg_ids_info', 'Theme Info & Sidebar IDs', 'ctg_ids_metabox_callback', CTG_CPT, 'side'); }); function ctg_ids_metabox_callback($post) { $layout_slug = $post->post_name; $active_theme = get_stylesheet(); $theme = wp_get_theme($layout_slug); echo '<div style="padding:10px; background:#f0f0f1; border:1px solid #ccc; margin-bottom:15px; border-radius:4px;">'; echo '<small style="display:block; text-transform:uppercase; color:#666;">Active Site Theme:</small>'; echo '<strong style="color:#d63638; font-size:14px;">' . esc_html($active_theme) . '</strong>'; echo '</div>'; if ($theme->exists() && ($img = $theme->get_screenshot())) { echo '<div style="margin-bottom:15px;"><img src="'.esc_url($img).'" style="width:100%; height:auto; border:1px solid #ddd; border-radius:4px;"></div>'; } $saved_ids = get_option('ctg_ids_' . $layout_slug); if ($saved_ids) { echo '<p><strong>Sidebar IDs:</strong></p>'; echo '<ul style="background:#f9f9f9; padding:10px; border:1px solid #ddd; max-height:200px; overflow:auto; list-style:none; margin:0;">'; foreach ($saved_ids as $id => $name) { echo '<li style="margin-bottom:8px; border-bottom:1px solid #eee;"><code style="font-weight:bold; color:#2271b1;">' . esc_html($id) . '</code><br><small>' . esc_html($name) . '</small></li>'; } echo '</ul>'; } else { echo '<p style="font-size:11px; color:#666;">Activate "'.esc_html($layout_slug).'" once to sync IDs.</p>'; } } add_filter('manage_' . CTG_CPT . '_posts_columns', function($columns) { $new = []; foreach($columns as $k => $v) { if($k === 'title') $new['screenshot'] = 'Preview'; $new[$k] = $v; if($k === 'title') $new['slug_status'] = 'Theme Slug'; } return $new; }); add_action('manage_' . CTG_CPT . '_posts_custom_column', function($column, $post_id) { $slug = get_post_field('post_name', $post_id); $active = get_stylesheet(); $theme = wp_get_theme($slug); if ($column === 'screenshot' && $theme->exists()) { $img = $theme->get_screenshot(); echo $img ? '<img src="'.esc_url($img).'" style="width:60px; border-radius:4px;">' : ''; } if ($column === 'slug_status') { echo ($slug === $active ? '<b style="color:#d63638;">*</b> ' : '') . '<code>' . esc_html($slug) . '</code>'; } }, 10, 2); /* ============================================= 7. AUTO-SYNC & INITIALIZE ============================================= */ add_action('admin_init', function() { global $wp_registered_sidebars; if (empty($wp_registered_sidebars)) return; update_option('ctg_ids_' . get_stylesheet(), array_map(fn($s) => $s['name'], $wp_registered_sidebars)); }); add_action('admin_init', 'ctg_ensure_layout_exists'); function ctg_ensure_layout_exists() { if (!is_admin() || (defined('DOING_AJAX') && DOING_AJAX)) return; $theme_slug = get_stylesheet(); $existing = get_posts(['name' => $theme_slug, 'post_type' => CTG_CPT, 'post_status' => 'any', 'posts_per_page' => 1]); if (empty($existing)) { wp_insert_post(['post_title' => ucfirst($theme_slug).' Layout', 'post_name' => $theme_slug, 'post_status' => 'publish', 'post_type' => CTG_CPT, 'post_content' => '<div id="sidebar-1"></div>']); } }
CANCEL
Name
Type
Size
Modified
Actions
↩ ..
DIR
—
—
📄 widget-pages.php
PHP
9.7 KB
2026-05-15 14:20
EDIT