- All SKILL.md files now <500 lines (avg reduction 69%) - Detailed content extracted to references/ subdirectories - Frontmatter standardised: only name + description (Anthropic standard) - New skills: brand-guidelines, spec-coauthor, report-templates, skill-creator - Design skills: anti-slop guidelines, premium-proposals reference - Removed non-standard frontmatter fields (triggers, version, author, category) Plugins affected: infraestrutura, marketing, dev-tools, crm-ops, gestao, core-tools, negocio, perfex-dev, wordpress, design-media Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
376 lines
11 KiB
Markdown
376 lines
11 KiB
Markdown
---
|
|
name: perfex-hooks
|
|
description: Sistema de hooks Perfex CRM — actions, filters, add_action, add_filter, do_action, apply_filters com lista completa por categoria. Baseado apenas na documentação oficial.
|
|
---
|
|
|
|
# /perfex-hooks - Sistema de Hooks Perfex CRM
|
|
|
|
Sistema de extensibilidade via actions e filters. **Zero assumptions, zero hallucinations** - apenas documentação oficial.
|
|
|
|
---
|
|
|
|
## Documentação Base
|
|
|
|
- [Action Hooks](https://help.perfexcrm.com/action-hooks/)
|
|
- [GitHub Hook List](https://gist.github.com/JamesSimpson/4eae4ba2d6d7072eca9f0fae58b8887c)
|
|
|
|
---
|
|
|
|
## Conceitos Fundamentais
|
|
|
|
| Tipo | Função | Retorno | Uso |
|
|
|------|--------|---------|-----|
|
|
| **Action** | Executa lógica após eventos | void | Side effects (logs, emails, etc.) |
|
|
| **Filter** | Modifica dados antes de processamento | Dados modificados | Alterar valores |
|
|
|
|
---
|
|
|
|
## Sintaxe (v2.3.0+)
|
|
|
|
### Registar Action
|
|
|
|
```php
|
|
hooks()->add_action($tag, $callback, $priority = 10, $accepted_args = 1);
|
|
```
|
|
|
|
**Parâmetros:**
|
|
- `$tag` (string): Nome do hook
|
|
- `$callback` (callable): Função a executar
|
|
- `$priority` (int): Ordem de execução (menor = primeiro). Default: 10
|
|
- `$accepted_args` (int): Número de argumentos. Default: 1
|
|
|
|
**Exemplo:**
|
|
|
|
```php
|
|
// No init file do módulo
|
|
hooks()->add_action('after_client_added', 'meu_modulo_after_client_added');
|
|
|
|
function meu_modulo_after_client_added($clientId)
|
|
{
|
|
// Lógica após cliente criado
|
|
log_activity('Novo cliente criado: ' . $clientId);
|
|
|
|
// Enviar notificação
|
|
$CI = &get_instance();
|
|
$CI->load->model('clients_model');
|
|
$client = $CI->clients_model->get($clientId);
|
|
|
|
// Integração externa, etc.
|
|
}
|
|
```
|
|
|
|
### Registar Filter
|
|
|
|
```php
|
|
hooks()->add_filter($tag, $callback, $priority = 10, $accepted_args = 1);
|
|
```
|
|
|
|
**Exemplo:**
|
|
|
|
```php
|
|
hooks()->add_filter('before_client_added', 'meu_modulo_before_client_added');
|
|
|
|
function meu_modulo_before_client_added($data)
|
|
{
|
|
// Modificar dados antes de guardar
|
|
if (empty($data['country'])) {
|
|
$data['country'] = 177; // Portugal
|
|
}
|
|
|
|
// OBRIGATÓRIO: retornar dados modificados
|
|
return $data;
|
|
}
|
|
```
|
|
|
|
### Executar Action (criar hooks próprios)
|
|
|
|
```php
|
|
hooks()->do_action($tag, $arg = '');
|
|
```
|
|
|
|
**Exemplo:**
|
|
|
|
```php
|
|
// No teu módulo, permitir que outros módulos executem código
|
|
hooks()->do_action('meu_modulo_after_process', $resultId);
|
|
```
|
|
|
|
### Aplicar Filter (criar filters próprios)
|
|
|
|
```php
|
|
hooks()->apply_filters($tag, $value, $additionalParams = []);
|
|
```
|
|
|
|
**Exemplo:**
|
|
|
|
```php
|
|
// Permitir que outros módulos modifiquem dados
|
|
$data = hooks()->apply_filters('meu_modulo_data', $data);
|
|
```
|
|
|
|
---
|
|
|
|
## Onde Colocar Hooks
|
|
|
|
### Opção 1: Init File do Módulo (Recomendado)
|
|
|
|
```php
|
|
// modules/meu_modulo/meu_modulo.php
|
|
hooks()->add_action('after_client_added', 'meu_modulo_client_handler');
|
|
```
|
|
|
|
### Opção 2: my_functions_helper.php (Customizações Simples)
|
|
|
|
```php
|
|
// application/helpers/my_functions_helper.php
|
|
hooks()->add_action('after_client_added', 'custom_client_handler');
|
|
```
|
|
|
|
---
|
|
|
|
## Lista Completa de Hooks por Categoria
|
|
|
|
### Autenticação
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `admin_auth_init` | Início auth admin | - |
|
|
| `after_staff_login` | Após login staff | $staff_id |
|
|
| `after_user_logout` | Após logout | - |
|
|
| `after_contact_login` | Após login contacto | $contact_id |
|
|
| `after_client_register` | Após registo cliente | $client_id |
|
|
| `after_client_logout` | Após logout cliente | - |
|
|
|
|
### Clientes
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `before_client_added` | **FILTER** - Antes de criar | $data |
|
|
| `after_client_added` | Após criar cliente | $client_id |
|
|
| `before_client_updated` | **FILTER** - Antes de actualizar | $data, $client_id |
|
|
| `after_client_updated` | Após actualizar | $client_id |
|
|
| `before_client_deleted` | Antes de apagar | $client_id |
|
|
| `after_client_deleted` | Após apagar | $client_id |
|
|
| `contact_created` | Contacto criado | $contact_id |
|
|
| `contact_updated` | Contacto actualizado | $contact_id |
|
|
| `before_delete_contact` | Antes apagar contacto | $contact_id |
|
|
| `contact_deleted` | Contacto apagado | $contact_id |
|
|
|
|
### Facturas
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `before_invoice_added` | **FILTER** - Antes de criar | $data |
|
|
| `after_invoice_added` | Após criar | $invoice_id |
|
|
| `before_invoice_updated` | **FILTER** - Antes de actualizar | $data, $invoice_id |
|
|
| `after_invoice_updated` | Após actualizar | $invoice_id |
|
|
| `invoice_sent` | Factura enviada | $invoice_id |
|
|
| `invoice_status_changed` | Status alterado | $invoice_id, $status |
|
|
| `before_invoice_deleted` | Antes de apagar | $invoice_id |
|
|
| `invoice_marked_as_cancelled` | Factura cancelada | $invoice_id |
|
|
|
|
### Orçamentos (Estimates)
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `before_estimate_added` | **FILTER** - Antes de criar | $data |
|
|
| `after_estimate_added` | Após criar | $estimate_id |
|
|
| `after_estimate_updated` | Após actualizar | $estimate_id |
|
|
| `estimate_sent` | Orçamento enviado | $estimate_id |
|
|
| `estimate_accepted` | Aceite pelo cliente | $estimate_id |
|
|
| `estimate_declined` | Rejeitado | $estimate_id |
|
|
| `estimate_converted_to_invoice` | Convertido em factura | $estimate_id, $invoice_id |
|
|
|
|
### Propostas
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `proposal_created` | Proposta criada | $proposal_id |
|
|
| `after_proposal_updated` | Após actualizar | $proposal_id |
|
|
| `proposal_sent` | Proposta enviada | $proposal_id |
|
|
| `proposal_accepted` | Aceite | $proposal_id |
|
|
| `proposal_declined` | Rejeitada | $proposal_id |
|
|
| `proposal_converted_to_invoice` | → Factura | $proposal_id |
|
|
| `proposal_converted_to_estimate` | → Orçamento | $proposal_id |
|
|
|
|
### Leads
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `lead_created` | Lead criado | $lead_id |
|
|
| `before_lead_deleted` | Antes de apagar | $lead_id |
|
|
| `lead_marked_as_lost` | Marcado perdido | $lead_id |
|
|
| `lead_marked_as_junk` | Marcado spam | $lead_id |
|
|
| `lead_converted_to_customer` | Convertido | $lead_id, $customer_id |
|
|
|
|
### Tarefas
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `after_add_task` | Tarefa criada | $task_id |
|
|
| `after_update_task` | Tarefa actualizada | $task_id |
|
|
| `task_status_changed` | Status alterado | $task_id, $status |
|
|
| `task_deleted` | Tarefa apagada | $task_id |
|
|
| `task_timer_started` | Timer iniciado | $task_id, $staff_id |
|
|
| `task_timer_deleted` | Timer apagado | $timer_id |
|
|
| `task_comment_added` | Comentário adicionado | $comment_id, $task_id |
|
|
| `task_checklist_item_created` | Checklist item criado | $item_id |
|
|
| `task_checklist_item_finished` | Checklist item concluído | $item_id |
|
|
|
|
### Projectos
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `after_add_project` | Projecto criado | $project_id |
|
|
| `after_update_project` | Projecto actualizado | $project_id |
|
|
| `before_remove_project_file` | Antes remover ficheiro | $file_id |
|
|
|
|
### Staff
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `staff_member_created` | Staff criado | $staff_id |
|
|
| `staff_member_updated` | Staff actualizado | $staff_id |
|
|
| `staff_member_profile_updated` | Perfil actualizado | $staff_id |
|
|
|
|
### Pagamentos
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `after_payment_added` | Pagamento registado | $payment_id |
|
|
| `customer_subscribed_to_subscription` | Subscrição activada | $subscription_id |
|
|
| `credit_note_refund_created` | Reembolso criado | $refund_id |
|
|
|
|
### Contratos
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `after_contract_added` | Contrato criado | $contract_id |
|
|
| `after_contract_updated` | Contrato actualizado | $contract_id |
|
|
| `before_contract_deleted` | Antes de apagar | $contract_id |
|
|
| `contract_html_viewed` | Contrato visualizado | $contract_id |
|
|
|
|
### Tickets
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `ticket_created` | Ticket criado | $ticket_id |
|
|
| `before_ticket_deleted` | Antes de apagar | $ticket_id |
|
|
| `before_delete_ticket_reply` | Antes apagar resposta | $reply_id |
|
|
|
|
### Módulos
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `modules_loaded` | Módulos carregados | - |
|
|
| `pre_activate_module` | Antes de activar | $module_name |
|
|
| `module_activated` | Módulo activado | $module_name |
|
|
| `pre_deactivate_module` | Antes de desactivar | $module_name |
|
|
| `module_deactivated` | Módulo desactivado | $module_name |
|
|
| `module_installed` | Módulo instalado | $module_name |
|
|
| `pre_uninstall_module` | Antes de desinstalar | $module_name |
|
|
| `module_uninstalled` | Módulo desinstalado | $module_name |
|
|
|
|
### UI / Templates
|
|
|
|
| Hook | Trigger | Argumentos |
|
|
|------|---------|------------|
|
|
| `app_admin_head` | Header admin | - |
|
|
| `app_admin_footer` | Footer admin | - |
|
|
| `before_start_render_dashboard_content` | Antes dashboard | - |
|
|
| `after_dashboard` | Após dashboard | - |
|
|
| `before_render_aside_menu` | Antes menu lateral | - |
|
|
| `after_render_aside_menu` | Após menu lateral | - |
|
|
|
|
---
|
|
|
|
## Exemplos Práticos
|
|
|
|
### 1. Integração Externa Após Cliente Criado
|
|
|
|
```php
|
|
hooks()->add_action('after_client_added', 'sync_to_external_crm');
|
|
|
|
function sync_to_external_crm($clientId)
|
|
{
|
|
$CI = &get_instance();
|
|
$CI->load->model('clients_model');
|
|
$client = $CI->clients_model->get($clientId);
|
|
|
|
// Enviar para API externa
|
|
$response = wp_remote_post('https://api.externa.com/customers', [
|
|
'body' => json_encode([
|
|
'name' => $client->company,
|
|
'email' => $client->email,
|
|
'vat' => $client->vat,
|
|
])
|
|
]);
|
|
|
|
log_activity('Cliente sincronizado: ' . $clientId);
|
|
}
|
|
```
|
|
|
|
### 2. Validar Dados Antes de Criar Factura
|
|
|
|
```php
|
|
hooks()->add_filter('before_invoice_added', 'validate_invoice_data');
|
|
|
|
function validate_invoice_data($data)
|
|
{
|
|
// Forçar data de vencimento mínima 30 dias
|
|
if (isset($data['duedate'])) {
|
|
$due = strtotime($data['duedate']);
|
|
$min = strtotime('+30 days');
|
|
|
|
if ($due < $min) {
|
|
$data['duedate'] = date('Y-m-d', $min);
|
|
}
|
|
}
|
|
|
|
return $data; // OBRIGATÓRIO retornar
|
|
}
|
|
```
|
|
|
|
### 3. Adicionar Conteúdo ao Dashboard
|
|
|
|
```php
|
|
hooks()->add_action('before_start_render_dashboard_content', 'add_custom_widget');
|
|
|
|
function add_custom_widget()
|
|
{
|
|
$CI = &get_instance();
|
|
$CI->load->view('meu_modulo/dashboard_widget');
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Anti-Patterns (NUNCA FAZER)
|
|
|
|
| Anti-Pattern | Risco | Alternativa |
|
|
|--------------|-------|-------------|
|
|
| Não retornar valor em filter | Dados perdidos | SEMPRE retornar |
|
|
| Modificar core em vez de hooks | Quebra em updates | Usar hooks |
|
|
| Hooks sem prefixo único | Conflitos | Prefixar callbacks |
|
|
| Ignorar prioridade | Ordem errada | Definir prioridade |
|
|
| Exceptions não tratadas em hooks | Quebra sistema | Try/catch |
|
|
|
|
---
|
|
|
|
## Checklist Implementação de Hook
|
|
|
|
```
|
|
1. [ ] Hook correcto identificado (action vs filter)
|
|
2. [ ] Callback com prefixo único
|
|
3. [ ] Número de argumentos correcto
|
|
4. [ ] Filter retorna dados (OBRIGATÓRIO)
|
|
5. [ ] Try/catch para operações externas
|
|
6. [ ] Testado em desenvolvimento
|
|
7. [ ] Log de actividade para debug
|
|
```
|
|
|
|
---
|
|
|
|
**Versão:** 1.0.0 | **Autor:** Descomplicar®
|
|
**Fonte:** help.perfexcrm.com/action-hooks
|