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>
90 lines
2.9 KiB
Markdown
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.
|