{"id":315,"date":"2026-05-13T18:00:27","date_gmt":"2026-05-13T21:00:27","guid":{"rendered":"https:\/\/neodoor.neo\/?post_type=neodoor_aula&#038;p=315"},"modified":"2026-05-21T09:05:20","modified_gmt":"2026-05-21T12:05:20","slug":"sitemap-admin-editor","status":"publish","type":"post","link":"https:\/\/www.portanova.com.br\/notebook\/sitemap-admin-editor\/","title":{"rendered":"[MU] Sitemap para o admin-menu-editor"},"content":{"rendered":"<h2>Aula: Sitemap para uso do MU &#8216;Admin Menu Editor&#8217; e ocultar categorias vazias<\/h2>\n<p><strong>Melhoria implementada:<\/strong> No sitemap unificado, categorias e subcategorias que n\u00e3o cont\u00eam nenhum post (do tipo correspondente: post normal ou aula) agora s\u00e3o automaticamente ocultadas, deixando o \u00edndice muito mais limpo e profissional.<\/p>\n<p>Na fun\u00e7\u00e3o <code>neodoor_render_taxonomy_section<\/code>, iteramos sobre as subcategorias e, para cada uma, contamos quantos posts do tipo atual existem. Se zero, pulamos a subcategoria. Se ap\u00f3s esse filtro uma categoria pai ficar sem nenhuma subcategoria, a categoria pai tamb\u00e9m \u00e9 ocultada.<\/p>\n<p>Abaixo est\u00e1 o c\u00f3digo completo do MU-Plugin <strong>neodoor-sitemaps-unified.php<\/strong> com a melhoria inclu\u00edda. Substitua o arquivo existente por este.<\/p>\n<pre><code>&lt;?php\n\/**\n * Plugin Name:  Neodoor Sitemaps Unified\n * Description:  Sitemaps HTML: [sitemap_wp] (posts), [sitemap_lessons] (aulas), [sitemap_completo] (ambos). Oculta categorias sem posts.\n * Version:      2.1\n * Author:       Reinaldo (Neodoor.neo)\n *\/\n\ndefined( 'ABSPATH' ) || exit;\n\nadd_shortcode( 'sitemap_wp', 'neodoor_sitemap_wp_shortcode' );\nadd_shortcode( 'sitemap_lessons', 'neodoor_sitemap_lessons_shortcode' );\nadd_shortcode( 'sitemap_completo', 'neodoor_sitemap_full_shortcode' );\n\nfunction neodoor_sitemap_wp_shortcode() {\n    return neodoor_sitemap_render( 'post', 'Blog' );\n}\n\nfunction neodoor_sitemap_lessons_shortcode() {\n    return neodoor_sitemap_render( 'neodoor_aula', 'Caderno de Estudos' );\n}\n\nfunction neodoor_sitemap_full_shortcode() {\n    $html = '&lt;div class=\"neodoor-sitemap-wrapper\"&gt;';\n    $html .= neodoor_sitemap_render( 'post', 'Blog' );\n    $html .= neodoor_sitemap_render( 'neodoor_aula', 'Caderno de Estudos' );\n    $html .= '&lt;\/div&gt;';\n    return $html;\n}\n\nfunction neodoor_sitemap_render( $post_type, $title ) {\n    ob_start();\n    ?&gt;\n    &lt;div class=\"sitemap-section\"&gt;\n        &lt;h2&gt;&lt;?php echo esc_html( $title ); ?&gt;&lt;\/h2&gt;\n        &lt;?php echo neodoor_render_taxonomy_section( 'category', $post_type ); ?&gt;\n    &lt;\/div&gt;\n    &lt;?php\n    return ob_get_clean();\n}\n\n\/**\n * Renderiza categorias e subcategorias, ocultando aquelas sem posts do tipo atual.\n *\/\nfunction neodoor_render_taxonomy_section( $taxonomy = 'category', $post_type = 'post' ) {\n    $categorias_pai = get_terms( array(\n        'taxonomy'   =&gt; $taxonomy,\n        'parent'     =&gt; 0,\n        'hide_empty' =&gt; false,\n        'orderby'    =&gt; 'name',\n        'order'      =&gt; 'ASC',\n    ) );\n\n    if ( empty( $categorias_pai ) || is_wp_error( $categorias_pai ) ) {\n        return '&lt;p&gt;Nenhuma categoria encontrada para este tipo de conte\u00fado.&lt;\/p&gt;';\n    }\n\n    $html = '';\n    foreach ( $categorias_pai as $pai ) {\n        if ( $pai-&gt;term_id == 11 ) continue; \/\/ opcional\n\n        $subcategorias = get_terms( array(\n            'taxonomy'   =&gt; $taxonomy,\n            'parent'     =&gt; $pai-&gt;term_id,\n            'hide_empty' =&gt; false,\n            'orderby'    =&gt; 'name',\n            'order'      =&gt; 'ASC',\n        ) );\n\n        if ( empty( $subcategorias ) || is_wp_error( $subcategorias ) ) {\n            continue;\n        }\n\n        $has_any = false;\n        $subcat_html = '';\n\n        foreach ( $subcategorias as $subcat ) {\n            $total = neodoor_count_posts_in_term( $post_type, $subcat-&gt;term_id );\n            if ( $total == 0 ) continue;\n            $has_any = true;\n\n            $posts_iniciais = get_posts( array(\n                'post_type'      =&gt; $post_type,\n                'tax_query'      =&gt; array( array(\n                    'taxonomy' =&gt; $taxonomy,\n                    'field'    =&gt; 'term_id',\n                    'terms'    =&gt; $subcat-&gt;term_id,\n                ) ),\n                'post_status'    =&gt; 'publish',\n                'posts_per_page' =&gt; 5,\n                'orderby'        =&gt; 'date',\n                'order'          =&gt; 'DESC',\n            ) );\n\n            $subcat_html .= '&lt;div class=\"sitemap-subcategoria\"&gt;';\n            $subcat_html .= '&lt;h5&gt;' . esc_html( $subcat-&gt;name ) . '&lt;\/h5&gt;';\n            $subcat_html .= '&lt;ul class=\"sitemap-posts-list\" id=\"sitemap-list-' . $post_type . '-' . $subcat-&gt;term_id . '\"&gt;';\n            foreach ( $posts_iniciais as $post ) {\n                $subcat_html .= sprintf( '&lt;li&gt;&lt;a href=\"%s\"&gt;%s&lt;\/a&gt; (%s)&lt;\/li&gt;',\n                    esc_url( get_permalink( $post ) ),\n                    esc_html( $post-&gt;post_title ),\n                    get_the_date( 'd\/m\/Y', $post )\n                );\n            }\n            $subcat_html .= '&lt;\/ul&gt;';\n\n            if ( $total &gt; 5 ) {\n                $subcat_html .= '&lt;button class=\"sitemap-load-more\" \n                    data-term_id=\"' . esc_attr( $subcat-&gt;term_id ) . '\"\n                    data-post_type=\"' . esc_attr( $post_type ) . '\"\n                    data-offset=\"5\"\n                    data-total=\"' . esc_attr( $total ) . '\"\n                    data-per_page=\"5\"&gt;Carregar mais&lt;\/button&gt;';\n                $subcat_html .= '&lt;span class=\"sitemap-loading\" style=\"display:none;\"&gt;Carregando...&lt;\/span&gt;';\n            }\n            $subcat_html .= '&lt;\/div&gt;';\n        }\n\n        if ( $has_any ) {\n            $html .= '&lt;div class=\"sitemap-categoria\"&gt;&lt;h4&gt;' . esc_html( $pai-&gt;name ) . '&lt;\/h4&gt;' . $subcat_html . '&lt;\/div&gt;';\n        }\n    }\n    return $html;\n}\n\nfunction neodoor_count_posts_in_term( $post_type, $term_id ) {\n    $query = new WP_Query( array(\n        'post_type'      =&gt; $post_type,\n        'tax_query'      =&gt; array( array(\n            'taxonomy' =&gt; 'category',\n            'field'    =&gt; 'term_id',\n            'terms'    =&gt; $term_id,\n        ) ),\n        'post_status'    =&gt; 'publish',\n        'posts_per_page' =&gt; -1,\n        'fields'         =&gt; 'ids',\n    ) );\n    $count = $query-&gt;post_count;\n    wp_reset_postdata();\n    return $count;\n}\n\nadd_action( 'wp_ajax_neodoor_sitemap_load_more', 'neodoor_sitemap_ajax_handler' );\nadd_action( 'wp_ajax_nopriv_neodoor_sitemap_load_more', 'neodoor_sitemap_ajax_handler' );\n\nfunction neodoor_sitemap_ajax_handler() {\n    $term_id    = intval( $_POST['term_id'] );\n    $offset     = intval( $_POST['offset'] );\n    $per_page   = intval( $_POST['posts_per_page'] );\n    $post_type  = sanitize_key( $_POST['post_type'] );\n\n    if ( ! $term_id ) wp_send_json_error( 'Termo inv\u00e1lido' );\n\n    $posts = get_posts( array(\n        'post_type'      =&gt; $post_type,\n        'tax_query'      =&gt; array( array(\n            'taxonomy' =&gt; 'category',\n            'field'    =&gt; 'term_id',\n            'terms'    =&gt; $term_id,\n        ) ),\n        'post_status'    =&gt; 'publish',\n        'posts_per_page' =&gt; $per_page,\n        'offset'         =&gt; $offset,\n        'orderby'        =&gt; 'date',\n        'order'          =&gt; 'DESC',\n    ) );\n\n    $html = '';\n    $count = 0;\n    foreach ( $posts as $post ) {\n        $html .= sprintf( '&lt;li&gt;&lt;a href=\"%s\"&gt;%s&lt;\/a&gt; (%s)&lt;\/li&gt;',\n            esc_url( get_permalink( $post ) ),\n            esc_html( $post-&gt;post_title ),\n            get_the_date( 'd\/m\/Y', $post )\n        );\n        $count++;\n    }\n    wp_send_json_success( array( 'html' =&gt; $html, 'count' =&gt; $count ) );\n}\n<\/code><\/pre>\n<h3>Como testar<\/h3>\n<ul>\n<li>Crie uma categoria &#8220;Teste&#8221; sem nenhum post associado a ela.<\/li>\n<li>Visualize a p\u00e1gina que usa <code>[sitemap_wp]<\/code> \u2013 a categoria n\u00e3o aparecer\u00e1.<\/li>\n<li>Adicione um post do tipo correto a essa categoria e recarregue \u2013 agora ela aparece.<\/li>\n<\/ul>\n<p><strong>Registro no caderno:<\/strong> data <!--?php echo date('d\/m\/Y'); ?--> \u2013 melhoria de usabilidade no sitemap, ocultando automaticamente se\u00e7\u00f5es vazias.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Aula: Sitemap para uso do MU &#8216;Admin Menu Editor&#8217; e ocultar categorias vazias Melhoria implementada: No sitemap unificado, categorias e subcategorias que n\u00e3o cont\u00eam nenhum post (do tipo correspondente: post normal ou aula) agora s\u00e3o automaticamente ocultadas, deixando o \u00edndice muito mais limpo e profissional. Na fun\u00e7\u00e3o neodoor_render_taxonomy_section, iteramos sobre as subcategorias e, para cada [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,4],"tags":[],"class_list":["post-315","post","type-post","status-publish","format-standard","hentry","category-lessons","category-pluginsmu"],"_links":{"self":[{"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/posts\/315","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/comments?post=315"}],"version-history":[{"count":0,"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/posts\/315\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/media?parent=315"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/categories?post=315"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/tags?post=315"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}