# Crocoblock — Automação Headless e Integrações Avançadas ## 1. JetEngine 3.8.0 — MCP Server Nativo A partir da versão 3.8.0, o JetEngine inclui um **MCP Server nativo** que expõe a topologia completa do site a agentes IA (Claude, Copilot, Cursor). ### Activar o MCP Server ``` WP Admin > JetEngine > AI Command Center > Enable MCP Server → URL do servidor: https://site.pt/wp-json/jet-engine/v1/mcp → Autenticação: Application Password ``` ### Capacidades do MCP | Capacidade | Descrição | |-----------|-----------| | Inspecção de schema | Lista CPTs, CCTs, Meta Boxes, Taxonomias, Relações | | Criação de CPT | Instanciar novo Custom Post Type via prompt | | Criação de CCT | Definir Custom Content Type com campos tipados | | Definir relações | Criar estruturas relacionais entre entidades | | Query Builder | Criar queries estruturadas | **Caso de uso:** Cliente especifica necessidades → Claude interroga MCP → constrói arquitectura completa (CPT + CCT + Relations + Queries) sem GUI. --- ## 2. JetFormBuilder — Formless Actions Endpoints O addon **Formless Actions Endpoints** permite usar as acções de um formulário JetFormBuilder como endpoint REST puro, sem renderizar formulário no frontend. ### Como Activar ``` JetFormBuilder > Settings > Formless Actions Endpoints: Enable Cada formulário recebe rota: POST /wp-json/jet-fb/v1/form/{form_id} ``` ### Payload de Exemplo ```bash # Submeter dados para formulário sem interface visual # Acciona todas as Post Submit Actions configuradas (Create Post, Email, Webhook, etc.) curl -X POST https://site.pt/wp-json/jet-fb/v1/form/1234 \ -H "Authorization: Basic dXNlcjpwYXNz..." \ -H "Content-Type: application/json" \ -d '{ "nome_cliente": "Empresa ABC", "email": "contacto@empresaabc.pt", "valor_contrato": 5000, "tipo_servico": "website" }' ``` ### Encadear Acções Complexas ``` Um único request pode: 1. Criar Post no CPT "Projecto" com status pending 2. Enviar email ao admin 3. Actualizar relação Cliente↔Projecto 4. Enviar Webhook para n8n 5. Criar registo em CCT "Notificacoes" ``` ### Interceptar com Hook Custom ```php get_all(); $texto = sanitize_textarea_field($dados['descricao'] ?? ''); $post_id = absint($dados['post_id'] ?? 0); if (empty($texto) || !$post_id) { // Cancelar o processamento com erro throw new \Jet_Form_Builder\Exceptions\Action_Exception('campos_obrigatorios_vazios'); } // Validação via API externa (exemplo: análise de risco) $score = minha_api_de_risco($texto); if ($score > 90) { throw new \Jet_Form_Builder\Exceptions\Action_Exception('risco_inaceitavel'); } // Actualizar meta field com o score calculado update_post_meta($post_id, '_score_risco', $score); $action_handler->add_response([ 'status' => 'success', 'message' => 'Processado com sucesso.', 'score' => $score, ]); }, 10, 2); ``` ### Tabela de Registos ```sql -- JetFormBuilder guarda registo de cada submissão SELECT * FROM wp_jet_fb_records WHERE form_id = 1234 ORDER BY id DESC LIMIT 10; ``` --- ## 3. JetSmartFilters — Indexer e Automação ### O Indexer O JetSmartFilters tem um subsistema de contagem chamado **Indexer** que mapeia contadores em `jet_smart_filters_indexer`. ```sql -- Ver contagens indexadas SELECT * FROM jet_smart_filters_indexer WHERE filter_id = 550 LIMIT 20; ``` **Problema:** Após actualizações SQL directas nas tabelas CCT ou wp_jet_rel_default, os contadores dos filtros ficam desactualizados. **Solução:** ```php indexer->index_all(); } }); ``` ```bash # Via WP-CLI PHP="/opt/alt/php-fpm83/usr/bin/php" WP="$PHP /usr/local/bin/wp --allow-root --path=/home/USER/public_html" $WP eval "jet_smart_filters()->indexer->index_all();" ``` ### Manipular Filtros Programaticamente ```php '100', 'max' => '500', ]; // Forçar AJAX $args['apply_type'] = 'ajax'; return $args; }, 10, 2); ``` ### Forçar Re-indexação após SQL Massivo ```php 'POST', 'callback' => function() { wp_cache_flush(); \Jet_Engine\Query_Builder\Manager::instance()->listings_cache->clear(); jet_smart_filters()->indexer->index_all(); return rest_ensure_response(['success' => true, 'message' => 'Re-indexação concluída.']); }, 'permission_callback' => function() { return current_user_can('edit_posts'); }, ]); }); ``` --- ## 4. Kits e Templates — Export/Import Programático ### Estrutura de um Kit ``` Kit JSON (manifest.json): ├── CPTs com todas as configurações ├── CCTs com schema de campos ├── Meta Boxes ├── Taxonomias ├── Relações ├── Query Builder queries ├── Listing Templates (Elementor) └── JetFormBuilder forms ``` ### Export via WP-CLI ```bash PHP="/opt/alt/php-fpm83/usr/bin/php" WP="$PHP /usr/local/bin/wp --allow-root --path=/home/USER/public_html" # Exportar estrutura JetEngine para JSON $WP eval ' $cpts = get_option("jet_engine_cpt", []); $ccls = get_option("jet_engine_ccl", []); $rels = get_option("jet_engine_relations", []); $metas = get_option("jet_engine_meta_boxes", []); $kit_data = compact("cpts", "ccls", "rels", "metas"); file_put_contents("/tmp/kit-jetengine.json", json_encode($kit_data, JSON_PRETTY_PRINT)); ' echo "Kit exportado para /tmp/kit-jetengine.json" ``` ### Import em Novo Ambiente ```bash # ATENÇÃO: os IDs das relações mudam entre ambientes # Sempre usar slugs como referência, não IDs numéricos $WP eval-file /tmp/import-kit.php $WP cache flush $WP rewrite flush ``` ### Pitfall de Migração — IDs de Relações ``` Problema: CCT item #45 no staging → ID #45 Mesmo item no production após import → ID #102 → Relações wp_jet_rel_default ficam com IDs errados Solução: Usar slug/título como referência durante migração Converter para ID após import via get_posts(['name' => 'slug']) Ou usar WP All Import para recriar relações com mapeamento de IDs ``` --- ## 5. Integração WooCommerce + JetEngine ### Queries em Produtos WooCommerce ``` Produtos WooCommerce são CPT 'product' → compatíveis com JetEngine Query Builder pode filtrar produtos por meta fields JetEngine adicionados JetWooBuilder consome estas queries para listagens customizadas ``` ### Relações com Produtos ```sql -- Produtos relacionados com CPT "Fornecedor" via JetEngine Relations SELECT p.post_title AS produto, f.post_title AS fornecedor FROM wp_posts p JOIN wp_jet_rel_default r ON r.child_object_id = p.ID JOIN wp_posts f ON f.ID = r.parent_object_id WHERE r.rel_id = 'relacao_fornecedores_produtos' AND p.post_status = 'publish'; ``` --- ## 6. Limitações e Riscos Críticos | Risco | Impacto | Mitigação | |-------|---------|-----------| | SQL directo em wp_postmeta serializado | **Crítico** — corrupção de dados | NUNCA. Usar PHP `unserialize → edit → serialize` | | store_items_type = "replace" na REST API | **Destrutivo** — apaga todas as relações | Usar "update" salvo intenção explícita | | Alterar wp_options serializados via SQL | **Crítico** — instalação WordPress corrompida | Sempre via PHP `get_option → update_option` | | SQL sem flush de cache | Dados obsoletos em listings | Sempre `wp_cache_flush()` + `listings_cache->clear()` + `indexer->index_all()` | | Registar meta boxes antes de init prioridade 12 | Falha silenciosa | Usar hook `jet-engine/meta-boxes/register-instances` | | Importar Kit entre versões JetEngine diferentes | Dependências fantasma no Query Builder | Manter versões alinhadas em staging e production | --- *Crocoblock Automation | Descomplicar® | 18-02-2026*