--- id: KB-PLUGIN-033 title: "GLPI 11 — Comandos de console de plugin exigem src/ e namespace de nome plugins::" 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\\` (namespaced — recomendado), ou - `Plugin` (legado não-namespaced), ou - vazio (PSR-4 sem namespace). O `src/` do plugin é registrado como PSR-4 `GlpiPlugin\\ → src/` (`Plugin.php`, ~linha 406). Então `src/Console/FooCommand.php` deve declarar `namespace GlpiPlugin\\Console;`. ## Regra rígida do nome (a armadilha) O nome do comando **DEVE** casar com o padrão `plugins::` (regex no core: `^plugins:(:[^:]+)+$`). Se não casar, o core emite `E_USER_WARNING` ("must be moved in the `plugins:` 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.