. add_action('template_redirect', array($this, 'precompute_active_templates'), 100); // Collecter aussi les template parts rencontrés dynamiquement lors du rendu // (filets de sécurité si parse_blocks n'a pas suffi, cas rares). add_filter('render_block', array($this, 'collect_rendered_template_part'), 10, 2); add_action('wp_head', array($this, 'output_templates_css'), 999); add_action('wp_footer', array($this, 'output_templates_js'), 999); } /** * Renvoie la liste des clés de templates/parts actifs sur la requête courante. * * @return array */ private function get_active_template_keys() { $keys = array(); if (!empty($GLOBALS['aibui_active_template_main_id'])) { $keys[] = 'wp_template:' . $GLOBALS['aibui_active_template_main_id']; } if (!empty($GLOBALS['aibui_active_template_parts']) && is_array($GLOBALS['aibui_active_template_parts'])) { foreach ($GLOBALS['aibui_active_template_parts'] as $part_id => $_) { $keys[] = 'wp_template_part:' . $part_id; } } return array_values(array_unique($keys)); } /** * Résout l'ID (theme//slug) du block template principal utilisé pour la requête courante. */ private function resolve_current_template_id() { if (!wp_is_block_theme()) { return null; } if (!empty($GLOBALS['_wp_current_template_id'])) { return (string) $GLOBALS['_wp_current_template_id']; } $slug = $this->resolve_template_slug_from_query(); if (!$slug) { return null; } $theme = get_stylesheet(); return $theme . '//' . $slug; } /** * Déduit le slug du template à utiliser en se basant sur la WP Query courante. * Ordre approximatif de la hiérarchie des templates block themes. */ private function resolve_template_slug_from_query() { if (is_embed()) { return 'embed'; } if (is_404()) { return '404'; } if (is_search()) { return 'search'; } if (is_front_page()) { return 'front-page'; } if (is_home()) { return 'home'; } if (is_singular()) { $obj = get_queried_object(); if ($obj && isset($obj->ID)) { $assigned = get_page_template_slug($obj->ID); if ($assigned) { return $assigned; } } if (is_page()) { return 'page'; } if (is_attachment()) { return 'attachment'; } if (is_single()) { return 'single'; } return 'singular'; } if (is_category()) { return 'category'; } if (is_tag()) { return 'tag'; } if (is_tax()) { return 'taxonomy'; } if (is_author()) { return 'author'; } if (is_date()) { return 'date'; } if (is_archive()) { return 'archive'; } return 'index'; } /** * Parcourt récursivement les blocs pour détecter les core/template-part * et enregistrer leurs identifiants dans un global partagé. * * @param array $blocks * @param int $depth */ private function walk_blocks_for_template_parts($blocks, $depth = 0) { if ($depth > 10 || empty($blocks) || !is_array($blocks)) { return; } foreach ($blocks as $block) { if (!is_array($block)) { continue; } if (!empty($block['blockName']) && $block['blockName'] === 'core/template-part') { $slug = isset($block['attrs']['slug']) ? (string) $block['attrs']['slug'] : ''; if ($slug !== '') { $theme = !empty($block['attrs']['theme']) ? (string) $block['attrs']['theme'] : get_stylesheet(); $part_id = $theme . '//' . $slug; if (empty($GLOBALS['aibui_active_template_parts'][$part_id])) { $GLOBALS['aibui_active_template_parts'][$part_id] = true; // Descendre récursivement dans le contenu du template part $part = function_exists('get_block_template') ? get_block_template($part_id, 'wp_template_part') : null; if ($part && !empty($part->content)) { $this->walk_blocks_for_template_parts( parse_blocks($part->content), $depth + 1 ); } } } } if (!empty($block['innerBlocks']) && is_array($block['innerBlocks'])) { $this->walk_blocks_for_template_parts($block['innerBlocks'], $depth + 1); } } } public function precompute_active_templates() { if (is_admin() || !wp_is_block_theme()) { return; } $template_id = $this->resolve_current_template_id(); if (!$template_id) { return; } $GLOBALS['aibui_active_template_main_id'] = $template_id; $GLOBALS['aibui_active_template_parts'] = isset($GLOBALS['aibui_active_template_parts']) && is_array($GLOBALS['aibui_active_template_parts']) ? $GLOBALS['aibui_active_template_parts'] : array(); if (!function_exists('get_block_template')) { return; } $template = get_block_template($template_id, 'wp_template'); if (!$template || empty($template->content)) { return; } $this->walk_blocks_for_template_parts(parse_blocks($template->content)); } /** * Filet de sécurité : détecter les core/template-part rendus dynamiquement * (via render_block) pour compléter la liste précalculée. */ public function collect_rendered_template_part($block_content, $block) { if (empty($block['blockName']) || $block['blockName'] !== 'core/template-part') { return $block_content; } $slug = isset($block['attrs']['slug']) ? (string) $block['attrs']['slug'] : ''; if ($slug === '') { return $block_content; } $theme = !empty($block['attrs']['theme']) ? (string) $block['attrs']['theme'] : get_stylesheet(); $id = $theme . '//' . $slug; if (!isset($GLOBALS['aibui_active_template_parts']) || !is_array($GLOBALS['aibui_active_template_parts'])) { $GLOBALS['aibui_active_template_parts'] = array(); } $GLOBALS['aibui_active_template_parts'][$id] = true; return $block_content; } public function output_templates_css() { $keys = $this->get_active_template_keys(); if (empty($keys)) { return; } $all = get_option('ai_builder_templates_css', array()); if (!is_array($all)) { return; } $buffer = ''; foreach ($keys as $key) { if (!empty($all[$key]['combined'])) { $buffer .= "\n" . $all[$key]['combined']; } } if (trim($buffer) === '') { return; } echo ''; } public function output_templates_js() { $keys = $this->get_active_template_keys(); if (empty($keys)) { return; } $all = get_option('ai_builder_templates_js', array()); if (!is_array($all)) { return; } $buffer = ''; foreach ($keys as $key) { if (!empty($all[$key]['combined'])) { $buffer .= "\n" . $all[$key]['combined']; } } if (trim($buffer) === '') { return; } echo ''; } } new AIBUI_Templates_Assets_Handler();