knowledge-base/records/plugin-dev/KB-PLUGIN-033-glpi11-plugin-console-commands.md
Rodolpho Lopes f1ec0c6405 KB-PLUGIN-032/033: segunda conexão DBmysql + comandos de console de plugin (GLPI 11)
Aprendizados validados no desenvolvimento do plugin sync:
- KB-PLUGIN-032: subclasse DBmysql read-only para banco externo (gotchas de
  senha rawurldecode, query() guard, flag connected).
- KB-PLUGIN-033: comandos de console de plugin exigem src/ + namespace de nome
  plugins:<key>:.

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

90 lines
2.9 KiB
Markdown

---
id: KB-PLUGIN-033
title: "GLPI 11 — Comandos de console de plugin exigem src/ e namespace de nome plugins:<key>:"
domain: plugin-dev
tags:
- glpi11
- plugin
- console
- symfony
- command
- cli
- gotcha
status: active
severity: high
created_at: 2026-06-16
updated_at: 2026-06-16
applies_to:
- plugins GLPI 11.x que expõem comandos de bin/console
related_records:
- KB-PLUGIN-031
- KB-PLUGIN-032
---
# GLPI 11 — Comandos de console de plugin
## Como o core descobre os comandos
`Glpi\Console\CommandLoader::findPluginCommands()` varre, para cada plugin
**ativo**, os diretórios `inc/` e `src/`, instanciando classes que sejam
`Symfony\Component\Console\Command\Command`. Os prefixos de classe tentados são:
- `GlpiPlugin\<Ucfirst(key)>\` (namespaced — recomendado), ou
- `Plugin<Ucfirst(key)>` (legado não-namespaced), ou
- vazio (PSR-4 sem namespace).
O `src/` do plugin é registrado como PSR-4 `GlpiPlugin\<Ucfirst(key)>\ → src/`
(`Plugin.php`, ~linha 406). Então `src/Console/FooCommand.php` deve declarar
`namespace GlpiPlugin\<Ucfirst(key)>\Console;`.
## Regra rígida do nome (a armadilha)
O nome do comando **DEVE** casar com o padrão `plugins:<key>:<algo>` (regex no
core: `^plugins:<key>(:[^:]+)+$`). Se não casar, o core emite
`E_USER_WARNING` ("must be moved in the `plugins:<key>` namespace") e **não
registra** o comando — ele simplesmente não aparece em `bin/console`.
```php
namespace GlpiPlugin\Sync\Console;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class TestConnectionCommand extends Command
{
protected function configure(): void
{
$this->setName('plugins:sync:test-connection'); // <- obrigatório
$this->setDescription('...');
$this->addOption('host', null, InputOption::VALUE_REQUIRED, '...');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
// ... lógica ...
return Command::SUCCESS; // SUCCESS / FAILURE / INVALID
}
}
```
## Notas
- Estender o `Command` do Symfony direto é suficiente (não exige
`Glpi\Console\AbstractCommand`). O Kernel já está bootado quando o comando roda,
então classes do core e dos plugins ativos estão disponíveis.
- O plugin precisa estar **ativado** para os comandos aparecerem.
- Arquivos de teste sob `src/`/`inc/` que casem o padrão também são varridos —
manter scripts de teste fora desses dirs (ver `.gitignore` do plugin).
## Validação
Comprovado no plugin `sync` (2026-06-16): `plugins:sync:test-connection`
registrou e executou; ver [KB-PLUGIN-032] para o conteúdo do comando (segunda
conexão DBmysql).
## Classificação
- Tipo: gotcha + padrão de implementação.
- Reutilização: qualquer plugin com comando de CLI.