{"id":233675,"date":"2023-02-19T20:42:00","date_gmt":"2023-02-19T17:42:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=233675"},"modified":"2022-11-11T08:47:41","modified_gmt":"2022-11-11T05:47:41","slug":"como-acessar-e-analisar-blocos-do-gutenberg-com-php","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/como-acessar-e-analisar-blocos-do-gutenberg-com-php\/","title":{"rendered":"Como acessar e analisar blocos do Gutenberg com PHP"},"content":{"rendered":"\n<p>Neste post, veremos como analisar os blocos Gutenberg de um post e extrair blocos espec\u00edficos para fazer outra coisa. Veremos as fun\u00e7\u00f5es PHP do WordPress para analisar, extrair e renderizar os blocos escolhidos.<\/p>\n<p>Um benef\u00edcio do novo editor Gutenberg no WordPress s\u00e3o dados mais estruturados para o conte\u00fado do post. Antigamente, tudo era armazenado como HTML e n\u00e3o havia como extrair partes espec\u00edficas de conte\u00fado sem algumas express\u00f5es regulares muito complexas. Mas com Gutenberg cada parte do conte\u00fado, seja um par\u00e1grafo, t\u00edtulo, imagem, v\u00eddeo, bot\u00e3o ou uma coluna que tenha outros blocos dentro dela, \u00e9 armazenada com informa\u00e7\u00f5es que nos dizem qual \u00e9 essa parte do conte\u00fado.<\/p>\n<p>Com as fun\u00e7\u00f5es integradas do WordPress, \u00e9 muito f\u00e1cil buscar todos os blocos no conte\u00fado de uma postagem em uma matriz com todas as suas informa\u00e7\u00f5es. Isso abre muitos recursos \u00fateis para desenvolvedores de temas. S\u00f3 para citar algumas ideias:<\/p>\n<ul>\n<li>Gere dinamicamente um sum\u00e1rio buscando todos os t\u00edtulos (tutorial abaixo).<\/li>\n<li>Busque todos os v\u00eddeos, imagens ou cita\u00e7\u00f5es usados \u200b\u200bem todas as postagens para reunir e list\u00e1-los em outra p\u00e1gina.<\/li>\n<li>Extraia o primeiro par\u00e1grafo de um post e use-o como trecho nos arquivos (tutorial abaixo).<\/li>\n<li>Obtenha uma vis\u00e3o geral do uso de blocos espec\u00edficos e sua posi\u00e7\u00e3o. Por exemplo, digamos que voc\u00ea tenha um bloco de an\u00fancios personalizado e precise saber com que frequ\u00eancia ele \u00e9 usado em suas postagens e at\u00e9 que ponto eles aparecem no conte\u00fado.<\/li>\n<li>Renderize os blocos de uma postagem, mas exclua tipos de blocos espec\u00edficos.<\/li>\n<li>Verifique se o conte\u00fado de uma postagem come\u00e7a com um v\u00eddeo e use esse v\u00eddeo em vez da imagem em destaque nos arquivos.<\/li>\n<li>Se voc\u00ea usar um bloco personalizado que cont\u00e9m especifica\u00e7\u00f5es t\u00e9cnicas de produtos, poder\u00e1 criar facilmente uma p\u00e1gina que exiba e compare as especifica\u00e7\u00f5es t\u00e9cnicas em postagens de produtos.<\/li>\n<li>Re\u00fana dinamicamente todas as imagens \u00fanicas usadas em uma postagem e gere uma galeria delas no final ou em outro lugar.<\/li>\n<\/ul>\n<p>Vamos pular direto para isso!<\/p>\n<h2>Analisar os blocos de uma postagem<\/h2>\n<p>Para analisar blocos usamos a fun\u00e7\u00e3o WordPress <code>[parse_blocks](https:\/\/developer.wordpress.org\/reference\/functions\/parse_blocks\/)()<\/code>. Como par\u00e2metro, voc\u00ea precisa fornecer uma string do conte\u00fado de uma postagem. Se voc\u00ea estiver dentro de um loop ou tiver acesso a um objeto post simplesmente forne\u00e7a <code>$post-&gt;post_content<\/code>como par\u00e2metro para a fun\u00e7\u00e3o.<\/p>\n<pre><code>$post_id = 1;\n$post = get_post($post_id);\n$blocks = parse_blocks($post-&gt;post_content);<\/code><\/pre>\n<p>O retorno de <code>parse_blocks()<\/code>\u00e9 um array onde cada elemento do array \u00e9 um bloco. Para cada elemento de bloco voc\u00ea tem informa\u00e7\u00f5es como tipo de bloco (chave &#8216; <code>blockName<\/code>&#8216;), atributos do bloco (chave &#8216; <code>attrs<\/code>&#8216;), blocos internos para blocos aninhados como Colunas (chave &#8216; <code>innerBlocks<\/code>&#8216;) e dois elementos para o conte\u00fado real do bloco (chaves &#8216; <code>innerHTML<\/code>&#8216; e &#8216; <code>innerContent<\/code>&#8216;). O elemento <code>innerHTML<\/code>\u00e9 uma string de conte\u00fado HTML, enquanto <code>innerContent<\/code>\u00e9 uma matriz de strings HTML.<\/p>\n<p>E isso \u00e9 tudo! Percorra o array retornado de <code>parse_blocks()<\/code>para fazer o que voc\u00ea quer. Veremos mais exemplos de c\u00f3digo disso mais adiante neste post.<\/p>\n<h2>Uma nota sobre posts cl\u00e1ssicos (n\u00e3o-Gutenberg)<\/h2>\n<p>Voc\u00ea pode estar trabalhando em um site WordPress mais antigo que criou postagens antes de atualizar para o Gutenberg (ou usou um plug-in Desativar Gutenberg). Nesse caso, essas postagens n\u00e3o ter\u00e3o conte\u00fado de postagem estruturado, mas todo o conte\u00fado da postagem estar\u00e1 dentro de um bloco &quot;Editor cl\u00e1ssico&quot;.<\/p>\n<p>O array retornado da fun\u00e7\u00e3o <code>parse_blocks()<\/code>neste tipo de post retornar\u00e1 um elemento de array de bloco com <code>blockName<\/code>definido como <code>null<\/code>. O conte\u00fado HTML completo do post est\u00e1 dentro da <code>innerHTML<\/code>string deste elemento.<\/p>\n<p>Podemos assumir com seguran\u00e7a que se o retorno de um post <code>parse_blocks()<\/code>tem um elemento e <code>blockName<\/code>\u00e9 <code>null<\/code>, estamos lidando com um post &#8220;pr\u00e9-Gutenberg&quot;. Caso contr\u00e1rio <code>blockName<\/code>, ser\u00e1 sempre preenchido. Esta \u00e9 uma boa verifica\u00e7\u00e3o para se ter em mente ao escrever c\u00f3digo para analisar os blocos de postagens e voc\u00ea deseja lidar com conte\u00fado mais antigo do WordPress.<\/p>\n<h2>Renderizar um bloco<\/h2>\n<p>O WordPress tamb\u00e9m oferece uma fun\u00e7\u00e3o para renderizar um bloco espec\u00edfico com <code>[render_block](https:\/\/developer.wordpress.org\/reference\/functions\/render_block\/)()<\/code>. Como par\u00e2metro voc\u00ea precisa fornecer um array para um bloco, assim como um daqueles retornados de <code>parse_blocks()<\/code>cima. A fun\u00e7\u00e3o retorna uma string de HTML renderizado que voc\u00ea pode simplesmente ecoar diretamente.<\/p>\n<pre><code>$post_id = 1;\n$post = get_post($post_id);\n$blocks = parse_blocks($post-&gt;post_content);\nforeach ($blocks as $block) {\n    echo render_block($block);\n}<\/code><\/pre>\n<p>O c\u00f3digo acima ir\u00e1 renderizar todos os blocos do post, exatamente como faria normalmente ao renderizar o conte\u00fado do post. A parte divertida vem quando come\u00e7amos a adicionar c\u00f3digo para excluir ou incluir blocos espec\u00edficos nos quais estamos interessados.<\/p>\n<p>Por exemplo, o c\u00f3digo abaixo imprimir\u00e1 apenas os blocos de par\u00e1grafos do post:<\/p>\n<pre><code>foreach ($blocks as $block) {\n    if ($block['blockName'] == 'core\/paragraph') {\n        echo render_block($block);\n    }\n}<\/code><\/pre>\n<p>E isso renderizar\u00e1 todos os blocos, mas excluir\u00e1 todos os blocos de shortcode:<\/p>\n<pre><code>foreach ($blocks as $block) {\n    if ($block['blockName'] != 'core\/shortcode') {\n        echo render_block($block);\n    }\n}<\/code><\/pre>\n<h2>Nomes de bloco<\/h2>\n<p>Ao analisar os blocos de uma postagem, voc\u00ea provavelmente precisar\u00e1 verificar o tipo do bloco. Eles s\u00e3o bem simples de adivinhar. Por exemplo, um bloco de par\u00e1grafo \u00e9, bem, voc\u00ea adivinhou, <code>paragraph<\/code>. No entanto, lembre-se de que todos os blocos do Gutenberg no WordPress s\u00e3o prefixados com um namespace. Para os blocos principais do WordPress (padr\u00e3o), todos eles s\u00e3o prefixados com &#8221; <code>core\/<\/code>&#8220;. A exce\u00e7\u00e3o s\u00e3o os blocos Embed que s\u00e3o prefixados com &#8221; <code>core-embed\/<\/code>&#8220;. Assim, por exemplo, um bloco de par\u00e1grafo ter\u00e1 o nome do bloco <code>core\/paragraph<\/code>.<\/p>\n<p>Para evitar adivinha\u00e7\u00f5es, aqui est\u00e1 uma vis\u00e3o geral dos blocos padr\u00e3o fornecidos pelo WordPress (no momento em que escrevo isso):<\/p>\n<h3>Blocos comuns<\/h3>\n<ul>\n<li>Par\u00e1grafo:<code>core\/paragraph<\/code><\/li>\n<li>Imagem:<code>core\/image<\/code><\/li>\n<li>Cabe\u00e7alho:<code>core\/heading<\/code><\/li>\n<li>Galeria:<code>core\/gallery<\/code><\/li>\n<li>Lista:<code>core\/list<\/code><\/li>\n<li>Citar:<code>core\/quote<\/code><\/li>\n<li>\u00c1udio:<code>core\/audio<\/code><\/li>\n<li>Cobrir:<code>core\/cover<\/code><\/li>\n<li>Arquivo:<code>core\/file<\/code><\/li>\n<li>V\u00eddeo:<code>core\/video<\/code><\/li>\n<\/ul>\n<h3>Formata\u00e7\u00e3o<\/h3>\n<ul>\n<li>Pr\u00e9-formatado:<code>core\/preformatted<\/code><\/li>\n<li>C\u00f3digo:<code>core\/code<\/code><\/li>\n<li>Cl\u00e1ssico: <code>core\/freeform<\/code><br \/>\n(mas para postagens n\u00e3o-Gutenberg ser\u00e1 <code>null<\/code>, veja a nota sobre postagens n\u00e3o-Gutenberg)<\/li>\n<li>HTML personalizado:<code>core\/html<\/code><\/li>\n<li>Cita\u00e7\u00e3o:<code>core\/pullquote<\/code><\/li>\n<li>Mesa:<code>core\/table<\/code><\/li>\n<li>Vers\u00edculo:<code>core\/verse<\/code><\/li>\n<\/ul>\n<h3>Esquema<\/h3>\n<ul>\n<li>Bot\u00e3o:<code>core\/button<\/code><\/li>\n<li>Colunas:<code>core\/columns<\/code><\/li>\n<li>Mais:<code>core\/more<\/code><\/li>\n<li>Quebra de p\u00e1gina:<code>core\/nextpage<\/code><\/li>\n<li>Separador:<code>core\/separator<\/code><\/li>\n<li>Espa\u00e7ador:<code>core\/spacer<\/code><\/li>\n<li>M\u00eddia e texto:<code>core\/media-text<\/code><\/li>\n<\/ul>\n<h3>Widgets<\/h3>\n<ul>\n<li>C\u00f3digo curto:<code>core\/shortcode<\/code><\/li>\n<li>Arquivos:<code>core\/archives<\/code><\/li>\n<li>Categorias:<code>core\/categories<\/code><\/li>\n<li>\u00daltimos Coment\u00e1rios:<code>core\/latest-omments<\/code><\/li>\n<li>\u00daltimas postagens:<code>core\/latest-posts<\/code><\/li>\n<\/ul>\n<h3>Incorpora\u00e7\u00f5es<\/h3>\n<ul>\n<li>\n<p>Embutir:<code>core\/embed<\/code><\/p>\n<\/li>\n<li>\n<p>Twitter:<code>core-embed\/twitter<\/code><\/p>\n<\/li>\n<li>\n<p>Youtube:<code>core-embed\/youtube<\/code><\/p>\n<\/li>\n<li>\n<p>Facebook:<code>core-embed\/facebook<\/code><\/p>\n<\/li>\n<li>\n<p>Instagram:<code>core-embed\/instagram<\/code><\/p>\n<\/li>\n<li>\n<p>WordPress:<code>core-embed\/wordpress<\/code><\/p>\n<\/li>\n<li>\n<p>SoundCloud:<code>core-embed\/soundcloud<\/code><\/p>\n<\/li>\n<li>\n<p>Spotify:<code>core-embed\/spotify<\/code><\/p>\n<\/li>\n<li>\n<p>Flickr:<code>core-embed\/flickr<\/code><\/p>\n<\/li>\n<li>\n<p>Vimeo:<code>core-embed\/vimeo<\/code><\/p>\n<\/li>\n<li>\n<p>Animado:<code>core-embed\/animoto<\/code><\/p>\n<\/li>\n<li>\n<p>Nuvem:<code>core-embed\/cloudup<\/code><\/p>\n<\/li>\n<li>\n<p>Crowdsignal:<code>core-embed\/crowdsignal<\/code><\/p>\n<\/li>\n<li>\n<p>Movimento di\u00e1rio:<code>core-embed\/dailymotion<\/code><\/p>\n<\/li>\n<li>\n<p>Hulu:<code>core-embed\/hulu<\/code><\/p>\n<\/li>\n<li>\n<p>Imgur:<code>core-embed\/imgur<\/code><\/p>\n<\/li>\n<li>\n<p>Quest\u00e3o:<code>core-embed\/issuu<\/code><\/p>\n<\/li>\n<li>\n<p>Iniciador:<code>core-embed\/kickstarter<\/code><\/p>\n<\/li>\n<li>\n<p>Meetup. com:<code>core-embed\/meetup-com<\/code><\/p>\n<\/li>\n<li>\n<p>Mixcloud:<code>core-embed\/mixcloud<\/code><\/p>\n<\/li>\n<li>\n<p>Reddit:<code>core-embed\/reddit<\/code><\/p>\n<\/li>\n<li>\n<p>ReverbNation:<code>core-embed\/reverbnation<\/code><\/p>\n<\/li>\n<li>\n<p>Screencast:<code>core-embed\/screencast<\/code><\/p>\n<\/li>\n<li>\n<p>Scribd:<code>core-embed\/scribd<\/code><\/p>\n<\/li>\n<li>\n<p>Compartilhamento de slides:<code>core-embed\/slideshare<\/code><\/p>\n<\/li>\n<li>\n<p>SmugMug:<code>core-embed\/smugmug<\/code><\/p>\n<\/li>\n<li>\n<p>Plataforma de alto-falante:<code>core-embed\/speaker<\/code><\/p>\n<\/li>\n<li>\n<p>TED:<code>core-embed\/ted<\/code><\/p>\n<\/li>\n<li>\n<p>Tumblr:<code>core-embed\/tumblr<\/code><\/p>\n<\/li>\n<li>\n<p>VideoPress:<code>core-embed\/videopress<\/code><\/p>\n<\/li>\n<li>\n<p>wordpress.tv:<code>core-embed\/wordpress-tv<\/code><\/p>\n<\/li>\n<li>\n<p>Amazon Kindle:<code>core-embed\/amazon-kindle<\/code><\/p>\n<\/li>\n<\/ul>\n<h2>Exemplo de c\u00f3digo: buscar o primeiro par\u00e1grafo de uma postagem como trecho<\/h2>\n<p>Um post bem escrito deve come\u00e7ar com um par\u00e1grafo que apresente o assunto do post e tente as pessoas a continuar lendo. Eles s\u00e3o perfeitos para usar como trechos em vez de depender da fun\u00e7\u00e3o de trecho autom\u00e1tico no WordPress!<\/p>\n<p>Esta \u00e9 uma fun\u00e7\u00e3o que voc\u00ea pode adicionar ao seu tema <code>functions.php<\/code>que retornar\u00e1 o primeiro par\u00e1grafo de um post. Se nenhum post foi fornecido, ele se referir\u00e1 ao objeto global post. Ele tamb\u00e9m acomoda postagens que n\u00e3o s\u00e3o de Gutenberg, retornando o trecho real do WordPress para elas.<\/p>\n<pre><code>function awp_get_excerpt($post=false) {\n    if (!$post) { \n        global $post;\n    }\n    if (!$post) { return ''; }\n    $excerpt = '';\n    $blocks = parse_blocks($post-&gt;post_content);\n    if (count($blocks) == 1 &amp;&amp; $blocks[0]['blockName'] == null) {  \/\/ Non-Gutenberg posts\n        $excerpt = get_the_excerpt($post-&gt;ID);\n    } else {\n        foreach ($blocks as $block) {\n            if ($block['blockName'] == 'core\/paragraph') {\n                $excerpt = strip_tags($block['innerHTML']);\n                break;\n            }\n        }\n    }\n    return \"&lt;div class='excerpt'&gt;$excerpt&lt;\/div&gt;\";\n}<\/code><\/pre>\n<p>Ap\u00f3s a <code>parse_blocks()<\/code>chamada da fun\u00e7\u00e3o, verificamos se o post tem ou n\u00e3o dados de bloco inv\u00e1lidos (o post foi criado antes do Gutenberg) e retornamos o trecho do post se for o caso. Caso contr\u00e1rio, percorremos os blocos da postagem, encontramos o primeiro bloco de par\u00e1grafo e retornamos seu <code>innerHTML<\/code>. No final, retornamos uma string com (isso \u00e9 opcional) a <code>&lt;div&gt;<\/code>em torno dela.<\/p>\n<p>Para usar esta fun\u00e7\u00e3o tudo que voc\u00ea precisa fazer \u00e9 chamar:<\/p>\n<pre><code>echo awp_get_excerpt();<\/code><\/pre>\n<p>Supondo que a chamada da fun\u00e7\u00e3o seja colocada em algum lugar, h\u00e1 um <code>$post<\/code>objeto global, por exemplo, dentro de um loop. Se voc\u00ea quiser especificar um post, forne\u00e7a o objeto post como par\u00e2metro para a chamada de fun\u00e7\u00e3o:<\/p>\n<pre><code>$post_id = 1;\n$post = get_post($post_id);\necho awp_get_excerpt($post);<\/code><\/pre>\n<h2>Exemplo: criar um \u00edndice a partir dos t\u00edtulos de uma postagem<\/h2>\n<p>Voc\u00ea pode gerar autom\u00e1tica e dinamicamente um \u00edndice com base nos blocos de cabe\u00e7alho de uma postagem. O processo \u00e9 bastante simples; analise os blocos do post e encontre todos os blocos do tipo <code>core\/heading<\/code>. Mas podemos dar um passo adiante e incorporar n\u00edveis; por exemplo, colocando <code>h3<\/code>como subt\u00edtulo sob <code>h2<\/code>e assim por diante.<\/p>\n<p>Um bloco de cabe\u00e7alho cont\u00e9m informa\u00e7\u00f5es sobre seu n\u00edvel no elemento da matriz de atributos (chave &#8216; <code>attrs<\/code>&#8216;). Dentro do <code>attrs<\/code>array seria um elemento do array com a chave &#8216; <code>level<\/code>&#8216; e um inteiro significando o n\u00edvel. A <code>h3<\/code>teria &#8216; <code>level<\/code>&#8216; valor de <code>3<\/code>, a <code>h4<\/code>teria &#8216; <code>level<\/code>&#8216; de <code>4<\/code>, e assim por diante.<\/p>\n<p>No entanto, observe que os <code>attrs<\/code>blocos de cabe\u00e7alho podem estar vazios! Isso acontece quando o autor n\u00e3o alterou o tipo de t\u00edtulo para fora dos padr\u00f5es nas configura\u00e7\u00f5es do bloco. Para contornar isso, precisamos fazer algumas suposi\u00e7\u00f5es. Como os t\u00edtulos padr\u00e3o ser\u00e3o <code>h2<\/code>(a menos que voc\u00ea tenha alterado isso em seu tema). Portanto, podemos supor que, se um bloco de cabe\u00e7alho n\u00e3o tiver um atributo de n\u00edvel, \u00e9 um <code>h2<\/code>. Caso contr\u00e1rio, obtemos as informa\u00e7\u00f5es de n\u00edvel dos atributos.<\/p>\n<p>Se voc\u00ea realmente est\u00e1 \u00e0 altura do desafio, convido voc\u00ea a melhorar o c\u00f3digo abaixo. A quest\u00e3o de gerar uma <code>ol<\/code>lista bem estruturada \u00e9 que n\u00e3o podemos controlar como o autor estrutura seus t\u00edtulos. Eles podem muito bem enlouquecer e come\u00e7ar com um <code>h4<\/code>t\u00edtulo e pular direto para um <code>h2<\/code>t\u00edtulo logo depois. E de repente eles misturam um <code>h1<\/code>no meio. Minha solu\u00e7\u00e3o, portanto, envolve gerar uma <code>ol<\/code>lista simples e fornecer as informa\u00e7\u00f5es de n\u00edvel nas classes do item da lista. Ent\u00e3o, com algum CSS inteligente, voc\u00ea pode recuar os itens da lista de acordo com algum preenchimento esquerdo.<\/p>\n<h3>O c\u00f3digo<\/h3>\n<p>Aqui est\u00e1 a fun\u00e7\u00e3o de \u00edndice:<\/p>\n<pre><code>function awp_table_of_contents($post=false) {\n    if (!$post) {\n        global $post;\n    }\n    if (!$post) { return ''; }\n    $headings = [];\n    $blocks = parse_blocks($post-&gt;post_content);\n    if (count($blocks) == 1 &amp;&amp; $blocks[0]['blockName'] == null) {  \/\/ Non-Gutenberg posts\n        return '';\n    } else {\n        foreach ($blocks as $block) {\n            if ($block['blockName'] == 'core\/heading') {\n                $level = (isset($block['attrs']['level']))? $block['attrs']['level']: 2;  \/\/ h2 as default\n                $headings[] = ['title' =&gt; wp_strip_all_tags($block['innerHTML']), 'level' =&gt; $level];\n            }\n        }\n    }\n\u00a0\n    if (empty($headings)) {  \/\/ No headings found in post\n        return '';\n    }\n\u00a0\n    $toc = '&lt;ol class=\"table-of-contents\"&gt;';\n    foreach ($headings as $heading) {\n        $toc .= '&lt;li class=\"heading-level-'. $heading['level']. '\"&gt;'. $heading['title']. '&lt;\/li&gt;';\n    }\n    $toc .= '&lt;\/ol&gt;';\n    return $toc;\n}<\/code><\/pre>\n<p>A fun\u00e7\u00e3o come\u00e7a com a manipula\u00e7\u00e3o da postagem e a an\u00e1lise de seus blocos. Na linha <code>#9<\/code>, acomodamos posts que n\u00e3o sejam Gutenberg. A fun\u00e7\u00e3o continua a percorrer todos os blocos e sempre que encontra um bloco de cabe\u00e7alho, ele \u00e9 adicionado ao nosso <code>$headings<\/code>array. Usamos <code>[wp_strip_all_tags](https:\/\/developer.wordpress.org\/reference\/functions\/wp_strip_all_tags\/)()<\/code>para retirar as tags HTML dos t\u00edtulos. Tamb\u00e9m adicionamos as informa\u00e7\u00f5es de n\u00edvel ao nosso array, onde o padr\u00e3o \u00e9 definido como <code>2<\/code>se os atributos estiverem vazios.<\/p>\n<p>Ap\u00f3s o loop de blocos, o <code>$headings<\/code>array deve conter todos os t\u00edtulos do post, em ordem. Podemos ent\u00e3o simplesmente gerar uma string HTML e produzir seu conte\u00fado. Como mencionado, gerei um nome de classe em cada elemento com informa\u00e7\u00f5es sobre o n\u00edvel do cabe\u00e7alho para que possamos criar a ilus\u00e3o de uma lista estruturada com CSS.<\/p>\n<p>Como com a fun\u00e7\u00e3o de excerto acima, podemos chamar esta fun\u00e7\u00e3o quando estamos dentro do loop assim:<\/p>\n<pre><code>echo awp_table_of_contents();<\/code><\/pre>\n<p>Ou se estamos fora do loop ou queremos especificar um post;<\/p>\n<pre><code>$post_id = 1;\n$post = get_post($post_id);\necho awp_table_of_contents($post);<\/code><\/pre>\n<p>Isso gerar\u00e1 uma lista parecida com esta:<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-152586-61e4e13930788.png\" data-rel=\"lightbox\" ><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-152586-61e4e13930788.png\" alt=\"Como acessar e analisar blocos do Gutenberg com PHP\" ><\/a><\/p>\n<h2>Conclus\u00e3o<\/h2>\n<p>Como vimos com o conte\u00fado de postagem rico estruturado possibilitado pelo Gutenberg, podemos encontrar e extrair facilmente partes espec\u00edficas do conte\u00fado das postagens. Consulte a lista de exemplos que mencionei no in\u00edcio do post. N\u00e3o h\u00e1 limites para o que voc\u00ea, como desenvolvedor de temas, pode fazer. Depende apenas do que o seu tema ou site WordPress precisa (ou o que seria simplesmente legal).<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte de grava\u00e7\u00e3o:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/awhitepixel.com\" class=\"external external_icon\">awhitepixel.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Uma vis\u00e3o detalhada de como analisar os blocos de uma postagem usando as fun\u00e7\u00f5es PHP do WordPress para analisar, filtrar e renderizar blocos espec\u00edficos.<\/p>\n","protected":false},"author":1,"featured_media":152587,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[898,898,722,722,941,941,1110,816,816,846,846,867,867],"tags":[1170],"class_list":["post-233675","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-2","category-desenvolvedor","category-gutenberg-8","category-n-a","category-plug-ins","category-tutoriais","category-wordpress-8","tag-affiai-pt-pt"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/233675","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/comments?post=233675"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/233675\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/152587"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=233675"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=233675"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=233675"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}