2.4 KiB
| id | title | domain | tags | status | severity | created_at | updated_at | applies_to | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| KB-PLUGIN-009 | Validacao mandatory ignora respostas que sao arrays nao-vazios com chaves em branco | plugin-dev |
|
active | high | 2026-05-02 | 2026-05-02 |
|
Validacao mandatory ignora respostas que sao arrays nao-vazios com chaves em branco
Sintoma
Um campo obrigatório (mandatory) de um novo QuestionType não dispara nenhum erro de validação se o usuário o enviar vazio. Em vez disso, a página tenta enviar e falha, devolvendo um erro genérico do sistema (geralmente gerado na hora de gravar os destinos).
Causa
O mecanismo do AnswersHandler do GLPI verifica campos vazios da seguinte forma:
if ($answer === null || (is_string($answer) && strip_tags($answer) === '') || (is_array($answer) && count($answer) === 0))
Em widgets complexos que retornam uma estrutura via vários inputs (como [items_id] e [itemtype]), se o usuário não selecionar nada, a resposta "crua" (raw) pode chegar no backend como um array:
$answer = [
'itemtype' => 'ITILCategory',
'items_id' => ''
];
Este array possui 2 chaves, logo count($answer) === 0 é false. O GLPI entende que a pergunta "foi respondida" e pula a checagem de obrigatoriedade.
Solucao
A classe QuestionType deve implementar (ou sobrescrever) o método transformConditionValueForComparisons originado da ConditionValueTransformerInterface.
O objetivo é examinar a resposta raw precocemente e convertê-la ativamente em uma string vazia '' caso os dados essenciais estejam ausentes.
use Override;
#[Override]
public function transformConditionValueForComparisons(mixed $value, ?\Glpi\DBAL\JsonFieldInterface $question_config): string
{
if (is_array($value)) {
$items_id = $value['items_id'] ?? '';
// Trata chaves em branco ou nulas como resposta vazia global
if ($items_id === '' || $items_id === null || (int)$items_id <= 0) {
return ''; // string vazia dispara o check nativo do AnswersHandler!
}
}
// Passa adiante se tudo estiver ok
return parent::transformConditionValueForComparisons($value, $question_config);
}
Ao retornar '', o AnswersHandler passará a reconhecer que o usuário pulou o campo, ativando corretamente a mensagem de erro (ou a sua CustomMandatoryMessageInterface caso definida).