{"id":799,"date":"2026-06-02T21:32:04","date_gmt":"2026-06-03T00:32:04","guid":{"rendered":"https:\/\/www.portanova.com.br\/notebook\/?p=799"},"modified":"2026-06-02T22:29:47","modified_gmt":"2026-06-03T01:29:47","slug":"wp-sitemap-de-rede","status":"publish","type":"post","link":"https:\/\/www.portanova.com.br\/notebook\/wp-sitemap-de-rede\/","title":{"rendered":"[WP] Sitemap de Rede (ID Blog, Categorias e &#8220;Carregar mais&#8221;)"},"content":{"rendered":"<h3>\ud83d\udcd8 MU-Plugin: Sitemap de Rede Avan\u00e7ado (com categorias e &#8220;Carregar mais&#8221;) \u2013 Vers\u00e3o 2.1<\/h3>\n<p><strong>Arquivo:<\/strong> <code>\/wp-content\/mu-plugins\/sitemap-rede.php<\/code><\/p>\n<p>Shortcode <code><code> rede_sitemap <\/code><\/code>: Atributos: <code>incluir<\/code> e <code>excluir<\/code> (IDs dos blogs). Colocar entre chaves<strong> [ rede _ sitemap ]<\/strong> e sem espa\u00e7os<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>T\u00edtulo do blog (link para a home)<\/li>\n<li>Categorias com pelo menos um post<\/li>\n<li>Os <strong>5 posts mais recentes<\/strong> de cada categoria<\/li>\n<li>Bot\u00e3o <strong>&#8220;Carregar mais&#8221;<\/strong> que, via AJAX, traz os pr\u00f3ximos 5 posts da categoria sem recarregar a p\u00e1gina.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Voc\u00ea pode filtrar quais blogs aparecem usando os atributos <code>incluir<\/code> ou <code>excluir<\/code>, ex: <code><code> rede_sitemap <\/code>rede_sitemap incluir=\"2,4\"<\/code>.<\/p>\n<p><strong>Arquivo:<\/strong> <code>\/wp-content\/mu-plugins\/sitemap-rede.php<\/code><\/p>\n<pre style=\"background: #cccccc; color: #f8f8f2; padding: 1rem; overflow-x: auto; border-radius: 8px;\"><code>&lt;?php\r\n\/**\r\n * Plugin Name: Sitemap de Rede \u2013 Vers\u00e3o 2.1 [  rede _ sitemap   ] sem espa\u00e7os\r\n * Description: Exibe blogs, categorias e os 5 posts mais recentes de cada categoria, com bot\u00e3o \"Carregar mais\" via AJAX.\r\n * Version: 2.1\r\n * Author: Reinaldo (Neodoor.neo)\r\n *\/\r\n\r\nif ( ! defined( 'ABSPATH' ) ) {\r\n    exit;\r\n}\r\n\r\nclass Sitemap_Rede {\r\n\r\n    public function __construct() {\r\n        add_shortcode( 'rede_sitemap', array( $this, 'exibir_sitemap' ) );\r\n        add_action( 'wp_ajax_carregar_mais_posts', array( $this, 'ajax_carregar_mais_posts' ) );\r\n        add_action( 'wp_ajax_nopriv_carregar_mais_posts', array( $this, 'ajax_carregar_mais_posts' ) );\r\n        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );\r\n    }\r\n\r\n    public function enqueue_scripts() {\r\n        global $post;\r\n        if ( is_a( $post, 'WP_Post' ) &amp;&amp; has_shortcode( $post-&gt;post_content, 'rede_sitemap' ) ) {\r\n            wp_enqueue_script( 'jquery' );\r\n            wp_add_inline_script(\r\n                'jquery',\r\n                'jQuery(document).ready(function($) {\r\n                    $(document).on(\"click\", \".sitemap-carregar-mais\", function(e) {\r\n                        e.preventDefault();\r\n                        var botao = $(this);\r\n                        var categoriaId = botao.data(\"categoria-id\");\r\n                        var blogId = botao.data(\"blog-id\");\r\n                        var offset = botao.data(\"offset\");\r\n                        var container = botao.siblings(\".sitemap-lista-posts\");\r\n\r\n                        $.ajax({\r\n                            url: \"' . admin_url( 'admin-ajax.php' ) . '\",\r\n                            type: \"POST\",\r\n                            data: {\r\n                                action: \"carregar_mais_posts\",\r\n                                blog_id: blogId,\r\n                                category_id: categoriaId,\r\n                                offset: offset\r\n                            },\r\n                            beforeSend: function() {\r\n                                botao.text(\"Carregando...\");\r\n                            },\r\n                            success: function(response) {\r\n                                if (response.success) {\r\n                                    container.append(response.data.html);\r\n                                    botao.data(\"offset\", offset + 5);\r\n                                    if (!response.data.has_more) {\r\n                                        botao.remove();\r\n                                    } else {\r\n                                        botao.text(\"Carregar mais\");\r\n                                    }\r\n                                } else {\r\n                                    alert(\"Erro ao carregar mais posts.\");\r\n                                    botao.text(\"Tentar novamente\");\r\n                                }\r\n                            },\r\n                            error: function() {\r\n                                alert(\"Erro na requisi\u00e7\u00e3o.\");\r\n                                botao.text(\"Tentar novamente\");\r\n                            }\r\n                        });\r\n                    });\r\n                });'\r\n            );\r\n        }\r\n    }\r\n\r\n    public function ajax_carregar_mais_posts() {\r\n        $blog_id      = intval( $_POST['blog_id'] );\r\n        $category_id  = intval( $_POST['category_id'] );\r\n        $offset       = intval( $_POST['offset'] );\r\n        $posts_per_page = 5;\r\n\r\n        switch_to_blog( $blog_id );\r\n\r\n        $args = array(\r\n            'cat'            =&gt; $category_id,\r\n            'posts_per_page' =&gt; $posts_per_page,\r\n            'offset'         =&gt; $offset,\r\n            'orderby'        =&gt; 'date',\r\n            'order'          =&gt; 'DESC',\r\n            'post_status'    =&gt; 'publish',\r\n        );\r\n\r\n        $query = new WP_Query( $args );\r\n        $html = '';\r\n\r\n        if ( $query-&gt;have_posts() ) {\r\n            while ( $query-&gt;have_posts() ) {\r\n                $query-&gt;the_post();\r\n                $html .= sprintf(\r\n                    '&lt;li&gt;&lt;a href=\"%s\"&gt;%s&lt;\/a&gt;&lt;\/li&gt;',\r\n                    esc_url( get_permalink() ),\r\n                    esc_html( get_the_title() )\r\n                );\r\n            }\r\n        }\r\n\r\n        $has_more = ( $offset + $posts_per_page ) &lt; $query-&gt;found_posts;\r\n\r\n        wp_reset_postdata();\r\n        restore_current_blog();\r\n\r\n        wp_send_json_success( array( 'html' =&gt; $html, 'has_more' =&gt; $has_more ) );\r\n    }\r\n\r\n    public function exibir_sitemap( $atts ) {\r\n        $atts = shortcode_atts(\r\n            array(\r\n                'incluir' =&gt; '',\r\n                'excluir' =&gt; '',\r\n            ),\r\n            $atts,\r\n            'rede_sitemap'\r\n        );\r\n\r\n        $sites = get_sites( array( 'number' =&gt; 0, 'public' =&gt; 1 ) );\r\n        if ( empty( $sites ) ) {\r\n            return '&lt;p&gt;Nenhum site encontrado na rede.&lt;\/p&gt;';\r\n        }\r\n\r\n        $incluir_ids = ! empty( $atts['incluir'] ) ? array_map( 'intval', explode( ',', $atts['incluir'] ) ) : array();\r\n        $excluir_ids = ! empty( $atts['excluir'] ) ? array_map( 'intval', explode( ',', $atts['excluir'] ) ) : array();\r\n\r\n        $html = '&lt;div class=\"sitemap-rede-v2\"&gt;';\r\n\r\n        foreach ( $sites as $site ) {\r\n            $blog_id = $site-&gt;blog_id;\r\n\r\n            if ( ! empty( $incluir_ids ) &amp;&amp; ! in_array( $blog_id, $incluir_ids ) ) continue;\r\n            if ( ! empty( $excluir_ids ) &amp;&amp; in_array( $blog_id, $excluir_ids ) ) continue;\r\n\r\n            switch_to_blog( $blog_id );\r\n            $site_title = get_bloginfo( 'name' );\r\n            $site_url   = home_url();\r\n\r\n            $html .= sprintf(\r\n                '&lt;div class=\"sitemap-blog\" data-blog-id=\"%d\"&gt;\r\n                    &lt;h2&gt;&lt;a href=\"%s\"&gt;%s&lt;\/a&gt;&lt;\/h2&gt;',\r\n                $blog_id,\r\n                esc_url( $site_url ),\r\n                esc_html( $site_title )\r\n            );\r\n\r\n            $categories = get_categories( array( 'hide_empty' =&gt; true ) );\r\n            if ( ! empty( $categories ) ) {\r\n                $html .= '&lt;div class=\"sitemap-categorias\"&gt;';\r\n                foreach ( $categories as $category ) {\r\n                    $posts_inicial = get_posts( array(\r\n                        'cat'            =&gt; $category-&gt;term_id,\r\n                        'posts_per_page' =&gt; 5,\r\n                        'orderby'        =&gt; 'date',\r\n                        'order'          =&gt; 'DESC',\r\n                        'post_status'    =&gt; 'publish',\r\n                    ) );\r\n\r\n                    $html .= sprintf(\r\n                        '&lt;div class=\"sitemap-categoria\" data-categoria-id=\"%d\" data-blog-id=\"%d\"&gt;\r\n                            &lt;h3&gt;%s&lt;\/h3&gt;\r\n                            &lt;ul class=\"sitemap-lista-posts\"&gt;',\r\n                        $category-&gt;term_id,\r\n                        $blog_id,\r\n                        esc_html( $category-&gt;name )\r\n                    );\r\n\r\n                    foreach ( $posts_inicial as $post ) {\r\n                        $html .= sprintf(\r\n                            '&lt;li&gt;&lt;a href=\"%s\"&gt;%s&lt;\/a&gt;&lt;\/li&gt;',\r\n                            esc_url( get_permalink( $post ) ),\r\n                            esc_html( $post-&gt;post_title )\r\n                        );\r\n                    }\r\n\r\n                    if ( $category-&gt;count &gt; 5 ) {\r\n                        $html .= sprintf(\r\n                            '&lt;\/ul&gt;&lt;button class=\"sitemap-carregar-mais\" data-blog-id=\"%d\" data-categoria-id=\"%d\" data-offset=\"5\"&gt;Carregar mais&lt;\/button&gt;',\r\n                            $blog_id,\r\n                            $category-&gt;term_id\r\n                        );\r\n                    } else {\r\n                        $html .= '&lt;\/ul&gt;';\r\n                    }\r\n                    $html .= '&lt;\/div&gt;';\r\n                }\r\n                $html .= '&lt;\/div&gt;';\r\n            } else {\r\n                $html .= '&lt;p&gt;Este blog ainda n\u00e3o possui categorias com posts.&lt;\/p&gt;';\r\n            }\r\n\r\n            $html .= '&lt;\/div&gt;';\r\n            restore_current_blog();\r\n        }\r\n\r\n        $html .= '&lt;\/div&gt;';\r\n\r\n        \/\/ CSS b\u00e1sico\r\n        $html .= '&lt;style&gt;\r\n            .sitemap-rede-v2{max-width:1200px;margin:0 auto;font-family:sans-serif}\r\n            .sitemap-blog{margin-bottom:3rem;border-bottom:1px solid #eee;padding-bottom:1.5rem}\r\n            .sitemap-blog h2{margin-bottom:1rem}\r\n            .sitemap-categorias{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:1.5rem}\r\n            .sitemap-categoria{background:#f9f9f9;padding:1rem;border-radius:8px;box-shadow:0 1px 3px rgba(0,0,0,0.05)}\r\n            .sitemap-categoria h3{margin-top:0;margin-bottom:.75rem;font-size:1.2rem}\r\n            .sitemap-lista-posts{margin:0;padding-left:1.2rem;font-size:.9rem}\r\n            .sitemap-lista-posts li{margin-bottom:.3rem}\r\n            .sitemap-carregar-mais{background:#007cba;color:#fff;border:none;padding:5px 12px;border-radius:4px;cursor:pointer;font-size:.8rem;margin-top:.5rem;transition:background .2s}\r\n            .sitemap-carregar-mais:hover{background:#005a87}\r\n        &lt;\/style&gt;';\r\n\r\n        return $html;\r\n    }\r\n}\r\n\r\nnew Sitemap_Rede();\r\n?&gt;<\/code><\/pre>\n<p><strong>Instru\u00e7\u00f5es finais:<\/strong><\/p>\n<ol>\n<li>No seu post, mude para o modo <strong>&#8220;Texto&#8221;<\/strong> (editor cl\u00e1ssico).<\/li>\n<li><strong>Apague todo o conte\u00fado existente<\/strong>.<\/li>\n<li><strong>Cole este c\u00f3digo HTML<\/strong> (ele j\u00e1 est\u00e1 completamente escapado, inclusive os shortcodes de exemplo).<\/li>\n<li><strong>Atualize o post<\/strong> sem alternar para o modo &#8220;Visual&#8221;.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Este shortcode [rede_sitemap] exibe todos os blogs da sua rede Multisite, mostrando para cada blog:<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,4],"tags":[],"class_list":["post-799","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\/799","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=799"}],"version-history":[{"count":36,"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/posts\/799\/revisions"}],"predecessor-version":[{"id":835,"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/posts\/799\/revisions\/835"}],"wp:attachment":[{"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/media?parent=799"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/categories?post=799"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.portanova.com.br\/notebook\/wp-json\/wp\/v2\/tags?post=799"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}