Documentação do Plugin Brasil de Sabores

Visão geral

O plugin Brasil de Sabores – Receitas é o núcleo funcional do projeto editorial e comunitário do site. Ele concentra a estrutura de conteúdo, os endpoints REST, o painel do usuário, a moderação administrativa e a importação em lote de receitas via JSON.

A proposta dessa arquitetura é manter o WordPress como base principal da operação, usando CPTs, taxonomias, metadados e rotas próprias para dar suporte ao catálogo regional de receitas brasileiras.


Arquivo principal do plugin

brasil-de-sabores-receitas.php

Função no sistema

Este é o arquivo principal do plugin. Ele registra o plugin no WordPress e centraliza o carregamento dos módulos internos por meio de require_once.

Responsabilidades

  • Declarar nome, descrição, versão e autor do plugin.

  • Proteger o arquivo contra acesso direto com ABSPATH.

  • Carregar os módulos:

    • cpt-taxonomias-rest.php

    • painel-usuario.php

    • moderacao-admin.php

    • importador-json.php

Observações

Esse arquivo deve permanecer simples e servir como ponto de entrada do plugin. Toda regra de negócio deve ficar distribuída nos arquivos de includes.


Estrutura de conteúdo e API

cpt-taxonomias-rest.php

Função no sistema

Este arquivo é a camada estrutural central do plugin. Ele define os tipos de conteúdo, taxonomias, metacampos e endpoints REST usados pelo frontend e pelos módulos internos.

Responsabilidades

  • Registrar o CPT receita.

  • Registrar o CPT tema_regiao.

  • Registrar as taxonomias regiao e subcategoria.

  • Registrar metadados da receita com suporte à REST API.

  • Expor endpoints REST públicos e autenticados.

CPTs registrados

receita

Representa a receita individual publicada no site, com URL própria, conteúdo indexável e metadados culinários.

tema_regiao

Representa o conteúdo editorial de apoio para uma região, como texto introdutório, banner e contexto cultural.

Taxonomias registradas

regiao

Taxonomia hierárquica compartilhada entre receitas e temas regionais. Organiza o conteúdo por Norte, Nordeste, Centro-Oeste, Sudeste e Sul.

subcategoria

Taxonomia hierárquica usada para classificar a receita por tipo de prato ou agrupamento temático.

Metacampos principais

  • link_original

  • tempo_preparo

  • rendimento

  • dificuldade

  • ingredientes

  • modo_preparo

  • total_visualizacoes

  • total_favoritos

  • bds_status_editorial

  • motivo_rejeicao

Endpoints REST disponíveis

GET
/wp-json/bds/v1/regiao/{slug}

Retorna os dados da região, tema editorial, novidades e receitas mais acessadas.

GET
/wp-json/bds/v1/sorteio

Retorna uma receita aleatória, com filtro opcional por região e subcategoria.

POST
/wp-json/bds/v1/favoritar

Adiciona ou remove uma receita da lista de favoritos do usuário autenticado.

GET
/wp-json/bds/v1/receita/{id}

Retorna o payload completo de uma receita individual para uso em single ou frontend dinâmico.

Observações técnicas

Os campos ingredientes e modo_preparo foram registrados como arrays com schema REST explícito, o que melhora a consistência da API e reduz ambiguidade na leitura dos dados.

O arquivo também foi preparado para lidar com dados antigos eventualmente salvos como JSON string, mantendo compatibilidade durante a transição.


Painel do usuário

painel-usuario.php

Função no sistema

Este arquivo é a camada comunitária do plugin. Ele controla autenticação, área do usuário, favoritos e envio de receitas pela comunidade.

Responsabilidades

  • Registrar o shortcode

    Entrar ou criar conta

    Salve receitas favoritas, envie novas receitas e acompanhe sua participação na comunidade.

    .developer.wordpress

  • Exibir login e cadastro para visitantes.

  • Exibir painel interno para usuários autenticados.

  • Permitir edição da conta.

  • Listar favoritos do usuário.

  • Listar receitas enviadas pelo próprio usuário.

  • Receber novas receitas enviadas pela comunidade.

Shortcode

Entrar ou criar conta

Salve receitas favoritas, envie novas receitas e acompanhe sua participação na comunidade.

Renderiza toda a interface pública do painel do usuário em uma página do WordPress.developer.wordpress+1

Abas do painel

Minha conta

Permite atualizar nome, e-mail e senha do usuário autenticado.

Favoritos

Lista as receitas que o usuário salvou como favoritas.

Enviar receita

Exibe o formulário comunitário de submissão de receita com imagem, taxonomias e metadados principais.

Minhas receitas

Lista as receitas enviadas pelo próprio usuário e mostra o status editorial atual.

Fluxo de envio de receita

Quando o usuário envia uma nova receita:

  • o post é criado no CPT receita;

  • a receita entra com post_status =
    pending
    ;

  • a meta bds_status_editorial recebe o valor pendente;

  • a imagem é enviada como featured image;

  • o conteúdo segue para moderação administrativa.

Observações técnicas

A autenticação do login foi ajustada para funcionar por e-mail de forma mais previsível, localizando o usuário e depois executando wp_signon() com o login real.

Os campos ingredientes e modo_preparo são salvos como arrays, alinhados ao registro estrutural do plugin.


Moderação administrativa

moderacao-admin.php

Função no sistema

Este arquivo é a camada editorial administrativa do plugin. Ele controla a revisão das receitas enviadas pela comunidade antes da publicação definitiva.

Responsabilidades

  • Registrar a página de moderação no admin do CPT receita.

  • Listar receitas pendentes ou aguardando ajustes.

  • Aprovar e publicar receitas.

  • Solicitar ajustes ao autor.

  • Rejeitar editorialmente uma submissão.

  • Registrar motivo de revisão ou rejeição.

Status editoriais usados

pending

Status inicial da receita enviada pelo usuário, aguardando revisão.

needs_revision

Status customizado usado para receitas que precisam de ajustes antes da publicação. Esse tipo de status pode ser registrado com register_post_status() no WordPress.developer.wordpress

draft + bds_status_editorial
= rejeitado

Usado quando a equipe editorial decide reprovar a receita, mas quer manter o histórico da submissão.

publish

Usado quando a receita é aprovada e publicada.

Fluxo editorial

  • Receita enviada entra como pendente.

  • Moderador pode aprovar e publicar.

  • Moderador pode solicitar ajustes e devolver ao fluxo editorial.

  • Moderador pode rejeitar com justificativa salva em meta.

Metacampos usados

  • bds_status_editorial

  • motivo_rejeicao

Observações técnicas

Esse arquivo substitui a lógica fraca de “rejeitar = lixeira” por um fluxo editorial mais rastreável e mais útil para o projeto.

A tela administrativa pode carregar assets específicos com admin_enqueue_scripts condicionado à página de moderação, o que é o padrão mais adequado para esse tipo de interface no admin.


Importação em lote

importador-json.php

Função no sistema

Este arquivo é a camada de ingestão administrativa do plugin. Ele permite importar receitas em lote por meio de um arquivo JSON estruturado.

Responsabilidades

  • Registrar a página administrativa de importação JSON.

  • Ler um arquivo JSON com array de receitas.

  • Importar uma receita por chamada AJAX.

  • Evitar duplicatas.

  • Criar ou associar taxonomias automaticamente.

  • Baixar imagem remota e associar ao post.

  • Registrar dados de auditoria da importação.

Modos de duplicata

Ignorar

Se a receita já existir, o item não é importado novamente.

Atualizar

Se a receita já existir, os dados existentes são atualizados.

Critérios de deduplicação

A busca por duplicata segue esta ordem:

  1. link_original

  2. slug

  3. titulo

Formato esperado do JSON

Cada item do array pode conter:

  • titulo

  • slug

  • descricao

  • regiao

  • subcategoria

  • ingredientes

  • modo_preparo

  • tempo_preparo

  • rendimento

  • dificuldade

  • imagem_url

  • link_original

Imagem remota

Quando imagem_url estiver presente, o sistema tenta baixar a imagem automaticamente e definir o arquivo como imagem destacada da receita. Esse fluxo pode ser implementado com media_handle_sideload() após o download do arquivo remoto.developer.wordpress+1

Metacampos de auditoria

  • bds_origem_importacao

  • bds_data_importacao

  • bds_importado_por

  • bds_slug_importado

Observações técnicas

O processamento está organizado item por item via AJAX, o que reduz risco de timeout em lotes médios e deixa o MVP mais seguro operacionalmente.


Convenções de dados

Status editorial

O campo bds_status_editorial padroniza o estado editorial da receita dentro do projeto.

Valores previstos:

  • pendente

  • publicado

  • em_revisao

  • rejeitado

  • rascunho

Motivo editorial

O campo motivo_rejeicao armazena a justificativa da equipe quando uma receita precisa de ajustes ou é rejeitada. Apesar do nome, ele também pode guardar observações de revisão.

Estrutura culinária

Os campos ingredientes e modo_preparo devem ser tratados como arrays estruturados, e não como texto único ou JSON solto.


Fluxos principais do plugin

Descoberta de receita

  • Usuário entra no site.

  • Escolhe uma região.

  • Navega pelas receitas.

  • Abre a single da receita.

  • Pode favoritar o conteúdo se estiver autenticado.

Envio comunitário

  • Usuário cria conta ou faz login.

  • Envia uma receita pelo painel.

  • A receita entra como pendente.

  • A equipe revisa no admin.

  • A receita é publicada, devolvida para ajustes ou rejeitada.

Importação administrativa

  • Admin acessa a tela de importação.

  • Envia um JSON estruturado.

  • O sistema cria ou atualiza receitas.

  • Taxonomias são ajustadas.

  • A imagem destacada é baixada quando disponível.


Próximos passos recomendados

Frontend

  • Criar os templates públicos da home, região e single.

  • Conectar os endpoints REST ao carregamento dinâmico da home.

Painel do usuário

  • Adicionar JavaScript e CSS definitivos para o painel.

  • Permitir edição de receita devolvida para ajustes.

Moderação

  • Incluir filtros por status, autor e região.

  • Adicionar histórico editorial por receita.

Importação

  • Suportar lotes maiores com processamento em blocos.

  • Adicionar relatório final mais detalhado da importação.

=======================================================

assets/js/user-recipes.js

Função no sistema

Este arquivo é a camada JavaScript do painel do usuário no frontend. Ele conecta os formulários renderizados por painel-usuario.php às rotas AJAX e REST do plugin, fazendo o painel realmente funcionar no navegador, sem dependência de jQuery ou bibliotecas externas.

Responsabilidades

  • Alternar abas de autenticação entre login e cadastro.

  • Alternar abas do painel do usuário autenticado (conta, favoritos, enviar receita, minhas receitas).

  • Enviar login por AJAX.

  • Enviar cadastro por AJAX.

  • Atualizar dados da conta por AJAX.

  • Enviar nova receita por AJAX com FormData, incluindo upload de imagem.

  • Carregar favoritos do usuário sob demanda.

  • Carregar a lista de receitas enviadas pelo usuário sob demanda.

  • Permitir remover favoritos diretamente da listagem de favoritos.

  • Favoritar/desfavoritar receitas fora do painel, em qualquer botão .bds-favorito-btn[data-receita-id] presente na página.

Dependências

Este arquivo depende de:

  • HTML produzido por painel-usuario.php;

  • classes e atributos como .bds-aba, .bds-painel-aba, [data-aba-conteudo], [data-painel-conteudo] e .bds-form__msg;

  • admin-ajax.php exposto ao frontend;developer.wordpress+1

  • objeto global bdsUserPanel, localizado via wp_localize_script(), que é o padrão recomendado para passar ajaxUrl e demais parâmetros dinâmicos ao JavaScript.dev+1

Estratégia de requisição

O script implementa três formas de comunicação, cada uma para um tipo de payload:

  • post(): monta URLSearchParams e envia como application/x-www-form-urlencoded para admin-ajax.php, usado em login, cadastro, conta, favoritos e minhas receitas.codingace+1

  • postFormData(): monta um FormData a partir do próprio <form>, usado exclusivamente no envio de receita, pois preserva o upload de arquivo sem serialização manual.developer.wordpress

  • fetch() direto para a rota REST /bds/v1/favoritar, autenticado via header X-WP-Nonce, que é a forma padrão de autenticação por cookie na REST API do WordPress.developer.wordpress+1

Todas as chamadas usam credentials:
'same-origin'
para garantir que os cookies de sessão do WordPress sejam enviados corretamente.stackoverflow

Fluxos cobertos

Navegação por abas

initAbasAuth() alterna entre login e cadastro na tela de visitante, e initAbasPainel() alterna entre conta, favoritos, envio de receita e minhas receitas no painel autenticado, sem recarregar a página.

Login

O formulário #bds-form-login envia email, senha, action=bds_login e nonce para o backend via post(). Em caso de sucesso, a página é recarregada para exibir o painel autenticado.

Cadastro

O formulário #bds-form-cadastro envia nome, email, senha, action=bds_cadastro e nonce. Em caso de sucesso, a página recarrega com o usuário já autenticado.

Atualização de conta

O formulário #bds-form-conta envia nome, email, nova senha opcional e nonce. Após sucesso, a mensagem é exibida no próprio formulário e o campo de senha é limpo.

Envio de receita

O formulário #bds-form-enviar-receita envia todos os campos, inclusive o arquivo de imagem, usando postFormData(), o que permite upload de mídia sem serialização manual do formulário.developer.wordpress

Favoritos

A aba de favoritos é carregada sob demanda, apenas na primeira vez que o usuário a abre, via carregarFavoritos(). O script monta os cards com base no retorno do backend, cobre os estados de carregando, vazio e erro, e liga os botões de desfavoritar de cada card.

Minhas receitas

A aba “Minhas receitas” também é carregada sob demanda, via carregarMinhasReceitas(), usando a resposta AJAX para montar a listagem com status editorial, rótulo amigável e eventual feedback de moderação.

Favoritar em qualquer página

initFavoritarBotoesGlobais() liga qualquer botão .bds-favorito-btn[data-receita-id] fora da lista de favoritos (por exemplo, na single da receita) à mesma lógica de toggle usada no painel.

Estratégia de fallback do favoritar

toggleFavorito() tenta primeiro a rota REST /bds/v1/favoritar, enviando o nonce no header X-WP-Nonce. Se essa chamada falhar por qualquer motivo — rede, CORS, indisponibilidade —, o script cai automaticamente para o endpoint AJAX bds_favoritar_fallback via admin-ajax.php, garantindo que o recurso de favoritar continue funcionando mesmo sem a REST API disponível.developer.wordpress+1

Contrato esperado do objeto global

O script espera ser localizado com um objeto assim:

php
wp_localize_script( 'bds-user-recipes', 'bdsUserPanel', array(     'ajaxUrl'          => admin_url( 'admin-ajax.php' ),     'restFavoritarUrl' => rest_url( 'bds/v1/favoritar' ),     'wpRestNonce'      => wp_create_nonce( 'wp_rest' ),     'favoritosNonce'   => wp_create_nonce( 'bds_painel_usuario_nonce' ),     'strings'          => array(         'erroGenerico' => 'Ocorreu um erro ao processar a solicitação.',         'carregando'   => 'Carregando...',         'semFavoritos' => 'Você ainda não salvou nenhuma receita.',         'semReceitas'  => 'Você ainda não enviou nenhuma receita.',     ), ) );

O uso de wp_localize_script() para expor ajaxUrl e demais parâmetros dinâmicos ao JavaScript continua sendo uma prática amplamente adotada em plugins WordPress, embora a documentação oficial mais recente recomende wp_add_inline_script() para dados que não são strings de tradução; ambas as abordagens funcionam de forma equivalente para este caso.wordpress.stackexchange+1

Observações técnicas

O carregamento de favoritos e de “minhas receitas” foi desenhado em modo lazy — só ocorre quando a aba correspondente é aberta pela primeira vez, controlado por dataset.carregado. Isso reduz requisições desnecessárias e deixa o carregamento inicial do painel mais leve.

As mensagens de retorno de login, cadastro, conta e envio de receita são mostradas dentro do próprio formulário, no elemento .bds-form__msg, mantendo o feedback no contexto da ação realizada.

O botão de favoritar alterna a classe .ativo e o texto (“Favoritar” / “Remover favorito”) com base na resposta do backend, e, quando usado dentro da lista de favoritos, remove o card da tela e exibe o estado vazio se a lista ficar sem itens.

Atenções e pendências

Para que o botão de favoritos funcione plenamente no fallback, o plugin precisa registrar a action wp_ajax_bds_favoritar_fallback apontando para ajax_favoritar_fallback() — essa função e o hook já foram implementados no painel-usuario.php durante esta revisão.

O nome do nonce usado em favoritosNonce e nos handlers ajax_listar_favoritos(), ajax_minhas_receitas() e ajax_favoritar_fallback() precisa ser idêntico entre geração (wp_create_nonce()) e verificação (check_ajax_referer()); o padrão adotado neste plugin é bds_painel_usuario_nonce.developer.wordpress+1

É importante enfileirar este arquivo, junto com dashboard.css, apenas nas páginas onde o shortcode

Entrar ou criar conta

Salve receitas favoritas, envie novas receitas e acompanhe sua participação na comunidade.

estiver presente, para evitar carregar JS e CSS desnecessários em outras páginas do site.

====================================================================

assets/css/dashboard.css

Função no sistema

Este arquivo é a camada visual do painel do usuário no frontend. Ele estiliza autenticação, navegação por abas, formulários, cards de favoritos, listagem de receitas enviadas e mensagens de estado, mantendo uma interface de web app compacta e clara.

Responsabilidades

  • Estilizar a área de login e cadastro.

  • Estilizar o painel do usuário autenticado.

  • Definir visual das abas de navegação do painel.

  • Padronizar botões, links de ação e estados ativos.

  • Estruturar formulários de conta e envio de receita.

  • Exibir mensagens de sucesso, erro, vazio e carregamento.

  • Organizar cards de favoritos e lista de “minhas receitas”.

  • Garantir comportamento responsivo em mobile, tablet e desktop.

Direção visual adotada

O CSS segue uma abordagem de painel administrativo leve: tipografia compacta, superfícies neutras, um único acento principal e densidade equilibrada. Em interfaces desse tipo, a recomendação é usar títulos contidos, labels curtos, feedback inline e layout eficiente, sem escalas tipográficas grandes nem efeitos teatrais.

Blocos principais

.bds-auth-wrap e .bds-auth-box

Agrupam e estilizam a área de visitantes, com foco em login e cadastro.

.bds-painel

É o contêiner principal do painel autenticado. Recebe superfície, borda, raio e sombra base.

.bds-abas e .bds-painel-abas

Controlam a faixa de navegação por abas. Os botões ativos usam contraste alto e os inativos mantêm leitura discreta.

.bds-form

Padroniza os formulários com grid, espaçamento e campos consistentes.

.bds-cards-grid e .bds-card

Estruturam a visualização de favoritos em cards responsivos.

.bds-minhas-lista e .bds-minha-receita

Organizam a listagem das receitas enviadas pelo usuário com status editorial e ações rápidas.

Estados visuais

O arquivo define blocos específicos para:

  • .bds-form__msg.erro e .bds-erro;

  • .bds-form__msg.sucesso e .bds-sucesso;

  • .bds-loading;

  • .bds-vazio.

Essa abordagem segue a boa prática de tratar loading, empty e error como estados projetados da interface, e não como conteúdo improvisado.

Responsividade

Em mobile, os botões de abas e ações passam a ocupar largura total, as ações ficam empilhadas e o painel prioriza leitura em uma coluna. Em telas médias e grandes, entram grids de duas colunas para formulários e cards, além de uma composição mais larga para receitas e resumos.

Acessibilidade e usabilidade

O CSS inclui foco visível, áreas clicáveis confortáveis e altura mínima de 44px para botões e ações principais, alinhando o painel às recomendações para interfaces web e navegação por toque.

Integração esperada

Este arquivo deve ser enfileirado junto do assets/js/user-recipes.js, de preferência somente na página onde o shortcode do painel estiver presente.

===========================================================

Documentação do enqueue

Enqueue de assets do painel

Função no sistema

Esse trecho adiciona ao painel-usuario.php a responsabilidade de registrar e carregar os assets do painel do usuário no frontend, conectando o HTML do shortcode com o CSS dashboard.css e o JavaScript user-recipes.js.developer.wordpress+1

Responsabilidades

  • Registrar o CSS do painel com wp_register_style().developer.wordpress

  • Registrar o JavaScript do painel com wp_register_script().developer.wordpress

  • Carregar os assets apenas quando o shortcode é renderizado.wpexplorer+1

  • Passar ajaxUrl, URL REST e nonces para o JavaScript via wp_localize_script().developer.wordpress+1

  • Expor o nonce wp_rest para chamadas autenticadas à REST API.medium

  • Expor um nonce próprio do painel para fallbacks AJAX tradicionais.developer.wordpress

Métodos adicionados

registrar_assets()

Registra os arquivos assets/css/dashboard.css e assets/js/user-recipes.js no frontend, sem necessariamente enfileirá-los naquele momento.developer.wordpress+1

enqueue_assets()

Enfileira os assets já registrados e injeta no script o objeto global bdsUserPanel, contendo URLs e nonces necessários para o funcionamento do painel.developer.wordpress+1

render_shortcode()

Renderiza o conteúdo do shortcode

Entrar ou criar conta

Salve receitas favoritas, envie novas receitas e acompanhe sua participação na comunidade.

e chama enqueue_assets() no momento em que o painel realmente é usado na página. Essa estratégia evita carga desnecessária em outras páginas do site.sanjeebaryal.com+1

Objeto JavaScript localizado

O objeto bdsUserPanel enviado ao frontend contém:

  • ajaxUrl, apontando para admin-ajax.php;medium

  • restFavoritarUrl, apontando para a rota REST de favoritos;medium

  • wpRestNonce, para autenticação REST no header X-WP-Nonce;medium

  • favoritosNonce, para fallback AJAX tradicional;developer.wordpress

  • mensagens auxiliares em strings.developer.wordpress

Vantagens dessa abordagem

  • Evita carregar assets do painel no site inteiro.wpexplorer+1

  • Mantém o shortcode autocontido.sanjeebaryal.com

  • Centraliza os parâmetros dinâmicos do frontend em um único objeto JavaScript.developer.wordpress

  • Deixa o painel preparado para conviver com AJAX clássico e REST API.

==========================================================

ajax_cadastro()

Função no sistema

Cria uma nova conta de usuário a partir do formulário público do painel, valida os campos e autentica o usuário automaticamente após o cadastro.developer.wordpress

Responsabilidades

  • Validar o nonce do cadastro.developer.wordpress

  • Validar nome, e-mail e senha.developer.wordpress

  • Impedir cadastro com e-mail duplicado.developer.wordpress

  • Gerar um user_login com base no e-mail, evitando conflito de usernames.developer.wordpress

  • Criar o usuário com papel subscriber.developer.wordpress

  • Autenticar o usuário após o cadastro.developer.wordpress

ajax_login()

Função no sistema

Executa o login do usuário a partir do formulário público do painel, buscando primeiro o usuário pelo e-mail e autenticando com wp_signon().developer.wordpress

Responsabilidades

  • Validar o nonce do login.developer.wordpress

  • Validar e-mail e senha.developer.wordpress

  • Buscar o usuário pelo e-mail informado.developer.wordpress

  • Autenticar via wp_signon().developer.wordpress

  • Retornar resposta JSON para o frontend.

ajax_atualizar_conta()

Função no sistema

Atualiza os dados da conta do usuário autenticado a partir do painel frontend, permitindo alterar nome, e-mail e senha sem ir ao wp-admin.developer.wordpress

Responsabilidades

  • Validar o nonce da requisição AJAX.developer.wordpress

  • Garantir que exista uma sessão autenticada válida.developer.wordpress

  • Validar nome e e-mail informados.developer.wordpress

  • Evitar conflito com e-mail já usado por outra conta.core.trac.wordpress

  • Atualizar senha apenas quando o campo for preenchido.developer.wordpress

  • Persistir os dados via wp_update_user().developer.wordpress

Observação técnica

Ao enviar user_pass no array de atualização, o WordPress trata o hash internamente. Em mudanças de senha do usuário atual, o fluxo de autenticação pode ser afetado, por isso a revalidação da sessão após a atualização ajuda a manter a experiência estável no painel.wp-kama+1

ajax_enviar_receita()

Função no sistema

Recebe a submissão de uma nova receita enviada pelo usuário autenticado no frontend, cria o post no CPT receita, associa taxonomias e metadados e envia a imagem destacada para a biblioteca de mídia.developer.wordpress+1

Responsabilidades

  • Validar o nonce da submissão AJAX.developer.wordpress

  • Garantir que o usuário esteja autenticado.developer.wordpress

  • Sanitizar os campos textuais e URLs da receita.make.xwp

  • Transformar ingredientes e modo de preparo em arrays por linha.make.xwp

  • Criar a receita com status pending.make.xwp

  • Associar regiao e subcategoria à nova receita.make.xwp

  • Salvar os principais metacampos editoriais e culinários.make.xwp

  • Fazer upload da imagem com media_handle_upload().wp-kama+1

  • Definir a imagem destacada do post.wordpress.stackexchange

  • Notificar o administrador por e-mail sobre a nova submissão.developer.wordpress

Observação técnica

No frontend WordPress, media_handle_upload() exige a inclusão explícita dos arquivos image.php, file.php e media.php antes do upload. Sem isso, a função pode falhar fora do wp-admin.

ajax_listar_favoritos()

Ela valida login, verifica o nonce com check_ajax_referer(), lê os favoritos via get_user_meta() e retorna a resposta com wp_send_json_success() ou wp_send_json_error(), que são o padrão recomendado para handlers AJAX no WordPress.wordpress+2
Na montagem do payload, get_the_post_thumbnail_url() é apropriada para devolver a URL da imagem destacada, e get_permalink() entrega a URL pública da receita para o card do painel.developer.wordpress

Estrutura esperada do front

O JavaScript vai receber algo neste formato:

json
{   "success": true,   "data": {     "items": [       {         "id": 15,         "titulo": "Baião de dois",         "link": "https://site.com/receita/baiao-de-dois",         "imagem": "https://site.com/uploads/baiao.jpg",         "descricao": "Receita tradicional nordestina...",         "tempo_preparo": "45 min",         "rendimento": "4 porções",         "dificuldade": "Fácil",         "regiao": "Nordeste",         "subcategoria": "Prato principal",         "favoritado": true       }     ],     "total": 1   } }

O formato success/data vem automaticamente de wp_send_json_success(), então no JS o correto é acessar response.data.items e response.data.total.wp-kama+1

Registro AJAX

Você também precisa garantir estes hooks:

php
add_action( 'wp_ajax_bds_listar_favoritos', array( $this, 'ajax_listar_favoritos' ) );

Como essa ação depende de usuário autenticado, normalmente não faz sentido registrar wp_ajax_nopriv_* para ela. O padrão WordPress separa mesmo ações autenticadas em wp_ajax_* e ações públicas em wp_ajax_nopriv_*.wordpress

Ajuste recomendado

Se no seu plugin os favoritos estiverem salvos com outro meta key, por exemplo favoritos_receitas ou _bds_favoritos, basta trocar 'bds_favoritos' na função.
Se quiser, no próximo passo eu monto também o user-recipes.js que consome esse endpoint e renderiza os cards de favoritos no painel.

A ajax_minhas_receitas() retorna dados já prontos para renderização no dashboard, inclusive status_label, feedback, imagem e links, o que reduz processamento no JavaScript.developer.wordpress
Já a ajax_favoritar_fallback() serve como redundância útil quando o fluxo REST não estiver disponível no frontend, mantendo atualização segura via nonce, get_user_meta() e update_user_meta().developer.wordpress+1

Ajuste importante

O ponto mais pesado aqui é contar_total_favoritos_receita(), porque ele percorre usuários para recalcular a contagem. Para MVP funciona bem, mas em escala maior vale migrar para atualização incremental desse meta ou para uma tabela própria de favoritos.

templates/single-receita.php

Função no sistema

Este template renderiza a página pública individual de cada receita, com conteúdo completo, ingredientes, modo de preparo, imagem, fonte e dados estruturados Recipe em JSON-LD, sendo estratégico para indexação orgânica no Google.

Responsabilidades

  • Carregar e normalizar os metacampos da receita (ingredientes, modo_preparo, tempo_preparo, rendimento, dificuldade, link_original).

  • Incrementar total_visualizacoes a cada carregamento da página.

  • Montar o schema Recipe em JSON-LD com name, image, description, recipeIngredient, recipeInstructions, recipeYield, recipeCategory, recipeCuisine e totalTime.karpi

  • Exibir breadcrumb, taxonomia de região, chips de metadados, botão de favoritar e conteúdo completo da receita.

  • Listar receitas relacionadas da mesma região na barra lateral.

Dados estruturados (JSON-LD)

O Google exige apenas name e image no nível da página para elegibilidade de rich results de receita, mas recomenda fortemente recipeIngredient, recipeInstructions, prepTime, cookTime, totalTime, recipeYield, recipeCategory e recipeCuisine para melhorar a exibição nos resultados de busca. Cada passo do modo de preparo é representado como um objeto HowToStep com a propriedade text, seguindo o padrão recomendado pela Schema.org.schema+1

Compatibilidade de dados

Os campos ingredientes e modo_preparo podem ter sido salvos como array estruturado, JSON string ou texto quebrado por linha, dependendo da origem (formulário, importação ou dados legados). O template trata as três possibilidades antes de renderizar, evitando páginas quebradas.

Favoritos

O botão de favoritar exibe estado visual diferente quando a receita já está salva pelo usuário autenticado, e sinaliza com data-requer-login quando o visitante não está logado, para que o JavaScript do painel (favorites.js) trate o redirecionamento ou o aviso de login.

SEO complementar

A página usa itemscope/itemprop como camada adicional de microdata sobre os elementos visuais, além do JSON-LD, reforçando a leitura semântica do conteúdo pelos mecanismos de busca.

assets/css/single.css

Função no sistema

Este arquivo estiliza a página pública individual da receita, cobrindo breadcrumb, cabeçalho com metadados, imagem destacada, corpo editorial, lista de ingredientes, passos numerados do preparo, bloco de fonte e sidebar de categorias e receitas relacionadas.

Responsabilidades

  • Definir hierarquia visual do título, introdução e chips de metadados da receita.

  • Estilizar o botão de favoritar com estado ativo e contador.

  • Organizar a leitura da história, ingredientes e modo de preparo com largura de prosa controlada.

  • Numerar visualmente os passos do preparo com destaque no acento teal.

  • Estruturar a sidebar fixa com categorias e receitas relacionadas em telas grandes.

  • Garantir leitura confortável em mobile, com imagem reduzida e ações em largura total.

Reaproveitamento de tokens

O arquivo depende das variáveis já definidas em dashboard.css (--bds-primary, --bds-surface, --bds-radius-*, --bds-space-*, --bds-text-*), garantindo consistência visual entre o painel do usuário e a página pública da receita. Por isso, dashboard.css deve ser carregado antes de single.css, ou os tokens devem ser centralizados em um arquivo compartilhado.

Layout de leitura

A prosa da história e dos ingredientes é limitada entre 60ch e 68ch para manter conforto de leitura, enquanto o título e a introdução podem ocupar até 75ch, já que texto de destaque é lido de forma diferente do corpo de texto.

Sidebar fixa

A partir de 1024px, a sidebar de categorias e relacionadas fica fixa (position: sticky) enquanto o conteúdo principal rola, ajudando na permanência de navegação sem competir com o conteúdo principal.

Documentação do Arquivo: cpt-taxonomias-rest.php

Visão Geral

Este arquivo é um componente central do plugin “Brasil de Sabores”, responsável por definir a estrutura de conteúdo principal do projeto. Ele registra os Custom Post Types (CPTs) para “Receitas” e “Temas de Região”, as taxonomias para “Regiões” e “Subcategorias”, os metadados associados ao CPT “Receita”, e os endpoints da API REST para interagir com esses dados de forma dinâmica.

Estrutura do Arquivo

O arquivo é dividido em cinco seções principais:

  1. Registro dos CPTs e Taxonomias: Define e registra os tipos de post personalizados e as taxonomias.
  2. Meta Fields: Registra os campos de metadados para o CPT “Receita”.
  3. REST API: Registra as rotas e endpoints personalizados da API REST.
  4. Callbacks dos Endpoints: Implementa a lógica para cada endpoint REST.
  5. Helpers: Funções auxiliares para formatação e consulta de dados.

Detalhes por Seção

1. Registro dos CPTs e Taxonomias

Esta seção é responsável por criar os tipos de conteúdo e as categorias que estruturam o projeto.

  • Hook: init
  • Função Principal: bds_registrar_cpts_e_taxonomias()

1.1. CPT: receita

Representa uma receita culinária.

  • Labels: “Receitas”, “Receita”, “Adicionar nova receita”, etc.
  • public: true (visível no frontend e no admin).
  • has_archive: true (permite uma página de arquivo para todas as receitas).
  • show_in_rest: true (disponível via API REST).
  • menu_icon: dashicons-carrot (ícone no menu do admin).
  • supports: titleeditor (conteúdo principal), thumbnail (imagem destacada), excerpt (resumo), authorcustom-fields (para metadados).
  • rewrite: slug => receita (URL amigável: /receita/nome-da-receita).
  • capability_type: post (usa as capacidades padrão de posts).
  • map_meta_cap: true (mapeia capacidades meta para capacidades primitivas).

1.2. CPT: tema_regiao

Representa um tema ou região específica, podendo conter informações editoriais sobre ela.

  • Labels: “Temas de Região”, “Tema de Região”.
  • public: false (não visível diretamente no frontend, mas acessível via admin e REST).
  • show_ui: true (visível no painel administrativo).
  • show_in_rest: true (disponível via API REST).
  • supports: titleeditorthumbnailcustom-fields.
  • menu_icon: dashicons-location-alt.

1.3. Taxonomia: regiao

Usada para categorizar receitas e temas de região por localização geográfica.

  • Associada a: receitatema_regiao.
  • Labels: “Regiões”, “Região”.
  • hierarchical: true (permite estrutura de árvore, ex: “Norte” > “Amazonas”).
  • show_in_rest: true.
  • show_admin_column: true (exibe a coluna no admin).
  • rewrite: slug => regiao (URL amigável: /regiao/nome-da-regiao).

1.4. Taxonomia: subcategoria

Usada para categorizar receitas por tipo ou subcategoria culinária.

  • Associada a: receita.
  • Labels: “Subcategorias”, “Subcategoria”.
  • hierarchical: true.
  • show_in_rest: true.
  • show_admin_column: true.
  • rewrite: slug => tipo (URL amigável: /tipo/nome-da-subcategoria).

2. Meta Fields

Esta seção registra os metadados personalizados para o CPT receitaregister_post_meta() define as propriedades dos metadados, mas não cria a interface de usuário no painel administrativo. Para isso, é necessária uma meta box separada.

  • Hook: init
  • Função Principal: bds_registrar_meta_fields()
  • auth_callback: bds_meta_auth_callback() (requer edit_posts para manipular metadados).

Metadados Registrados:

  • link_original: URL da fonte original da receita.
    • Tipo: string
    • Sanitização: esc_url_raw
  • tempo_preparo: Tempo estimado para o preparo da receita.
    • Tipo: string
    • Sanitização: sanitize_text_field
  • rendimento: Quantidade de porções ou unidades que a receita rende.
    • Tipo: string
    • Sanitização: sanitize_text_field
  • dificuldade: Nível de dificuldade da receita (Fácil, Médio, Difícil).
    • Tipo: string
    • Sanitização: sanitize_text_field
  • ingredientes: Lista de ingredientes.
    • Tipo: array (armazenado como array de strings).
    • Sanitização: bds_sanitize_array_strings (converte string JSON ou textarea em array de strings).
    • Schema REST: array de string.
  • modo_preparo: Passos para o preparo da receita.
    • Tipo: array (armazenado como array de strings).
    • Sanitização: bds_sanitize_array_strings.
    • Schema REST: array de string.
  • total_visualizacoes: Contador de visualizações da receita.
    • Tipo: integer
    • Sanitização: absint
  • total_favoritos: Contador de vezes que a receita foi favoritada.
    • Tipo: integer
    • Sanitização: absint
  • bds_status_editorial: Status editorial da receita (ex: publicadopendenterejeitado).
    • Tipo: string
    • Sanitização: sanitize_text_field
  • motivo_rejeicao: Texto explicando o motivo da rejeição editorial.
    • Tipo: string
    • Sanitização: sanitize_textarea_field

Funções Auxiliares de Meta Fields:

  • bds_meta_auth_callback(): Verifica se o usuário atual tem permissão para editar posts (edit_posts).
  • bds_sanitize_array_strings( $value ): Sanitiza um valor que pode ser uma string JSON ou um array de strings, garantindo que o resultado seja um array de strings sanitizadas.

3. REST API

Esta seção registra as rotas personalizadas da API REST para o plugin, permitindo que aplicações frontend interajam com os dados do Brasil de Sabores.

  • Hook: rest_api_init
  • Função Principal: bds_registrar_rotas_rest()
  • Namespace: bds/v1

Endpoints Registrados:

  • GET /regiao/(?P<slug>[a-zA-Z0-9-]+): Retorna detalhes de uma região específica, incluindo informações do tema_regiao associado e listas de receitas (novidadesmais_acessadas).
    • Parâmetros: slug (obrigatório, sanitizado com sanitize_title).
    • Permissão: Pública (__return_true).
    • Callback: bds_endpoint_regiao().
  • GET /sorteio: Retorna uma receita aleatória, opcionalmente filtrada por região e/ou subcategoria.
    • Parâmetros: regiao (opcional), subcategoria (opcional).
    • Permissão: Pública (__return_true).
    • Callback: bds_endpoint_sorteio().
  • POST /favoritar: Adiciona ou remove uma receita dos favoritos do usuário logado. Atualiza o contador total_favoritos da receita.
    • Parâmetros: post_id (obrigatório, ID da receita).
    • Permissão: Requer usuário logado (is_user_logged_in()).
    • Callback: bds_endpoint_favoritar().
  • GET /receita/(?P<id>\d+): Retorna todos os detalhes de uma receita específica, incluindo metadados e termos de taxonomia.
    • Parâmetros: id (obrigatório, ID da receita).
    • Permissão: Pública (__return_true).
    • Callback: bds_endpoint_receita().

4. Callbacks dos Endpoints

Implementa a lógica de negócios para cada endpoint REST registrado.

  • bds_endpoint_regiao( $request ):
    • Busca o termo da taxonomia regiao pelo slug.
    • Consulta o CPT tema_regiao associado à região para obter banner e descrição.
    • Realiza consultas separadas para “novidades” e “mais acessadas” dentro daquela região.
    • Retorna um objeto JSON com os dados da região, tema e listas de receitas.
  • bds_endpoint_sorteio( $request ):
    • Constrói uma WP_Query com base nos filtros de regiao e subcategoria fornecidos.
    • Ordena por rand para retornar uma receita aleatória.
    • Retorna a receita formatada como um card.
  • bds_endpoint_favoritar( $request ):
    • Verifica se o post_id é válido e se o usuário está logado.
    • Gerencia a lista de favoritos do usuário (armazenada em user_meta bds_favoritos).
    • Adiciona ou remove o post_id da lista de favoritos.
    • Atualiza o post_meta total_favoritos da receita.
    • Retorna o status da ação e o novo total de favoritos.
  • bds_endpoint_receita( $request ):
    • Busca o post da receita pelo ID.
    • Retorna um objeto JSON completo com título, descrição, conteúdo, imagem, link, todos os metadados (ingredientesmodo_preparotempo_preparo, etc.), status de favorito para o usuário logado, e termos de regiao e subcategoria.

5. Helpers

Funções auxiliares reutilizáveis para consultas e formatação de dados.

  • bds_query_receitas_por_regiao( $slug_regiao, $args_extra = array() ):
    • Executa uma WP_Query para buscar receitas de uma regiao específica.
    • Permite argumentos extras para ordenação, paginação, etc.
    • Retorna um array de receitas formatadas como cards.
  • bds_formatar_card_receita( $post ):
    • Formata um objeto WP_Post (ou ID de post) em um array de dados simplificado, ideal para exibição em cards (ID, título, descrição, imagem, link, tempo de preparo, rendimento, dificuldade, região, subcategoria, status de favorito).
  • bds_usuario_favoritou( $user_id, $post_id ):
    • Verifica se um determinado usuário favoritou uma receita específica, consultando o user_meta bds_favoritos.
  • bds_get_receita_meta_array( $post_id, $meta_key ):
    • Recupera um metadado que se espera ser um array (como ingredientes ou modo_preparo).
    • Lida com casos onde o valor pode estar armazenado como string JSON ou array serializado, garantindo que sempre retorne um array.
  • bds_formatar_termos( $terms ):
    • Formata um array de objetos de termo (WP_Term) em um array mais simples com idnome e slug.

Documentação

cpt-taxonomias-rest.php: Este arquivo passa a ser a camada estrutural central do plugin, responsável por registrar os tipos de conteúdo, taxonomias, metadados e endpoints REST usados pelo frontend e pelos módulos internos. Responsabilidades Registrar o CPT receita. Registrar o CPT tema_regiao. Registrar as taxonomias regiao e subcategoria. Registrar os metadados principais da receita com suporte REST. Expor endpoints REST para região, sorteio, favoritar e leitura da single da receita. Mudanças aplicadas Inclusão de custom-fields no CPT receita, necessária para metadados registrados aparecerem corretamente na REST API. ingredientes e modo_preparo passaram a ser registrados como array com schema REST explícito, em vez de string. Criação do endpoint GET /wp-json/bds/v1/receita/{id} para payload completo da receita. Adição de args com sanitização e validação nas rotas REST, melhorando robustez do contrato da API. Inclusão de metas editoriais como bds_status_editorial e motivo_rejeicao, preparando integração com moderação e painel do usuário. Endpoints disponíveis GET /wp-json/bds/v1/regiao/{slug} → retorna dados da região, tema, novidades e mais acessadas. GET /wp-json/bds/v1/sorteio?regiao=...&subcategoria=... → retorna uma receita aleatória filtrada. POST /wp-json/bds/v1/favoritar → adiciona/remove favorito do usuário logado. GET /wp-json/bds/v1/receita/{id} → retorna payload completo da receita para single ou app frontend. Helpers internos bds_sanitize_array_strings() sanitiza arrays de strings para ingredientes e modo de preparo. bds_get_receita_meta_array() garante compatibilidade com dados antigos salvos como JSON string. bds_formatar_card_receita() padroniza payload reduzido para cards. bds_formatar_termos() normaliza taxonomias retornadas na API. Observações de compatibilidade O arquivo foi preparado para conviver com dados antigos que talvez ainda estejam salvos como JSON string em ingredientes e modo_preparo, então a migração pode ser feita sem quebra imediata. Mesmo assim, daqui em diante o ideal é que painel do usuário e importador passem a salvar esses campos já como array consistente, para reduzir ambiguidade na camada de dados.

painel-usuario.php: Este arquivo é a camada comunitária do plugin Brasil de Sabores, responsável por autenticação do usuário final, manutenção da conta, consulta de favoritos e submissão de receitas para curadoria editorial. Responsabilidades Renderizar o shortcode [bds_painel_usuario*]. (shorticode sem o * no final, aqui usado para não renderizar aqui nessa pagina). Exibir login/cadastro para visitantes. Exibir painel interno para usuários autenticados. Permitir atualização de conta. Listar favoritos do usuário. Listar receitas enviadas pelo próprio usuário. Receber submissão de receita com imagem destacada e enviar para moderação. Mudanças aplicadas Inclusão de um nonce dedicado ao painel autenticado, usado nas ações AJAX internas de favoritos e “minhas receitas”, o que corrige a inconsistência anterior entre HTML e validação no backend. Login refeito para autenticar por e-mail de forma mais previsível: primeiro localiza o usuário pelo e-mail e depois usa wp_signon() com o user_login real. Cadastro refeito para gerar user_login legível e único sem depender de usar o e-mail inteiro como login. Upload da imagem da receita migrado para media_handle_upload(), que é a função do core para salvar arquivo enviado por formulário e criar o attachment corretamente. ingredientes e modo_preparo agora são salvos como array, alinhados ao novo registro de meta do arquivo estrutural. O formulário de envio passou a coletar também tempo_preparo, rendimento e dificuldade, aproximando a submissão comunitária do modelo editorial final. Inclusão de bds_status_editorial = pendente ao criar receitas da comunidade, preparando integração com a moderação. Fluxos cobertos Visitante cria conta e entra no sistema. Usuário autenticado atualiza nome, e-mail e senha. Usuário consulta seus favoritos. Usuário consulta o status das próprias receitas enviadas. Usuário envia uma nova receita com taxonomias, ingredientes, modo de preparo e imagem. Dependências Este arquivo depende do registro prévio de: CPT receita. Taxonomias regiao e subcategoria. Helpers como bds_formatar_card_receita(). Metas ingredientes, modo_preparo, tempo_preparo, rendimento, dificuldade, link_original, bds_status_editorial e motivo_rejeicao. Pendências futuras Ainda faltará, em uma fase posterior: JavaScript do painel para trocar abas e disparar os AJAXs. CSS do painel do usuário. Possibilidade de editar receita rejeitada ou devolvida para ajustes. Exibição mais rica de status editoriais para a aba “Minhas receitas”.

moderacao-admin.php: Este arquivo é a camada editorial administrativa do plugin, responsável por transformar receitas enviadas pela comunidade em conteúdo revisado, publicado, devolvido para ajustes ou rejeitado. Responsabilidades Registrar e renderizar a página de moderação dentro do admin de receita. Listar receitas em pending e needs_revision. Aprovar receitas e publicá-las. Solicitar ajustes ao autor sem mandar o conteúdo para a lixeira. Rejeitar editorialmente preservando histórico em meta. Comunicar o autor por e-mail após cada decisão editorial. Mudanças aplicadas Substituição da lógica de “rejeitar = trash” por um fluxo editorial mais claro com: pending para envio inicial, needs_revision para itens que precisam de ajuste, draft + meta rejeitado para reprovação editorial. Registro do status needs_revision via register_post_status(), o que permite representar “precisa de ajustes” de forma mais correta no WordPress. Migração do CSS da página para carregamento via admin_enqueue_scripts condicionado ao hook_suffix, que é o padrão indicado para assets específicos do admin. Reforço de autorização com current_user_can() no menu, no render e em cada callback AJAX, usando também checagem por post quando necessário. Inclusão de ação intermediária “Solicitar ajustes”, em vez de forçar aprovação ou rejeição direta. Fluxo editorial adotado Receita enviada pelo usuário entra como post_status = pending e meta bds_status_editorial = pendente. Moderador pode: aprovar → publish + bds_status_editorial = publicado; solicitar ajustes → needs_revision + bds_status_editorial = em_revisao; rejeitar → draft + bds_status_editorial = rejeitado. Dependências Este arquivo depende de: CPT receita. Meta bds_status_editorial e motivo_rejeicao. Meta culinária (ingredientes, modo_preparo, tempo_preparo, rendimento, dificuldade, link_original). Helper bds_get_receita_meta_array() vindo do arquivo estrutural. Vantagens da nova abordagem O conteúdo não depende mais da lixeira para representar decisão editorial, o que melhora rastreabilidade e permite reaproveitar a receita no fluxo do autor. Além disso, o status “precisa de ajustes” cria um caminho mais humano e prático para colaboração com a comunidade. Pendências futuras Em uma etapa posterior, você ainda pode evoluir este arquivo com: paginação real; filtros por região, autor e status; campo interno de observações só para moderadores; histórico de ações editoriais por receita.

importador-json.php: Este arquivo é a camada de ingestão administrativa do plugin Brasil de Sabores, responsável por importar receitas em lote e normalizá-las para o modelo de conteúdo usado no site. Responsabilidades Criar submenu administrativo para importação JSON. Ler um arquivo JSON contendo um array de receitas. Importar ou atualizar uma receita por requisição AJAX. Evitar duplicação por link_original, slug e título. Criar/associar taxonomias automaticamente. Baixar imagem remota e definir como featured image. Registrar metadados de auditoria da importação. Mudanças aplicadas Remoção da dependência de get_page_by_title(), que não deve mais ser usada em WordPress moderno; a detecção de duplicata agora usa consultas com get_posts(). Inclusão de dois modos de duplicata: ignorar, quando a receita já existe; atualizar, quando a receita existente deve ser sobrescrita. Validação mais rígida do payload, exigindo titulo, ingredientes e modo_preparo, além de validar URLs remotas. Salvamento de arrays reais em ingredientes e modo_preparo, em vez de serializar manualmente como JSON string. Inclusão de metadados de auditoria: bds_origem_importacao bds_data_importacao bds_importado_por bds_slug_importado Alinhamento do status editorial com o status de publicação escolhido durante a importação. Política de duplicatas A busca por duplicata segue esta prioridade: link_original, quando existe. slug da receita. titulo, como fallback. Essa ordem reduz falsos positivos e melhora a idempotência da importação. Formato de JSON esperado Cada item do array pode conter: titulo slug opcional descricao regiao subcategoria ingredientes como array modo_preparo como array tempo_preparo rendimento dificuldade imagem_url link_original Dependências Este arquivo depende de: CPT receita. Taxonomias regiao e subcategoria. Metas ingredientes, modo_preparo, tempo_preparo, rendimento, dificuldade, link_original, bds_status_editorial. WordPress media functions download_url() e media_handle_sideload(). Observações operacionais O processamento continua sendo receita por receita via AJAX, o que é mais seguro para MVP do que uma única importação monolítica com muitas imagens. Para lotes muito grandes, no futuro pode valer migrar para lotes paginados por blocos ou processamento assíncrono mais avançado.