--- id: KB-PLUGIN-009 title: Validacao mandatory ignora respostas que sao arrays nao-vazios com chaves em branco domain: plugin-dev tags: - glpi - glpi11 - form-builder - validation - answers-handler status: active severity: high created_at: 2026-05-02 updated_at: 2026-05-02 applies_to: - GLPI 11.0.x --- # 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: ```php 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: ```php $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. ```php 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).