Aula: Exportação Avançada para CSV com MU-Plugin – Substituindo o Advanced Export for WP WPMU
Objetivo: Substituir o plugin advanced-export-for-wp-wpmu por um MU-Plugin enxuto que permite exportar posts, páginas e custom post types para um arquivo CSV com os campos selecionáveis, diretamente da tela de administração.
Contexto: O plugin original oferece exportação flexível para CSV/XML, mas é desnecessariamente complexo para necessidades básicas. Vamos criar uma solução que adiciona uma nova ação em massa “Export to CSV” na lista de posts, permitindo baixar um arquivo CSV com os dados dos posts selecionados, com suporte a metadados e taxonomias.
Funcionalidades implementadas no nosso MU-Plugin
- Ação em massa “Export to CSV” na lista de posts, páginas e CPTs.
- Exportação dos campos padrão: ID, Título, Slug, Data, Autor, Status, Tipo, Link.
- Inclusão opcional de metadados (campos personalizados) – configurável via array.
- Inclusão opcional de taxonomias (categorias, tags, etc.) – configurável.
- Download automático do arquivo CSV com nome no padrão
export-posts-YYYY-MM-DD.csv. - Delimitador CSV padrão (ponto e vírgula) para compatibilidade com Excel PT-BR.
- Codificação UTF-8 com BOM para acentos corretos.
- Verificação de permissão (usuário precisa ter capacidade de exportar).
- Tratamento seguro de dados (escapamento para CSV).
Código do MU-Plugin
Crie a pasta wp-content/mu-plugins/neodoor-advanced-export/ e dentro dela o arquivo neodoor-advanced-export.php com o conteúdo abaixo:
<?php
/**
* Plugin Name: Neodoor Advanced Export
* Description: Adiciona ação em massa "Export to CSV" na lista de posts para exportar dados selecionados.
* Version: 1.0
* Author: Reinaldo (Neodoor.neo)
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Neodoor_Advanced_Export {
private static $instance = null;
// Configuração dos campos a serem exportados
private $export_fields = [
'ID' => 'ID',
'post_title' => 'Título',
'post_name' => 'Slug',
'post_date' => 'Data',
'post_author'=> 'Autor',
'post_status'=> 'Status',
'post_type' => 'Tipo',
'guid' => 'Link',
];
// Metadados adicionais a incluir (meta_key => rótulo)
private $meta_fields = [
// '_yoast_wpseo_title' => 'SEO Title', // Exemplo descomente se usar Yoast
// '_thumbnail_id' => 'Imagem ID', // ID da imagem destacada
];
// Taxonomias adicionais a incluir (taxonomia => rótulo)
private $taxonomy_fields = [
'category' => 'Categorias',
'post_tag' => 'Tags',
];
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
add_filter( 'bulk_actions-edit-post', [ $this, 'add_bulk_export_action' ] );
add_filter( 'bulk_actions-edit-page', [ $this, 'add_bulk_export_action' ] );
add_filter( 'handle_bulk_actions-edit-post', [ $this, 'handle_bulk_export' ], 10, 3 );
add_filter( 'handle_bulk_actions-edit-page', [ $this, 'handle_bulk_export' ], 10, 3 );
// Para CPTs dinâmicos – dispara para todos os tipos que usam edit.php
add_filter( 'bulk_actions-edit-product', [ $this, 'add_bulk_export_action' ] );
add_filter( 'handle_bulk_actions-edit-product', [ $this, 'handle_bulk_export' ], 10, 3 );
}
/**
* Adiciona a ação "Export to CSV" no dropdown de ações em massa
*/
public function add_bulk_export_action( $bulk_actions ) {
$bulk_actions['neodoor_csv_export'] = __( 'Export to CSV', 'neodoor-export' );
return $bulk_actions;
}
/**
* Processa a exportação quando a ação é acionada
*/
public function handle_bulk_export( $redirect_to, $doaction, $post_ids ) {
if ( $doaction !== 'neodoor_csv_export' ) {
return $redirect_to;
}
// Verifica permissão (apenas quem pode editar pode exportar)
if ( ! current_user_can( 'edit_posts' ) ) {
wp_die( 'Você não tem permissão para exportar conteúdo.' );
}
// Verifica nonce para segurança (o mesmo usado em bulk actions)
check_admin_referer( 'bulk-posts' );
// Prepara os dados para o CSV
$csv_data = [];
$headers = [];
// Monta cabeçalhos a partir dos campos configurados
foreach ( $this->export_fields as $field => $label ) {
$headers[] = $label;
}
foreach ( $this->meta_fields as $meta_key => $label ) {
$headers[] = $label;
}
foreach ( $this->taxonomy_fields as $tax => $label ) {
$headers[] = $label;
}
$csv_data[] = $headers;
// Processa cada post selecionado
foreach ( $post_ids as $post_id ) {
$post = get_post( $post_id );
if ( ! $post ) {
continue;
}
$row = [];
// Campos padrão
foreach ( $this->export_fields as $field => $label ) {
$value = '';
switch ( $field ) {
case 'ID':
$value = $post->ID;
break;
case 'post_author':
$author = get_userdata( $post->post_author );
$value = $author ? $author->display_name : $post->post_author;
break;
default:
$value = $post->$field ?? '';
}
$row[] = $value;
}
// Metadados
foreach ( $this->meta_fields as $meta_key => $label ) {
$meta_value = get_post_meta( $post->ID, $meta_key, true );
if ( is_array( $meta_value ) ) {
$meta_value = maybe_serialize( $meta_value );
}
$row[] = $meta_value;
}
// Taxonomias
foreach ( $this->taxonomy_fields as $tax => $label ) {
$terms = wp_get_post_terms( $post->ID, $tax, [ 'fields' => 'names' ] );
$value = is_wp_error( $terms ) ? '' : implode( ', ', $terms );
$row[] = $value;
}
$csv_data[] = $row;
}
// Gera o arquivo CSV para download
$this->send_csv_download( $csv_data );
// Após enviar o arquivo, o script termina (exit dentro da função)
return $redirect_to;
}
/**
* Envia o arquivo CSV para download
* @param array $data Dados formatados (headers + linhas)
*/
private function send_csv_download( $data ) {
// Nome do arquivo com data atual
$filename = 'export-posts-' . date( 'Y-m-d' ) . '.csv';
// Cabeçalhos HTTP para forçar download
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
header( 'Pragma: no-cache' );
header( 'Expires: 0' );
// Abre a saída diretamente
$output = fopen( 'php://output', 'w' );
// Adiciona BOM para UTF-8 (acentos no Excel)
fprintf( $output, chr( 0xEF ) . chr( 0xBB ) . chr( 0xBF ) );
// Escreve cada linha usando ponto e vírgula como delimitador (padrão PT-BR)
foreach ( $data as $row ) {
fputcsv( $output, $row, ';', '"' );
}
fclose( $output );
exit; // Encerra a execução para não carregar o WordPress novamente
}
}
Neodoor_Advanced_Export::get_instance();
Como testar na prática
- Após criar o MU-Plugin, acesse Posts → Todos os posts ou Páginas → Todas as páginas.
- Selecione um ou mais posts usando as caixas de seleção.
- No dropdown “Ações em massa”, escolha “Export to CSV”.
- Clique em “Aplicar”.
- O navegador iniciará o download de um arquivo chamado
export-posts-YYYY-MM-DD.csv. - Abra o arquivo no Excel, LibreOffice ou editor de texto para ver os dados exportados.
Exemplo visual do CSV gerado (Excel PT-BR)
ID;Título;Slug;Data;Autor;Status;Tipo;Link;Categorias;Tags
1;Olá mundo;ola-mundo;2024-01-01 12:00:00;admin;publish;post;https://...;Sem categoria;destaque
3;Página Exemplo;pagina-exemplo;2024-01-02 10:00:00;admin;publish;page;https://...;;
Configuração dos campos exportados
Você pode personalizar os campos editando as propriedades da classe:
$export_fields: Campos padrão do post. Formato:'campo_db' => 'Rótulo no CSV'. Os campos suportados são qualquer coluna da tabelawp_posts.$meta_fields: Metadados (campos personalizados). Exemplo:'_thumbnail_id' => 'Imagem Destacada ID'.$taxonomy_fields: Taxonomias registradas. Exemplo:'category' => 'Categorias','post_tag' => 'Tags'.
Para adicionar campos personalizados comuns, descomente as linhas de exemplo:
private $meta_fields = [
'_yoast_wpseo_title' => 'SEO Title', // Yoast SEO
'_elementor_edit_mode' => 'Elementor Editado', // Elementor
];
Personalizações avançadas
- Alterar delimitador do CSV: No método
send_csv_download, troquefputcsv( $output, $row, ';', '"' );– mude o';'para','se preferir vírgula (Excel americano). - Adicionar filtro por data ou status: Antes de processar os
$post_ids, você pode adicionar validações adicionais. - Exportar todos os posts de um tipo sem seleção: Para exportar todos os posts (não apenas os selecionados), você pode adicionar outra ação em massa ou uma página de exportação separada.
- Incluir imagens em base64: Não recomendado – deixe para exportações mais complexas com plugins especializados.
Suporte para Custom Post Types (CPTs)
Para adicionar a exportação a um CPT específico (ex: produto), você precisa adicionar duas linhas de filtro (já incluídas como exemplo para product):
add_filter( 'bulk_actions-edit-<slug_do_cpt>', [ $this, 'add_bulk_export_action' ] );
add_filter( 'handle_bulk_actions-edit-<slug_do_cpt>', [ $this, 'handle_bulk_export' ], 10, 3 );
Substitua <slug_do_cpt> pelo slug real. Você pode adicionar quantas linhas forem necessárias.
Comparação com o plugin original
- Mais leve: Cerca de 150 linhas de código, sem telas de configuração complexas.
- Sem dependências: Não requer bibliotecas externas de CSV.
- Foco em CSV: O plugin original oferece XML e outros formatos; se precisar de XML, a solução pode ser estendida.
- Totalmente configurável via código: Você decide exatamente quais campos exportar, sem interfaces confusas.
- Excel-friendly: Delimitador ponto e vírgula e BOM UTF-8 garantem acentos corretos no Excel PT-BR.
Possíveis problemas e soluções
- Arquivo CSV vazio ou sem dados: Verifique se você selecionou pelo menos um post antes de aplicar a ação.
- Acentos quebrados no Excel: O código já inclui BOM UTF-8 (
chr(0xEF).chr(0xBB).chr(0xBF)). Se ainda assim os acentos falharem, tente abrir o CSV no Excel usando “Dados → De Texto” e escolha UTF-8 como codificação. - Erro de permissão: Certifique-se de que o usuário tem capacidade
edit_posts(administradores e editores têm). - Exportação muito lenta com muitos posts: Para centenas ou milhares de posts, o PHP pode atingir o tempo limite (max_execution_time). Nesse caso, aumente o limite no
php.iniou processe em lotes.
Observações finais
- Segurança: A exportação só está disponível para usuários autenticados com permissão para editar posts.
- Performance: A exportação ocorre em tempo real (sem buffer), então o arquivo é baixado imediatamente sem ocupar disco no servidor.
- Limitação: O plugin não exporta comentários, mídia anexada ou outros objetos complexos. Para exportação completa do site, use a ferramenta nativa do WordPress (Ferramentas → Exportar) ou plugins como All-in-One WP Migration.
- Extensibilidade: Você pode facilmente adicionar novos campos ou modificar os existentes editando os arrays de configuração.
Registro no caderno
Data:
Funcionalidade: Exportação seletiva de posts para CSV via ação em massa
Plugins substituídos: advanced-export-for-wp-wpmu (e similares)
Tempo de implementação: ~15 minutos (criação e testes)
Observação: Para exportar todos os campos de uma vez, basta adicionar mais entradas nos arrays $meta_fields e $taxonomy_fields.