{"id":230225,"date":"2022-11-22T17:03:00","date_gmt":"2022-11-22T14:03:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230225"},"modified":"2022-11-22T20:24:23","modified_gmt":"2022-11-22T17:24:23","slug":"carregando-arquivos-no-wordpress-revisitado-parte-2-o-lado-do-servidor","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/carregando-arquivos-no-wordpress-revisitado-parte-2-o-lado-do-servidor\/","title":{"rendered":"Carregando arquivos no WordPress revisitado, parte 2 &#8211; O lado do servidor"},"content":{"rendered":"\n<p>Antes de pular direto para o c\u00f3digo para isso, eu queria mencionar duas coisas:<\/p>\n<ol>\n<li>Sim, eu cobri isso com alguns detalhes <strong><a href=\"https:\/\/tommcfarlin.com\/uploading-files-to-a-custom-directory\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">h\u00e1 algum tempo,<\/a><\/strong><\/li>\n<li>E esta \u00e9 a segunda parte de uma s\u00e9rie de duas partes.<\/li>\n<\/ol>\n<p>Se voc\u00ea n\u00e3o leu <a href=\"https:\/\/wordpress.mediadoma.com\/pt-pt\/carregando-arquivos-no-wordpress-revisitado-parte-1-o-lado-do-cliente\/\" title=\"a primeira parte\">a primeira parte<\/a>, fa\u00e7a-o primeiro. A ideia \u00e9 que o c\u00f3digo funcione em conjunto com o que vou abordar neste post para garantir que tanto o lado do cliente quanto o lado do servidor sejam cobertos.<\/p>\n<p>Em \u00faltima an\u00e1lise, a raz\u00e3o para dividi-lo assim n\u00e3o \u00e9 apenas garantir que as coisas sejam feitas corretamente, mas tamb\u00e9m garantir que o usu\u00e1rio tenha a experi\u00eancia mais positiva poss\u00edvel.<\/p>\n<p>Com isso dito, veja como fazer o upload de arquivos no WordPress no lado do servidor.<\/p>\n<h2>Carregando arquivos no WordPress no lado do servidor<\/h2>\n<p>Observe que, embora existam algumas verifica\u00e7\u00f5es de seguran\u00e7a que podem \u2013 e devem \u2013 ser feitas, ainda n\u00e3o encontrei uma maneira completamente infal\u00edvel de detectar que o arquivo que est\u00e1 sendo carregado \u00e9 do tipo adequado.<\/p>\n<p>Isso significa que ainda h\u00e1 uma chance de que um tipo de arquivo incorreto possa ser carregado. Se isso \u00e9 malicioso ou n\u00e3o, obviamente depende do usu\u00e1rio final. Compartilho apenas isso para deixar claro que o c\u00f3digo que vou mostrar \u00e9 o melhor que posso fornecer, mas ainda h\u00e1 um n\u00edvel de discri\u00e7\u00e3o que voc\u00ea deve usar.<\/p>\n<p>Talvez valha a pena procurar uma biblioteca de terceiros para validar os dados bin\u00e1rios depois de recebidos. Mas eu discordo.<\/p>\n<h3>1 Verifique as permiss\u00f5es do usu\u00e1rio<\/h3>\n<p>Lembre-se de que sempre que criamos o front-end, fazemos com que o WordPress gere um nonce para que possamos us\u00e1-lo para garantir que o usu\u00e1rio tenha permiss\u00e3o para fazer upload do arquivo.<\/p>\n<p>Al\u00e9m de verificar o nonce, h\u00e1 v\u00e1rias outras coisas que gosto de verificar, todas agrupadas em um m\u00e9todo chamado <strong>userCanSave<\/strong>.<\/p>\n<p>Primeiro, <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-00-nonce-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">lembre-se do front-end:<\/a><\/strong><\/p>\n<pre><code>&lt;form method=\"post\"\n      enctype=\"multipart\/form-data\"\n      action=\"&lt;?php echo esc_html(admin_url('admin-post.php')); ?&gt;\"\"&gt;\n    &lt;!-- Snip For Brevity ---&gt;\n    &lt;?php\n    wp_nonce_field(\n        'acme-item-upload',\n        'acme-item-importer'\n    );\n    ?&gt;\n&lt;\/form&gt;<\/code><\/pre>\n<p>Ent\u00e3o d\u00ea uma olhada como eu uso isso no c\u00f3digo. Primeiro, defino a <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-01-usercansave-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">fun\u00e7\u00e3o<\/a><\/strong> <strong>userCanSave<a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-01-usercansave-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external\"><\/a><\/strong> :<\/p>\n<pre><code>&lt;?php\n\n\/**\n * Determines if the current user has permission to upload a file based on their current role and the values\n * of the security nonce.\n *\n * @param  string $nonce     The WordPress-generated nonce.\n * @param  string $action    The developer-generated action name.\n * @return bool              True if the user has permission to save; otherwise, false.\n *\/\nprivate function userCanSave($nonce, $action)\n{\n    $isNonceSet   = isset($_POST[$nonce]);\n    $isValidNonce = false;\n\n    if ($isNonceSet) {\n        $isValidNonce = wp_verify_nonce($_POST[$nonce], $action);\n    }\n\n    return ($isNonceSet &amp;&amp; $isValidNonce);\n}\n<\/code><\/pre>\n<p>E ent\u00e3o eu simplesmente chamo isso no in\u00edcio do processo. Se falhar, eu <a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-01-save-part1-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">volto<\/a>.<\/p>\n<pre><code>&lt;?php\n\n\/**\n * Assuming the user has permission, verifies the security nonce and uploads the PDF file to the `uploads`\n * directory and the Media Library.\n *\/\npublic function save()\n{\n  if (!$this-&gt;userCanSave('acme-item-importer', 'acme-item-upload')) {\n    return;\n  }\n\n  \/\/ More to come...\n\n}\n<\/code><\/pre>\n<p>Eu recomendo mostrar uma mensagem de erro, mas eu discordo neste ponto, pois existem algumas maneiras de fazer isso dentro do post.<\/p>\n<h3>2 Carregue o arquivo<\/h3>\n<p>Supondo que o usu\u00e1rio tenha permiss\u00e3o para verificar o arquivo, \u00e9 seguro fazer upload do arquivo. O processo para fazer isso \u00e9 direto, mas ainda requer um pouco de trabalho com a API do WordPress (ou seja, com a fun\u00e7\u00e3o <a href=\"https:\/\/codex.wordpress.org\/Function_Reference\/wp_upload_bits\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wp_upload_bits<\/a> ).<\/p>\n<p>Primeiro, o arquivo precisa ser obtido do <a href=\"https:\/\/php.net\/manual\/en\/reserved.variables.files.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">$_FILES<\/a> global do PHP e ent\u00e3o carregado. Ao fazer isso, por\u00e9m, \u00e9 importante certificar-se de que voc\u00ea est\u00e1 enviando um arquivo com <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-02-save-part2-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">a extens\u00e3o de arquivo correta<\/a><\/strong> (no m\u00ednimo).<\/p>\n<pre><code>&lt;?php\n\n$file_type = explode('.', $filename);\n$file_type = strtolower($file_type[count($file_type) - 1]);\nif ('pdf' !== $file_type) {\n  \/\/ Give your feedback of choice here.\n}\n<\/code><\/pre>\n<p>Se o tipo de arquivo n\u00e3o for um PDF, voc\u00ea poder\u00e1 lan\u00e7ar um erro, simplesmente retornar (embora eu n\u00e3o seja f\u00e3 disso) ou <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-03-save-part3-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">dar algum feedback ao usu\u00e1rio<\/a><\/strong> (o que sou f\u00e3 de fazer).<\/p>\n<pre><code>&lt;?php\n\nif ($uploadFile['error']) {\n  \/\/ Your preferred method of feedback here.\n}<\/code><\/pre>\n<p>A \u00faltima etapa, por\u00e9m, \u00e9 colocar o arquivo no carregador de m\u00eddia.<\/p>\n<h3>3 Carregando no Media Uploader<\/h3>\n<p>A \u00faltima etapa de tudo isso \u00e9 colocar o arquivo no carregador de m\u00eddia. Para fazer isso, voc\u00ea precisa de v\u00e1rias coisas do n\u00facleo do WordPress:<\/p>\n<ol>\n<li>a biblioteca arquivo.php,<\/li>\n<li>uma matriz de anexos necess\u00e1ria para informar ao WordPress o que est\u00e1 sendo adicionado,<\/li>\n<li>uma fun\u00e7\u00e3o de API do WordPress, <strong>wp_insert_attachment<\/strong><\/li>\n<li>redirecionando de volta para a p\u00e1gina de chamada<\/li>\n<\/ol>\n<p>Parece muito, certo? N\u00e3o \u00e9 t\u00e3o ruim.<\/p>\n<p>Eu costumo agrupar a inclus\u00e3o da biblioteca de arquivos do WordPress e o <strong>wp_insert_attachment<\/strong> em um \u00fanico bloco.<\/p>\n<p>Voc\u00ea notar\u00e1 que defino o tipo MIME como <strong>pdf<\/strong> e me certifico de que o t\u00edtulo n\u00e3o inclua nada, exceto o nome do arquivo. Depois disso, uso <a href=\"https:\/\/codex.wordpress.org\/Function_Reference\/wp_insert_attachment\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wp_insert_attachment<\/a> para carregar o arquivo na Biblioteca de m\u00eddia.<\/p>\n<\/p>\n<p>O c\u00f3digo completo para isso \u00e9 <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-05-save-part5-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">o seguinte:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\n\nrequire_once(ABSPATH. \"wp-admin\". '\/includes\/file.php');\n$attachment  = array(\n    'post_mime_type' =&gt; 'pdf',\n    'post_title'     =&gt; preg_replace('\/.[^.]+$\/', '', $filename),\n    'post_status'    =&gt; 'inherit'\n);\n$attachment_id = wp_insert_attachment($attachment, $uploadFile['file']);\n<\/code><\/pre>\n<p>Depois disso, redireciono de volta para a p\u00e1gina que iniciou tudo isso (que geralmente \u00e9 a p\u00e1gina de administra\u00e7\u00e3o que vimos no post anterior. Para isso, pego o <strong>_wp_http_referer do array<\/strong> <a href=\"https:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">$_REQUEST<\/a> do PHP .<\/p>\n<pre><code>&lt;?php\nwp_safe_redirect(\n    $_REQUEST['_wp_http_referer'],\n    301\n);\nexit;\n<\/code><\/pre>\n<p>E isso <a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-06-save-part6-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">redirecionar\u00e1<\/a> o usu\u00e1rio de volta \u00e0 p\u00e1gina de onde veio.<\/p>\n<h2>E o arquivo \u00e9 carregado<\/h2>\n<p>Neste ponto, definimos o que queremos fazer:<\/p>\n<ol>\n<li>Ofere\u00e7a uma experi\u00eancia decente do lado do cliente,<\/li>\n<li>Carregou o arquivo na biblioteca de m\u00eddia (com oportunidades para oferecer feedback)<\/li>\n<li>E redirecionado de volta para a p\u00e1gina que come\u00e7ou tudo.<\/li>\n<\/ol>\n<p>\u00c9 verdade que h\u00e1 muito espa\u00e7o para feedback nisso, e pe\u00e7o que voc\u00ea adapte isso conforme necess\u00e1rio para o seu c\u00f3digo, mas a base do que voc\u00ea precisa deve ser fornecida tanto <a href=\"https:\/\/wordpress.mediadoma.com\/pt-pt\/carregando-arquivos-no-wordpress-revisitado-parte-1-o-lado-do-cliente\/\" title=\"no post anterior\">no post anterior<\/a> quanto neste post.<\/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>Um exemplo de c\u00f3digo do lado do servidor necess\u00e1rio para fazer upload de um arquivo via WordPress (e o Media Uploader).<\/p>\n","protected":false},"author":1,"featured_media":164785,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[898,846,867],"tags":[1170],"class_list":["post-230225","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-2","category-tutoriais","category-wordpress-8","tag-affiai-pt-pt"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/230225","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=230225"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/230225\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/164785"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=230225"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=230225"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=230225"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}