Pular para o conteúdo

doc

Auditoria SRP Blog Plugin v2.0.1
5
Erros Críticos
6
Avisos / Warnings
3
Incompatibilidades
9
Arquivos Auditados

01Mapa Estrutural do Plugin

srp-blog/ — estrutura completa de arquivos
srp-blog.php
⚠ WARN
Arquivo principal. Define constantes, hook de ativação, rewrite rules e carrega os includes. Contém a definição de usuários e senhas em texto puro via define(). O hook plugins_loaded para upgrade automático está registrado antes dos require_once — isso é seguro pois a ação dispara depois da execução completa do arquivo, mas merece atenção.
├─
includes/
⛔ ERROS
Pasta de classes PHP do backend.
│ ├─
class-db.php
⚠ COMPAT
SRP_Blog_DB — Camada de acesso ao banco de dados. Todos os métodos são estáticos. Gerencia posts e categorias com tabelas customizadas. Problema: usa union types int|false nos retornos de insert_post() e insert_category(), que exige PHP 8.0+. Compatibilidade com PHP 7.4 quebrada.
│ ├─
class-ajax.php
⛔ CRÍTICO
SRP_Blog_Ajax — Registra e trata todas as ações AJAX (wp_ajax_ e wp_ajax_nopriv_). Instancia a própria classe ao final do arquivo. Problemas críticos: (1) handle_save_cat() chama wp_send_json_error() sem return após verificar nome vazio — execução continua indevidamente. (2) handle_login() chama wp_send_json_success() dentro do foreach sem return — se o WP não encerrar a execução (em testes unitários, por ex.) pode gerar comportamento duplo. (3) handle_save_post(): falta return no bloco de falha do insert.
│ └─
class-shortcode.php
✓ OK
SRP_Blog_Shortcode — Registra os shortcodes [srp_blog_manager] e [srp_blog]. Enfileira assets CSS/JS apenas nas páginas que contêm os shortcodes. Lógica correta e bem estruturada.
├─
admin/
⚠ WARN
Interface administrativa WordPress.
│ └─
admin-page.php
⚠ WARN
Registra menu no painel WP, páginas de listagem de posts, criar/editar post e categorias. Usa wp_editor() para o TinyMCE. Problema: o elemento id="srpAdminToasts" está duplicado — aparece tanto em srp_blog_admin_page_novo() quanto em srp_blog_admin_page_cats(). IDs duplicados no mesmo DOM são inválidos em HTML e causam falha no JS que busca por esse ID.
├─
templates/
⛔ CRÍTICO
Templates PHP renderizados via shortcode ou template_redirect.
│ ├─
blog-single.php
⛔ CRÍTICO
ERRO FATAL — variável $post é definida na linha 11 ($post = SRP_Blog_DB::get_post_by_slug(...)), mas todo o restante do template usa $srp_post (inexistente). Isso gera erros fatais PHP “Attempt to read property on null/non-object” em todas as páginas de post individual. O plugin não funciona neste estado.
│ ├─
blog-manager.php
✓ OK
Template do gestor frontend (shortcode [srp_blog_manager]). Renderiza: tela de login, painel principal com abas (Posts, Criar Post, Categorias), editor rich text via contenteditable, e modais. Bem estruturado, sem erros de sintaxe.
│ └─
blog-public.php
✓ OK
Template público (shortcode [srp_blog]). Exibe grid de cards de posts com filtros por categoria. Depende das variáveis $posts e $cats injetadas pelo shortcode — correto.
└─
assets/
✓ OK
Recursos estáticos.
├─
css/srp-blog-admin.css
✓ OK
Estilos do painel administrativo WordPress. Arquivo robusto (~32KB). Sem problemas identificados.
├─
css/srp-blog-frontend.css
✓ OK
Estilos do frontend público e do gestor. Arquivo extenso (~44KB). Sem problemas identificados.
├─
js/srp-blog-admin.js
✓ OK
JS do painel admin. Usa objeto srpBlogAdmin localizado via wp_localize_script(). Gerencia tabela, modais, TinyMCE, upload de imagem e HTML. Lógica correta.
└─
js/srp-blog-frontend.js
⚠ WARN
JS do gestor frontend. Usa objeto srpBlogData localizado via wp_localize_script(). Editor rich text via document.execCommand (API depreciada). Sem erros de sintaxe; funcional mas com dependência de API obsoleta.

02Shortcodes & Credenciais de Acesso

Atenção de segurança: As senhas estão armazenadas em texto puro dentro de uma constante PHP no arquivo principal do plugin (srp-blog.php). Qualquer pessoa com acesso ao servidor ou ao repositório pode vê-las. Recomenda-se migrá-las para a tabela wp_options com hash (wp_hash_password).

Shortcodes disponíveis

Blog Público [srp_blog] — exibe o grid público de posts com filtros por categoria Parâmetros [srp_blog limite="12" categoria=""] Uso Inserir em qualquer página WordPress via editor de blocos ou clássico Gestor [srp_blog_manager] — painel de criação/edição de posts (requer login) Uso Inserir em página restrita (ex.: “Área do Editor”) — exibe tela de login automática Post Individual Rota automática via rewrite rule — não requer shortcode URL /blog/{slug-do-post}

Usuários e senhas do gestor frontend

Usuário (slug) Nome Exibido Senha Atual Autor Padrão Gênero
maura Maura Lídia 0118 Maura Lídia do Vale f
michel Michel 2882 Michel Lima m
ℹ O login é feito pela senha apenas (sem nome de usuário). O sistema percorre a lista de usuários e autentica quem tiver a senha correspondente. A sessão PHP é usada para manter o estado.

Credenciais do painel admin WordPress

O painel administrativo (wp-admin > Blog SRP) usa autenticação nativa do WordPress. Requer usuário com papel Administrator (manage_options). Não há senhas customizadas nesta camada.

03Erros Críticos — Impedem Funcionamento

CRÍTICO #1
Variável errada em blog-single.php — Fatal Error em todo post individual
templates/blog-single.php · linhas 16–120

O arquivo define $post na linha 11, mas em seguida usa $srp_post em todas as demais referências (18 ocorrências). $srp_post nunca é definida — PHP 8 lança TypeError fatal; PHP 7 gera Notice e retorna null, quebrando a renderização. Nenhum post individual pode ser exibido.

❌ Código com erro (linhas 11 e 16)
11 $post = SRP_Blog_DB::get_post_by_slug( sanitize_text_field( $slug ) );

16 $cat_ids = array_filter( explode( ‘,’, $srp_post->categoria_ids ) ); // ← $srp_post não existe!
22 add_action( ‘wp_head’, function() use ( $post, $site_name ) {
23 $srp_post->imagem_destaque … // ← $srp_post não capturada no use()
✓ Correção: substituir $post por $srp_post na linha 11 (ou vice-versa — escolha um nome e padronize)
// OPÇÃO A: renomear a variável atribuída para $srp_post
11 $srp_post = SRP_Blog_DB::get_post_by_slug( sanitize_text_field( $slug ) );

// E corrigir o closure do add_action para capturar $srp_post:
22 add_action( ‘wp_head’, function() use ( $srp_post, $site_name ) {
Além da renomeação, verificar que o redirect em srp-blog.php já valida se o post existe antes de incluir o template — isso está correto. A correção é apenas no template.
CRÍTICO #2
handle_save_cat(): execução continua após wp_send_json_error() sem return
includes/class-ajax.php · linha 194

wp_send_json_error() não encerra a execução automaticamente em todas as versões do WordPress (antes do WP 5.5, o segundo parâmetro $status_code é ignorado e não há exit). Mesmo nas versões modernas, omitir return é má prática. Se o nome estiver vazio, o código envia o JSON de erro mas continua executando e tenta atualizar/inserir a categoria com nome vazio.

❌ Código com erro
if ( empty( $nome ) ) {
wp_send_json_error( [ ‘message’ => ‘O nome da categoria é obrigatório.’ ] );
// ← FALTA return; aqui!
}
// execução continua e tenta salvar categoria com nome vazio
✓ Correção
if ( empty( $nome ) ) {
wp_send_json_error( [ ‘message’ => ‘O nome da categoria é obrigatório.’ ] );
return;
}
CRÍTICO #3
handle_save_post(): falta return após falha no insert — resposta dupla
includes/class-ajax.php · linhas 133–139

No bloco de criação de novo post, se insert_post() retornar o ID válido, wp_send_json_success() é chamado — mas a execução cai em seguida para o wp_send_json_error() logo abaixo, porque não há return dentro do if ( $new_id ). Isso gera duas respostas JSON ou, no melhor caso, corrompe o output se o WordPress não encerrar imediatamente.

❌ Código com erro
if ( $new_id ) {
$post = SRP_Blog_DB::get_post_by_id( $new_id );
wp_send_json_success( [ ‘id’ => $new_id, ‘slug’ => $post->slug, ‘action’ => ‘created’ ] );
// ← FALTA return;
}
wp_send_json_error( [ ‘message’ => ‘Erro ao salvar o post.’ ] ); // ← chamado mesmo com sucesso
✓ Correção
if ( $new_id ) {
$post = SRP_Blog_DB::get_post_by_id( $new_id );
wp_send_json_success( [ ‘id’ => $new_id, ‘slug’ => $post->slug, ‘action’ => ‘created’ ] );
return;
}
wp_send_json_error( [ ‘message’ => ‘Erro ao salvar o post.’ ] );
CRÍTICO #4
Union types int|false incompatível com PHP 7.4 — Fatal Error na ativação
includes/class-db.php · linhas 159, 250

Os métodos insert_post() e insert_category() declaram o tipo de retorno int|false. Union types são suportados apenas a partir do PHP 8.0. O WordPress declara suporte mínimo ao PHP 7.4 — em servidores com PHP 7.x, o plugin causará um Fatal Error na ativação, impedindo completamente a instalação. Este é provavelmente o erro que impede a instalação relatado.

❌ Código com erro
public static function insert_post( array $data ): int|false { // ← PHP 8.0+ apenas
public static function insert_category( string $nome ): int|false { // ← PHP 8.0+ apenas
✓ Correção — compatível com PHP 7.4+
// Opção A: remover o tipo de retorno (mais simples)
public static function insert_post( array $data ) {
public static function insert_category( string $nome ) {

// Opção B: usar docblock (sem custo de performance)
/** @return int|false */
public static function insert_post( array $data ) {
Adicionar “Requires PHP: 8.0” no cabeçalho do plugin se a intenção for manter PHP 8, ou remover os union types para suportar PHP 7.4+.
CRÍTICO #5
blog-single.php: $srp_post não capturada no closure do wp_head
templates/blog-single.php · linha 22

Mesmo após corrigir o nome da variável (bug #1), o closure passado para add_action('wp_head', ...) usa a cláusula use($post, $site_name), mas referencia $srp_post dentro do corpo. A variável precisa ser capturada corretamente no use().

❌ Código com erro
add_action( ‘wp_head’, function () use ( $post, $site_name ) { // captura $post
$srp_post->imagem_destaque // mas usa $srp_post — não definida no escopo
} );
✓ Correção (após aplicar fix #1 — variável renomeada para $srp_post)
add_action( ‘wp_head’, function () use ( $srp_post, $site_name ) {
$img = $srp_post->imagem_destaque ? …
} );

04Avisos — Problemas que Prejudicam o Funcionamento

AVISO #1
ID HTML duplicado “srpAdminToasts” em admin-page.php
admin/admin-page.php · linhas 307 e 390

O elemento <div id="srpAdminToasts"> é gerado em duas funções diferentes que podem coexistir no mesmo carregamento de página (ao navegar entre páginas do admin, o WP carrega as funções todas). IDs duplicados são inválidos no HTML e causam comportamento imprevisível no JavaScript que busca o toast container.

Renomear o segundo para id="srpAdminToastsCats" e ajustar a referência no JS de categorias.
AVISO #2
handle_login(): wp_send_json_success() sem return dentro do foreach
includes/class-ajax.php · linha 83

Quando a senha é encontrada, wp_send_json_success() é chamado dentro do foreach, mas sem return. O WordPress encerra a execução via exit internamente nessa função, portanto na prática funciona — mas é uma prática problemática: em testes unitários (onde exit pode ser interceptado) ou refatorações futuras, o loop continuaria iterando e poderia chamar wp_send_json_error() em seguida.

✓ Correção recomendada
if ( $user[‘senha’] === $senha ) {
// … configura sessão …
wp_send_json_success( […] );
return; // ← adicionar
}
AVISO #3
Senhas em texto puro em constante PHP no código-fonte
srp-blog.php · linhas 29–45

As senhas '0118' e '2882' estão em texto puro dentro de uma constante PHP definida no arquivo principal do plugin. Qualquer acesso ao sistema de arquivos do servidor expõe essas credenciais diretamente. Além disso, não há mecanismo de expiração ou troca de senha pelo painel.

Migrar para wp_options com hashing via wp_hash_password(). Criar uma página de configuração no admin para alterar as senhas sem editar código.
AVISO #4
document.execCommand() depreciado em srp-blog-frontend.js
assets/js/srp-blog-frontend.js · múltiplas linhas

O editor rich text do gestor frontend usa document.execCommand('bold'), execCommand('foreColor'), etc. Essa API foi marcada como depreciada pelo W3C e pode ser removida em versões futuras de navegadores. Atualmente ainda funciona em todos os browsers, mas é tecnicamente obsoleta.

A longo prazo, migrar para uma solução como Quill.js ou ProseMirror. Por ora, funciona mas gera warnings no console de browsers modernos.
AVISO #5
Sessão PHP iniciada em contexto de shortcode — potencial conflito
includes/class-shortcode.php · linha 57 | templates/blog-manager.php · linha 4

session_start() é chamado no método render_manager() e também no topo de blog-manager.php. Em ambientes com caching (como WP Super Cache ou LiteSpeed Cache) ou com headers já enviados por outro plugin, session_start() pode falhar silenciosamente ou lançar um warning de “headers already sent”. A verificação if (!session_id()) já existe, o que é boa prática, mas o risco permanece.

Considerar mover o session_start() para um hook mais cedo (ex.: init) em vez de chamá-lo dentro do shortcode. Verificar compatibilidade com plugins de caching ativos no servidor.
AVISO #6
date() sem timezone definido pode gerar datas incorretas
includes/class-ajax.php · handle_download_post() | templates/blog-public.php

Chamadas como date('d/m/Y', strtotime(...)) usam o timezone padrão do PHP (date_default_timezone_get()), que pode não coincidir com o timezone configurado no WordPress (Settings > General > Timezone). Isso pode exibir datas com diferença de horas.

✓ Correção — usar funções WordPress
// Substituir:
date( ‘d/m/Y’, strtotime( $p->data_publicacao ) )

// Por:
get_date_from_gmt( $p->data_publicacao, ‘d/m/Y’ )

05Incompatibilidades de Versão

COMPAT #1
PHP Union Types (int|false) — requer PHP 8.0, plugin não declara isso
includes/class-db.php

Já detalhado no Crítico #4. O cabeçalho do plugin não contém Requires PHP: 8.0, então o WordPress não bloqueia a ativação em PHP 7.x, resultando em fatal error silencioso que impede qualquer uso.

Adicionar * Requires PHP: 8.0 ao cabeçalho de srp-blog.php, OU remover os union types para suportar PHP 7.4+.
COMPAT #2
Arrow functions (fn()) — requer PHP 7.4+
includes/class-db.php, templates/blog-*.php, includes/class-ajax.php

Arrow functions (fn($x) => ...) são usadas extensivamente em todo o plugin. Elas requerem PHP 7.4+, que é o mínimo atual do WordPress. Isso é compatível, mas é bom documentar que o plugin não suporta versões anteriores.

Sem ação necessária se o servidor estiver em PHP 7.4+. Garantir que o servidor de produção do cliente esteja atualizado.
COMPAT #3
wp_send_json_error() com código HTTP — comportamento varia antes do WP 4.1
includes/class-ajax.php · linha 52

wp_send_json_error(['message'=>'...'], 401) usa o segundo parâmetro (HTTP status code) introduzido no WordPress 4.1. Em instalações muito antigas isso é ignorado, mas não causa erro — apenas o código HTTP retorna 200 ao invés de 401.

Sem ação necessária se o WordPress estiver atualizado (qualquer versão pós-2015 suporta isso).

06Análise do Banco de Dados

Tabelas criadas pelo plugin

  • {prefix}srp_blog_categories — tabela de categorias com id, nome, slug (UNIQUE), criado_em. Estrutura correta.
  • {prefix}srp_blog_posts — tabela de posts com id, titulo, slug (UNIQUE), resumo, conteudo (LONGTEXT), categoria_ids (CSV), autor, imagem_destaque, data_publicacao, status, criado_em, atualizado_em. Índices criados em status, slug e data_publicacao.
  • dbDelta() é usado corretamente para criar/atualizar as tabelas, o que garante idempotência na ativação e upgrade.
  • Upgrade automático via hook plugins_loaded compara a versão salva em wp_options com a constante do plugin — correto.
  • ⚠️
    categoria_ids como CSV — armazenar IDs de categorias em texto separado por vírgula ("1,3,5") é funcional mas não normalizado. Funciona com FIND_IN_SET() no MySQL, mas prejudica performance em grandes volumes. Aceitável para blogs de baixo tráfego.
  • Sanitização — todos os inputs passam por sanitize_text_field(), sanitize_textarea_field(), wp_kses_post() ou esc_url_raw() antes de ir ao banco. Correto e seguro.
  • Queries preparadas — uso consistente de $wpdb->prepare() em todos os SELECTs com parâmetros. Sem risco de SQL injection.
  • Deleção de categoria — ao excluir uma categoria, o código remove o ID de categoria_ids de todos os posts vinculados. Integridade referencial mantida manualmente.

07Análise das Ações AJAX

Mapa de ações registradas

Ação AJAXHandlerAuthStatus
srp_blog_loginhandle_login()Nonce apenas⚠ return ausente
srp_blog_logouthandle_logout()Nenhuma✓ OK
srp_blog_save_posthandle_save_post()Nonce + sessão⛔ return ausente
srp_blog_delete_posthandle_delete_post()Nonce + sessão✓ OK
srp_blog_get_posthandle_get_post()Nonce apenas✓ OK
srp_blog_get_postshandle_get_posts()Nonce apenas✓ OK
srp_blog_save_cathandle_save_cat()Nonce + sessão⛔ return ausente
srp_blog_delete_cathandle_delete_cat()Nonce + sessão✓ OK
srp_blog_get_catshandle_get_cats()Nonce apenas✓ OK
srp_blog_upload_imagehandle_upload_image()Nonce + sessão✓ OK
srp_blog_upload_htmlhandle_upload_html()Nonce + sessão✓ OK
srp_blog_download_posthandle_download_post()Nonce + sessão✓ OK
srp_blog_admin_deletehandle_admin_delete()Nonce + manage_options✓ OK
srp_blog_admin_statushandle_admin_status()Nonce + manage_options✓ OK
Nonces usados: 'srp_blog_nonce' para ações do frontend, 'srp_blog_admin_nonce' para ações exclusivas do admin WP. Os objetos JS localizados são srpBlogData (frontend) e srpBlogAdmin (admin). O admin recebe ambos os nonces (nonce e fnonce).

08Resumo e Ordem de Correção

Correções obrigatórias (por ordem de prioridade)

  • 🔴
    [Fix #4 — PRIMEIRO] Remover ou substituir union types int|false em class-db.php. Este é o erro que impede a instalação em PHP 7.x. Adicionar * Requires PHP: 8.0 ao cabeçalho se preferir manter a sintaxe.
  • 🔴
    [Fix #1 + #5] Em blog-single.php: renomear a variável da linha 11 de $post para $srp_post, e atualizar o use($post, ...) do closure na linha 22 para use($srp_post, ...).
  • 🔴
    [Fix #2] Em class-ajax.php, método handle_save_cat(): adicionar return; após o wp_send_json_error() da validação de nome vazio.
  • 🔴
    [Fix #3] Em class-ajax.php, método handle_save_post(): adicionar return; dentro do bloco if ($new_id), antes que a execução caia no wp_send_json_error().
  • 🟡
    [Fix #6] Em class-ajax.php, método handle_login(): adicionar return; após wp_send_json_success() dentro do foreach.
  • 🟡
    [Fix #7] Em admin-page.php: renomear o segundo id="srpAdminToasts" para algo único e atualizar a referência correspondente no JS.
  • 🟢
    [Opcional] Migrar senhas para wp_options com hash. Substituir date() por get_date_from_gmt(). Testar compatibilidade do session_start() com o plugin de cache ativo no servidor.

O que está correto e não precisa ser alterado

  • Estrutura de tabelas do banco de dados e uso de dbDelta()
  • Sanitização de inputs e uso de $wpdb->prepare()
  • Verificação de nonces em todas as ações AJAX
  • Rewrite rules para /blog/{slug} com flush seguro
  • Enfileiramento condicional de assets (só carrega onde necessário)
  • Lógica de slug único com deduplicação automática
  • Template blog-manager.php e blog-public.php sem erros
  • JS admin e frontend sem erros de sintaxe
  • CSS admin e frontend sem problemas
📋 Conclusão: O plugin tem uma arquitetura sólida e bem pensada. Os erros encontrados são pontuais e corrigíveis em minutos. O principal bloqueador da instalação é o uso de union types PHP 8 sem declaração no cabeçalho. O segundo bloqueador funcional é a variável errada em blog-single.php que impede toda exibição de posts individuais. Com as 6 correções críticas aplicadas, o plugin estará completamente funcional.

Utilizamos cookies para oferecer uma experiência personalizada em nosso orquidário digital. Veja nossa Política de Privacidade.