{"id":230287,"date":"2022-11-24T10:35:00","date_gmt":"2022-11-24T07:35:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230287"},"modified":"2022-11-09T20:57:52","modified_gmt":"2022-11-09T17:57:52","slug":"modificar-conteineres-de-imagem-no-lado-do-servidor-no-wordpress","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/modificar-conteineres-de-imagem-no-lado-do-servidor-no-wordpress\/","title":{"rendered":"Modificar cont\u00eaineres de imagem no lado do servidor no WordPress"},"content":{"rendered":"\n<p>Sempre que voc\u00ea estiver criando solu\u00e7\u00f5es personalizadas para outras pessoas, poder\u00e1 ter que lidar com casos sutis de como o WordPress est\u00e1 renderizando o conte\u00fado.<\/p>\n<p>Isso geralmente se resume ao tema, pelo menos um plugin ou a combina\u00e7\u00e3o de ambos. E se voc\u00ea precisar trabalhar com imagens individualmente, pode ser um desafio. O problema de at\u00e9 mesmo tentar escrever um post como esse \u00e9 que \u00e9 dif\u00edcil at\u00e9 mesmo descrever uma situa\u00e7\u00e3o em que voc\u00ea possa precisar de algo assim.<\/p>\n<p>Mesmo assim, vou fazer o melhor que posso. Ou seja, quero compartilhar como modificar cont\u00eaineres de imagem no lado do servidor antes de renderiz\u00e1-los no lado do cliente e faz\u00ea-lo usando a biblioteca DOMDocument do PHP.<\/p>\n<p>Parece muito? Espero que eu possa quebrar isso com bastante facilidade.<\/p>\n<p>Antes de entrar no c\u00f3digo, digamos que voc\u00ea tenha um them que renderize imagens em um \u00fanico elemento de par\u00e1grafo (ou qualquer tipo de elemento em n\u00edvel de bloco) e voc\u00ea precise envolver cada elemento em algum tipo de classe para poder acessar via CSS ou JavaScript.<\/p>\n<h3>Onde estamos<\/h3>\n<p>Ent\u00e3o, para come\u00e7ar, digamos que as imagens sejam renderizadas assim:<\/p>\n<p>E voc\u00ea precisa renderiz\u00e1-los assim:<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-164647-61e7698060b2e.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-164647-61e7698060b2e.png\" alt=\"Modificar cont\u00eaineres de imagem no lado do servidor no WordPress\" ><\/a><\/p>\n<p>Agora, voc\u00ea pode ou n\u00e3o precisar de espa\u00e7o entre eles. Isso realmente n\u00e3o importa porque voc\u00ea tem controle sobre isso via CSS. Mas voc\u00ea tem controle sobre como isso \u00e9 enviado pela rede para o lado do cliente.<\/p>\n<p>Para fazer isso, voc\u00ea precisa de algumas coisas:<\/p>\n<ul>\n<li>Acesso \u00e0 biblioteca DOMDocument do PHP,<\/li>\n<li>Compreens\u00e3o de como manipular conte\u00fado atrav\u00e9s do gancho <strong>the_content do WordPress,<\/strong><\/li>\n<li>Uma estrat\u00e9gia de como voc\u00ea deseja envolver as imagens.<\/li>\n<\/ul>\n<p>Vou percorrer cada uma delas no c\u00f3digo, mas basta dizer que vou envolver cada imagem em um elemento de par\u00e1grafo. Obviamente, voc\u00ea pode optar por fazer o que quiser.<\/p>\n<h3>Como fazer isso<\/h3>\n<p>Primeiro, certifique-se de ter declarado que est\u00e1 usando o conte\u00fado do documento DOM acima <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/44178197b6878eb43e369cf6e5de09fc#file-00-acme-class-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">de sua classe<\/a><\/strong> :<\/p>\n<pre><code>&lt;?php\n\nnamespace Acme;\n\nuse DOMDocument;\n\nclass AcmeContentSubscriber\n{\n  \/\/ ...\n}\n<\/code><\/pre>\n<p>Em seguida, v\u00e1 em frente e crie um gancho para <a href=\"https:\/\/codex.wordpress.org\/Plugin_API\/Filter_Reference\/the_content\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">the_content<\/a>. Como voc\u00ea faz isso depender\u00e1 de como voc\u00ea organizou seu c\u00f3digo (seja <a href=\"https:\/\/tommcfarlin.com\/tag\/oop-fundamentals\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">OOP<\/a> ou n\u00e3o). Para este exemplo, vou mostrar um exemplo muito simples de <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/44178197b6878eb43e369cf6e5de09fc#file-01-acme-content-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">como fazer isso<\/a><\/strong> :<\/p>\n<pre><code>&lt;?php\n\npublic function contentSubscriber()\n{\n  add_action( 'the_content', [$this, 'addImageAttributes']);\n}\n<\/code><\/pre>\n<p>Depois disso, voc\u00ea precisar\u00e1 fazer um pouco de trabalho (tudo o que est\u00e1 abaixo, mas fora do escopo deste post). Isso inclui:<\/p>\n<ul>\n<li>convertendo a codifica\u00e7\u00e3o das entidades HTML,<\/li>\n<li>criando uma inst\u00e2ncia do documento DOM,<\/li>\n<li>carregando o HTML da postagem do conte\u00fado recebido<\/li>\n<\/ul>\n<p>No c\u00f3digo, deve ficar <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/44178197b6878eb43e369cf6e5de09fc#file-02-acme-add-image-attrbutes-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">assim<\/a><\/strong> :<\/p>\n<pre><code>&lt;?php\n\npublic function addImageAttributes($content)\n{\n\n    $content  = mb_convert_encoding($content, 'HTML-ENTITIES', \"UTF-8\");\n    $document = new DOMDocument();\n\n    libxml_use_internal_errors(true);\n    $document-&gt;loadHTML(utf8_decode($content));\n\n    \/\/ ...\n}\n<\/code><\/pre>\n<p>Em seguida, voc\u00ea precisa percorrer os\u00a0 elementos <strong>img<\/strong> e certificar-se de que est\u00e1 configurando um atributo adequado. Voc\u00ea pode optar por usar uma classe, pode optar por usar um atributo de dados ou pode optar por usar outra coisa. Essa parte n\u00e3o importa.<\/p>\n<p>Observe que, para uma determinada imagem, voc\u00ea desejar\u00e1 verificar se o pr\u00f3ximo elemento n\u00e3o \u00e9 um elemento de par\u00e1grafo, pois \u00e9 isso que estou optando por envolver a imagem. Em outras palavras, se o pr\u00f3ximo elemento n\u00e3o for um par\u00e1grafo, envolveremos o elemento em um elemento de par\u00e1grafo.<\/p>\n<p>Para fazer isso, o esqueleto da fun\u00e7\u00e3o principal deve <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/44178197b6878eb43e369cf6e5de09fc#file-03-acme-add-image-attrbutes-part-2-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">ficar assim<\/a><\/strong> :<\/p>\n<pre><code>&lt;?php\n\npublic function addImageAttributes($content)\n{\n\n    $content  = mb_convert_encoding($content, 'HTML-ENTITIES', \"UTF-8\");\n    $document = new DOMDocument();\n\n    libxml_use_internal_errors(true);\n    $document-&gt;loadHTML(utf8_decode($content));\n\n    $images = $document-&gt;getElementsByTagName('img');\n    foreach ($images as $image) {\n        $image-&gt;setAttribute('class', 'acme-iamge');\n        if ($image-&gt;nextSibling-&gt;tagName !== 'p') {\n            $this-&gt;wrapImage($document, $image);\n        }\n    }\n\n    \/\/ ...\n}\n<\/code><\/pre>\n<p>Ent\u00e3o a fun\u00e7\u00e3o respons\u00e1vel por realmente envolver o elemento em um elemento de par\u00e1grafo deve ficar <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/44178197b6878eb43e369cf6e5de09fc#file-05-wrap-image-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">assim<\/a><\/strong> :<\/p>\n<pre><code>&lt;?php\n\n\/**\n * This function is used to wrap individual images in a paragraph element.\n *\n * @param $document The DOM Document which is to be rendered.\n * @param $image    The image to wrap with the new paragraph element.\n *\/\nprivate function wrapImage($document, $image)\n{\n    if (null === $image) {\n        return;\n    }\n    $wrapper = $document-&gt;createElement('p');\n    $wrapper-&gt;setAttribute('class', 'acme-image');\n\n    $image-&gt;parentNode-&gt;replaceChild($wrapper, $image);\n    if (null !== $image) {\n        $wrapper-&gt;appendChild($image);\n    }\n}\n<\/code><\/pre>\n<p>Certifique-se de ler o DocBlock do c\u00f3digo para entender como a fun\u00e7\u00e3o funciona. Basta colocar:<\/p>\n<ul>\n<li>ele aceita uma inst\u00e2ncia do documento e o elemento de imagem,<\/li>\n<li>cria um elemento de par\u00e1grafo,<\/li>\n<li>adiciona um atributo de classe<\/li>\n<li>substitui o elemento da imagem original pelo par\u00e1grafo,<\/li>\n<li>e adiciona a imagem como um elemento filho<\/li>\n<\/ul>\n<p>E como baseamos o objeto de documento no m\u00e9todo, n\u00e3o precisamos retornar nada.<\/p>\n<p>A vers\u00e3o final da fun\u00e7\u00e3o original deve ficar <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/44178197b6878eb43e369cf6e5de09fc#file-04-acme-add-image-attrbutes-part-3-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">assim<\/a><\/strong> :<\/p>\n<pre><code>&lt;?php\n\npublic function addImageAttributes($content)\n{\n\n    $content  = mb_convert_encoding($content, 'HTML-ENTITIES', \"UTF-8\");\n    $document = new DOMDocument();\n\n    libxml_use_internal_errors(true);\n    $document-&gt;loadHTML(utf8_decode($content));\n\n    $images = $document-&gt;getElementsByTagName('img');\n    foreach ($images as $image) {\n        $image-&gt;setAttribute('class', 'acme-image');\n        if ($image-&gt;nextSibling-&gt;tagName !== 'p') {\n            $this-&gt;wrapImage($document, $image);\n        }\n    }\n\n  return $document-&gt;saveHTML();\n}\n<\/code><\/pre>\n<p>E sua sa\u00edda deve se parecer com a imagem acima. Lembre-se, por\u00e9m; voc\u00ea precisa retornar os resultados da inst\u00e2ncia do documento para o WordPress, para que ele renderize corretamente o HTML. E \u00e9 isso que a\u00a0 fun\u00e7\u00e3o <strong>saveHTML<\/strong> est\u00e1 fazendo no c\u00f3digo acima.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte de grava\u00e7\u00e3o:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Confira como usar DOMDocument para modificar elementos HTML antes de renderiz\u00e1-los.<\/p>\n","protected":false},"author":1,"featured_media":221217,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[722,846,867],"tags":[1170,1170],"class_list":["post-230287","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-desenvolvedor","category-tutoriais","category-wordpress-8","tag-affiai-pt-pt"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/230287","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=230287"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/230287\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/221217"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=230287"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=230287"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=230287"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}