knowledge-base/records/plugin-dev/KB-PLUGIN-023-mcprotocol-inputvalidation-extracted.md
Rodolpho Lopes 200cd6c2ce kb: KB-PLUGIN-031 runbook de workflow dev/deploy de plugins + commit dos registros 021-030 pendentes
- Novo runbook KB-PLUGIN-031: nascimento do plugin ate validacao E2E no
  GLPI dev (scaffold, Forgejo local, deploy CT100, console, bootstrap
  Kernel para testes CLI). Validado de ponta a ponta com o assetinherit.
- Registros KB-PLUGIN-021..030 existiam apenas no disco (drift) e foram
  incluidos no versionamento; index.json sincronizado via kb-fix.
- Ignora lixo AppleDouble/.DS_Store do macOS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 17:59:47 +00:00

85 lines
4.1 KiB
Markdown

---
id: KB-PLUGIN-023
title: mcprotocol — InputValidation extraída como classe utilitária compartilhada
domain: plugin-dev
tags:
- mcp
- tools
- validation
- refactor
- patterns
status: active
severity: medium
created_at: 2026-05-26
updated_at: 2026-05-26
applies_to:
- glpi-11
- mcprotocol-plugin
related_records:
- KB-PLUGIN-022
- KB-PLUGIN-019
---
# mcprotocol — InputValidation extraída como classe utilitária compartilhada
## Contexto
KB-PLUGIN-022 documentou os padrões `resolveReference`, `normalizeDate`, validação agregada e response com `applied` como métodos privados em `ProjectTools`. Esse KB previu que **na introdução do segundo handler** os helpers seriam extraídos para uma classe utilitária. Esse momento chegou ao implementar `glpi_projecttask_create`.
## Decisão
Extraído `src/InputValidation.php` (namespace `GlpiPlugin\Mcprotocol`) com métodos **estáticos públicos** reutilizáveis em qualquer handler de tool:
| Método | Responsabilidade |
|---|---|
| `resolveReference($table, $value, $field, &$errors, $nameCol='name')` | Aceita int ou string e devolve ID validado. Suporta coluna de busca customizada (ex: `name` em `glpi_users`). |
| `normalizeDate($value, $field, &$errors)` | Aceita `YYYY-MM-DD` ou `YYYY-MM-DD HH:MM:SS`, normaliza pro formato GLPI. |
| `validateDateRange($start, $end, $startField, $endField, &$errors)` | Garante `end >= start` quando ambos informados. |
| `validateIntRange($value, $field, $min, $max, &$errors)` | Valida inteiro em intervalo (ex: `percent_done` 0-100). |
## Mudanças realizadas
- **Novo arquivo:** `src/InputValidation.php`
- **Refatorado:** `src/ProjectTools.php` — removeu helpers privados, agora chama `InputValidation::*`. Também ganhou método `buildInputFromArgs($args, $isUpdate)` que centraliza a montagem do input para create/update (DRY).
- **Estendido:** `glpi_project_update` agora aceita os mesmos campos do create (datas, estado, tipo) — antes só aceitava name/content/percent_done.
- **Novo arquivo:** `src/ProjectTaskTools.php` — usa `InputValidation` desde o início, com 2 tools: `glpi_projecttask_create` e `glpi_projecttask_get`.
- **Atualizado:** `src/ToolRegistry.php` — registra `ProjectTaskTools::getTools()` no merge.
## Convenções de uso
1. **Acumular erros** — qualquer handler que valida múltiplos campos deve usar a assinatura `&$errors` e lançar UMA exception ao final. Nunca múltiplas.
2. **Coluna de busca por nome**`resolveReference` aceita `$nameCol`. Para tabelas onde o campo descritivo não se chama `name`, passar explicitamente:
```php
InputValidation::resolveReference('glpi_users', $args['users_id'], 'users_id', $errors, 'name');
```
3. **Validação prévia ao ORM** — todos os helpers rodam ANTES de `$obj->add()` ou `$obj->update()`. Se houver erro, exception é lançada e o ORM nunca é chamado. Evita erros de SQL/ORM crípticos.
4. **Response com `applied`** — handlers devem sempre retornar o input efetivamente aplicado:
```php
return ['status'=>'success', 'id'=>$newId, 'message'=>'...', 'applied'=>$input];
```
## Tabelas comuns para `resolveReference`
| Tabela | Coluna de nome | Uso típico |
|---|---|---|
| `glpi_projectstates` | `name` | Estado de projeto/tarefa |
| `glpi_projecttypes` | `name` | Tipo de projeto |
| `glpi_projecttasktypes` | `name` | Tipo de tarefa |
| `glpi_users` | `name` (login) | Responsável |
| `glpi_groups` | `name` | Grupo |
| `glpi_entities` | `name` | Entidade |
| `glpi_itilcategories` | `name` | Categoria de chamado |
| `glpi_locations` | `name` | Localização |
## Próximos handlers candidatos a usar `InputValidation`
- `glpi_ticket_create``users_id_recipient`, `users_id_lastupdater`, `itilcategories_id`, datas
- `glpi_ticket_update` — idem + estados (1=New, 2=Processing, etc. já são enums numéricos GLPI)
- Futuras tools de Computer/Asset (`glpi_computer_create`, etc.)
## Validação end-to-end
Padrão validado em produção criando o projeto VALGROUP (28 tarefas em hierarquia) através das tools. Erros de validação retornados claramente, datas normalizadas, estados resolvidos por nome ("New" → 1, "Processing" → 2). Aplicado conforme esperado.