From af40ec9ddd4e1fe83416c847ae7e9a69a3b48ddd Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 31 May 2023 10:29:10 +0200 Subject: [PATCH 01/58] Revert "fix(textfield): Unescaped HTML when displaying a form answer" This reverts commit d4763859e44e3e18cd9f29e3d8e550e841d1936e. --- inc/field/textfield.class.php | 8 +--- inc/formanswer.class.php | 1 + .../Formcreator/Field/TextField.php | 16 +------ .../Formcreator/Field/TextareaField.php | 12 ----- tests/src/CommonTargetTestCase.php | 44 +------------------ 5 files changed, 5 insertions(+), 76 deletions(-) diff --git a/inc/field/textfield.class.php b/inc/field/textfield.class.php index 07328d407..0b31a567f 100644 --- a/inc/field/textfield.class.php +++ b/inc/field/textfield.class.php @@ -63,7 +63,7 @@ public function showForm(array $options): void { public function getRenderedHtml($domain, $canEdit = true): string { if (!$canEdit) { - return Sanitizer::sanitize($this->value, false); + return $this->value; } $html = ''; @@ -108,11 +108,7 @@ public function getValueForDesign(): string { } public function getValueForTargetText($domain, $richText): ?string { - if ($richText) { - return Sanitizer::sanitize($this->value, false); - } - - return $this->value; + return Sanitizer::unsanitize($this->value); } public function moveUploads() { diff --git a/inc/formanswer.class.php b/inc/formanswer.class.php index 3bda2a636..337508bd9 100644 --- a/inc/formanswer.class.php +++ b/inc/formanswer.class.php @@ -1353,6 +1353,7 @@ public function parseTags(string $content, PluginFormcreatorTargetInterface $tar } } } + // $content = str_replace('##answer_' . $questionId . '##', Sanitizer::sanitize($value ?? ''), $content); $content = str_replace('##answer_' . $questionId . '##', $value ?? '', $content); if ($this->questionFields[$questionId] instanceof DropdownField) { diff --git a/tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php b/tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php index 4a1c8c40d..8f15350f3 100644 --- a/tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php +++ b/tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php @@ -397,12 +397,6 @@ public function providerGetValueForTargetText() { 'expected' => true, 'expectedValue' => 'foo\\bar', ], - [ - 'question' => $this->getQuestion(), - 'value' => '">', - 'expected' => true, - 'expectedValue' => '">', - ], ]; } @@ -426,13 +420,5 @@ public function testGetValueForTargetText($question, $value, $expected, $expecte } } - public function testGetRenderedHtml() { - // XSS check - $instance = $this->newTestedInstance($this->getQuestion()); - $instance->deserializeValue('">'); - $output = $instance->getRenderedHtml('no_domain', false); - $this->string($output)->isEqualTo('"><img src=x onerror="alert(1337)" x=x>'); - $output = $instance->getRenderedHtml('no_domain', true); - $this->string($output)->contains('">'); - } + } diff --git a/tests/3-unit/GlpiPlugin/Formcreator/Field/TextareaField.php b/tests/3-unit/GlpiPlugin/Formcreator/Field/TextareaField.php index e4b57b6f3..becf1d503 100644 --- a/tests/3-unit/GlpiPlugin/Formcreator/Field/TextareaField.php +++ b/tests/3-unit/GlpiPlugin/Formcreator/Field/TextareaField.php @@ -313,16 +313,4 @@ public function testGetValueForApi($input, $expected) { $output = $instance->getValueForApi(); $this->string($output)->isEqualTo($expected); } - - public function testGetRenderedHtml() { - // XSS check - $formAnswer = new PluginFormcreatorFormAnswer(); - $instance = $this->newTestedInstance($this->getQuestion()); - $instance->setFormAnswer($formAnswer); - $instance->deserializeValue('">'); - $output = $instance->getRenderedHtml('no_domain', false); - $this->string($output)->isEqualTo('">image'); - $output = $instance->getRenderedHtml('no_domain', true); - $this->string($output)->contains('">'); - } } diff --git a/tests/src/CommonTargetTestCase.php b/tests/src/CommonTargetTestCase.php index 5fc97fc28..92ad348ab 100644 --- a/tests/src/CommonTargetTestCase.php +++ b/tests/src/CommonTargetTestCase.php @@ -2,20 +2,9 @@ namespace GlpiPlugin\Formcreator\Tests; use PluginFormcreatorForm; -use PluginFormcreatorFormAnswer; -use PluginFormcreatorSection; abstract class CommonTargetTestCase extends CommonTestCase { - public function beforeTestMethod($method) { - parent::beforeTestMethod($method); - switch ($method) { - case 'testXSS': - $this->login('glpi', 'glpi'); - break; - } - } - /** * Test handling of uuid when adding an item */ @@ -67,35 +56,4 @@ public function testPrepareInputForUpdate_uuid() { $this->array($output)->HasKey('uuid'); $this->string($output['uuid'])->isEqualTo('foo'); } - - public function testXSS() { - $question = $this->getQuestion([ - 'fieldtype' => 'text', - ]); - $section = new PluginFormcreatorSection(); - $section->update([ - 'id' => $question->fields['plugin_formcreator_sections_id'], - 'name' => 'section', - ]); - $form = PluginFormcreatorForm::getByItem($question); - $testedClassName = $this->getTestedClassName(); - $target = new $testedClassName(); - $target->add([ - 'name' => $this->getUniqueString(), - 'plugin_formcreator_forms_id' => $form->getID(), - 'target_name' => '##answer_' . $question->getID() . '##', - 'content' => '##FULLFORM##', - ]); - $formAnswer = new PluginFormcreatorFormAnswer(); - $formAnswer->add([ - 'plugin_formcreator_forms_id' => $form->getID(), - 'formcreator_field_' . $question->getID() => '"><img src=x onerror="alert(1337)" x=x>"', - ]); - $generated = $formAnswer->targetList[0] ?? null; - $this->object($generated); - $this->string($generated->fields['name']) - ->isEqualTo('"><img src=x onerror="alert(1337)" x=x>"'); - $this->string($generated->fields['content']) - ->isEqualTo('<h1>Form data</h1><h2>section</h2><div><b>1) question : </b>"&#62;&#60;img src=x onerror="alert(1337)" x=x&#62;"</div>'); - } -} +} \ No newline at end of file From 6ce71f957d6908065edf79eeaa556fa0cc615aac Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Fri, 7 Apr 2023 16:05:40 +0200 Subject: [PATCH 02/58] fix(textfield): Unescaped HTML when displaying a form answer --- inc/field/textfield.class.php | 8 +++- inc/formanswer.class.php | 1 - .../Formcreator/Field/TextField.php | 16 ++++++- .../Formcreator/Field/TextareaField.php | 12 +++++ tests/src/CommonTargetTestCase.php | 44 ++++++++++++++++++- 5 files changed, 76 insertions(+), 5 deletions(-) diff --git a/inc/field/textfield.class.php b/inc/field/textfield.class.php index 0b31a567f..07328d407 100644 --- a/inc/field/textfield.class.php +++ b/inc/field/textfield.class.php @@ -63,7 +63,7 @@ public function showForm(array $options): void { public function getRenderedHtml($domain, $canEdit = true): string { if (!$canEdit) { - return $this->value; + return Sanitizer::sanitize($this->value, false); } $html = ''; @@ -108,7 +108,11 @@ public function getValueForDesign(): string { } public function getValueForTargetText($domain, $richText): ?string { - return Sanitizer::unsanitize($this->value); + if ($richText) { + return Sanitizer::sanitize($this->value, false); + } + + return $this->value; } public function moveUploads() { diff --git a/inc/formanswer.class.php b/inc/formanswer.class.php index 337508bd9..3bda2a636 100644 --- a/inc/formanswer.class.php +++ b/inc/formanswer.class.php @@ -1353,7 +1353,6 @@ public function parseTags(string $content, PluginFormcreatorTargetInterface $tar } } } - // $content = str_replace('##answer_' . $questionId . '##', Sanitizer::sanitize($value ?? ''), $content); $content = str_replace('##answer_' . $questionId . '##', $value ?? '', $content); if ($this->questionFields[$questionId] instanceof DropdownField) { diff --git a/tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php b/tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php index 8f15350f3..4a1c8c40d 100644 --- a/tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php +++ b/tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php @@ -397,6 +397,12 @@ public function providerGetValueForTargetText() { 'expected' => true, 'expectedValue' => 'foo\\bar', ], + [ + 'question' => $this->getQuestion(), + 'value' => '">', + 'expected' => true, + 'expectedValue' => '">', + ], ]; } @@ -420,5 +426,13 @@ public function testGetValueForTargetText($question, $value, $expected, $expecte } } - + public function testGetRenderedHtml() { + // XSS check + $instance = $this->newTestedInstance($this->getQuestion()); + $instance->deserializeValue('">'); + $output = $instance->getRenderedHtml('no_domain', false); + $this->string($output)->isEqualTo('"><img src=x onerror="alert(1337)" x=x>'); + $output = $instance->getRenderedHtml('no_domain', true); + $this->string($output)->contains('">'); + } } diff --git a/tests/3-unit/GlpiPlugin/Formcreator/Field/TextareaField.php b/tests/3-unit/GlpiPlugin/Formcreator/Field/TextareaField.php index becf1d503..e4b57b6f3 100644 --- a/tests/3-unit/GlpiPlugin/Formcreator/Field/TextareaField.php +++ b/tests/3-unit/GlpiPlugin/Formcreator/Field/TextareaField.php @@ -313,4 +313,16 @@ public function testGetValueForApi($input, $expected) { $output = $instance->getValueForApi(); $this->string($output)->isEqualTo($expected); } + + public function testGetRenderedHtml() { + // XSS check + $formAnswer = new PluginFormcreatorFormAnswer(); + $instance = $this->newTestedInstance($this->getQuestion()); + $instance->setFormAnswer($formAnswer); + $instance->deserializeValue('">'); + $output = $instance->getRenderedHtml('no_domain', false); + $this->string($output)->isEqualTo('">image'); + $output = $instance->getRenderedHtml('no_domain', true); + $this->string($output)->contains('">'); + } } diff --git a/tests/src/CommonTargetTestCase.php b/tests/src/CommonTargetTestCase.php index 92ad348ab..5fc97fc28 100644 --- a/tests/src/CommonTargetTestCase.php +++ b/tests/src/CommonTargetTestCase.php @@ -2,9 +2,20 @@ namespace GlpiPlugin\Formcreator\Tests; use PluginFormcreatorForm; +use PluginFormcreatorFormAnswer; +use PluginFormcreatorSection; abstract class CommonTargetTestCase extends CommonTestCase { + public function beforeTestMethod($method) { + parent::beforeTestMethod($method); + switch ($method) { + case 'testXSS': + $this->login('glpi', 'glpi'); + break; + } + } + /** * Test handling of uuid when adding an item */ @@ -56,4 +67,35 @@ public function testPrepareInputForUpdate_uuid() { $this->array($output)->HasKey('uuid'); $this->string($output['uuid'])->isEqualTo('foo'); } -} \ No newline at end of file + + public function testXSS() { + $question = $this->getQuestion([ + 'fieldtype' => 'text', + ]); + $section = new PluginFormcreatorSection(); + $section->update([ + 'id' => $question->fields['plugin_formcreator_sections_id'], + 'name' => 'section', + ]); + $form = PluginFormcreatorForm::getByItem($question); + $testedClassName = $this->getTestedClassName(); + $target = new $testedClassName(); + $target->add([ + 'name' => $this->getUniqueString(), + 'plugin_formcreator_forms_id' => $form->getID(), + 'target_name' => '##answer_' . $question->getID() . '##', + 'content' => '##FULLFORM##', + ]); + $formAnswer = new PluginFormcreatorFormAnswer(); + $formAnswer->add([ + 'plugin_formcreator_forms_id' => $form->getID(), + 'formcreator_field_' . $question->getID() => '"><img src=x onerror="alert(1337)" x=x>"', + ]); + $generated = $formAnswer->targetList[0] ?? null; + $this->object($generated); + $this->string($generated->fields['name']) + ->isEqualTo('"><img src=x onerror="alert(1337)" x=x>"'); + $this->string($generated->fields['content']) + ->isEqualTo('<h1>Form data</h1><h2>section</h2><div><b>1) question : </b>"&#62;&#60;img src=x onerror="alert(1337)" x=x&#62;"</div>'); + } +} From 6d7549c0eefc41f2b512111a863826fccb28f31f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Tue, 18 Apr 2023 09:17:59 +0200 Subject: [PATCH 03/58] Apply suggestions from code review --- inc/field/textfield.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/field/textfield.class.php b/inc/field/textfield.class.php index 07328d407..e2fc5a93b 100644 --- a/inc/field/textfield.class.php +++ b/inc/field/textfield.class.php @@ -63,7 +63,7 @@ public function showForm(array $options): void { public function getRenderedHtml($domain, $canEdit = true): string { if (!$canEdit) { - return Sanitizer::sanitize($this->value, false); + return Sanitizer::encodeHtmlSpecialChars($this->value); } $html = ''; @@ -109,7 +109,7 @@ public function getValueForDesign(): string { public function getValueForTargetText($domain, $richText): ?string { if ($richText) { - return Sanitizer::sanitize($this->value, false); + return Sanitizer::encodeHtmlSpecialChars($this->value); } return $this->value; From 613e0fad644350b8120e48d96f163f78e0d56b48 Mon Sep 17 00:00:00 2001 From: Stanislas Date: Wed, 31 May 2023 11:22:53 +0200 Subject: [PATCH 04/58] fix(glpiselectfield): fix namespace (#3287) --- inc/field/glpiselectfield.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/field/glpiselectfield.class.php b/inc/field/glpiselectfield.class.php index ced1b3e36..f10168244 100644 --- a/inc/field/glpiselectfield.class.php +++ b/inc/field/glpiselectfield.class.php @@ -39,6 +39,7 @@ use Entity; use CommonTreeDropdown; use CommonDBTM; +use Ticket; use User; use GlpiPlugin\Formcreator\Exception\ComparisonException; From db9986f12bd5700ff06cf5fbdc9004da25444470 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 31 May 2023 12:10:39 +0200 Subject: [PATCH 05/58] fix: bad lcoale in en_US --- locales/en_US.po | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/locales/en_US.po b/locales/en_US.po index bae7274aa..2009308ee 100644 --- a/locales/en_US.po +++ b/locales/en_US.po @@ -5,7 +5,6 @@ # # Translators: # Thierry Bugier , 2022 -# 조성현 (jaymz9634) , 2022 # #, fuzzy msgid "" @@ -14,7 +13,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-05-30 09:32+0200\n" "PO-Revision-Date: 2021-08-30 07:22+0000\n" -"Last-Translator: 조성현 (jaymz9634) , 2022\n" +"Last-Translator: Thierry Bugier , 2022\n" "Language-Team: English (United States) (https://app.transifex.com/teclib/teams/28042/en_US/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -341,7 +340,7 @@ msgstr "" #: inc/field/urgencyfield.class.php:121 msgctxt "urgency" msgid "Medium" -msgstr "매체" +msgstr "" #: inc/field/urgencyfield.class.php:122 msgctxt "urgency" @@ -377,7 +376,7 @@ msgstr[1] "" #: inc/field/timefield.class.php:129 msgid "Time" -msgstr "시간" +msgstr "" #: inc/field/emailfield.class.php:88 #, php-format @@ -810,7 +809,7 @@ msgstr "Form #" #: inc/notificationtargetformanswer.class.php:97 msgctxt "tag" msgid "Validator" -msgstr "검증자" +msgstr "" #: inc/notificationtargetformanswer.class.php:100 msgid "Refused comment" @@ -1492,7 +1491,7 @@ msgstr "Form Transfered: %s" #: inc/form.class.php:1557 msgid "Back" -msgstr "뒤로" +msgstr "" #: inc/form.class.php:1568 #, php-format @@ -2475,7 +2474,7 @@ msgstr "" #: entrée standard:64 msgid "Condition to show the section" -msgstr "섹션 표시를 위한 조건" +msgstr "" #: entrée standard:40 msgid "Condition to generate the target" From f4ebf9e5ef9361b10709c2b3468e904490071c61 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 31 May 2023 13:45:32 +0200 Subject: [PATCH 06/58] fix(form,category): obey show count on tabs parameter --- inc/category.class.php | 2 +- inc/form.class.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/category.class.php b/inc/category.class.php index 19b8d8c3f..1fbdff3dc 100644 --- a/inc/category.class.php +++ b/inc/category.class.php @@ -53,7 +53,7 @@ public static function getTypeName($nb = 1) { public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { $env = new self; $found_env = $env->find([static::getForeignKeyField() => $item->getID()]); - $nb = count($found_env); + $nb = $_SESSION['glpishow_count_on_tabs'] ? count($found_env) : 0; return self::createTabEntry(self::getTypeName($nb), $nb); } diff --git a/inc/form.class.php b/inc/form.class.php index 92c3e984f..339630100 100644 --- a/inc/form.class.php +++ b/inc/form.class.php @@ -570,7 +570,7 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { return [ 1 => self::createTabEntry( _n('Target', 'Targets', $nb, 'formcreator'), - $item->countTargets() + $nb ), 2 => __('Preview'), 3 => __('Form answer properties', 'formcreator'), From 3419affcf0e30e3b7c795e7ae6a23447d369b87f Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 30 May 2023 21:18:07 +0200 Subject: [PATCH 07/58] fix(issue): prevent fatal error in tooltip when a tooltip for an issue of a form answer is generated, an inconcistency in conditions may cause a crash --- inc/issue.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/inc/issue.class.php b/inc/issue.class.php index 7e1e89f83..ee5187700 100644 --- a/inc/issue.class.php +++ b/inc/issue.class.php @@ -1063,7 +1063,11 @@ public static function giveItem($itemtype, $option_id, $data, $num) { trigger_error(sprintf("Formanswer ID %s not found", $id), E_USER_WARNING); break; } - $content = $formAnswer->parseTags($formAnswer->getFullForm()); + try { + $content = $formAnswer->parseTags($formAnswer->getFullForm()); + } catch (Exception $e) { + $content = ''; // Exception when computing the tooltip + } break; } $link = self::getFormURLWithID($data['id']); From 5d6f1d3852d1d5d9f08d9623ec72f03012791bda Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 31 May 2023 16:19:09 +0200 Subject: [PATCH 08/58] refactor(wizard): useless condition --- front/wizard.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/front/wizard.php b/front/wizard.php index c212e02a8..06714fc9a 100644 --- a/front/wizard.php +++ b/front/wizard.php @@ -50,9 +50,7 @@ Html::header(__('Service catalog', 'formcreator')); } -if (PluginFormcreatorEntityconfig::getUsedConfig('is_dashboard_visible', Session::getActiveEntity()) == PluginFormcreatorEntityconfig::CONFIG_DASHBOARD_VISIBLE) { - PluginFormcreatorCommon::showMiniDashboard(); -} +PluginFormcreatorCommon::showMiniDashboard(); $form = PluginFormcreatorCommon::getForm(); $form->showServiceCatalog(); From 9dfc3b8dd409c48d162ef5f6dc7af687afa54e09 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Mon, 5 Jun 2023 09:30:55 +0200 Subject: [PATCH 09/58] fix(form_language): obey show counter in tab setting --- inc/form_language.class.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/inc/form_language.class.php b/inc/form_language.class.php index fe4fa5840..29c692f21 100644 --- a/inc/form_language.class.php +++ b/inc/form_language.class.php @@ -64,9 +64,12 @@ public function defineTabs($options = []) { public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { if ($item instanceof PluginFormcreatorForm) { - $nb = (new DbUtils())->countElementsInTable(self::getTable(), [ - 'plugin_formcreator_forms_id' => $item->getID(), - ]); + $nb = 0; + if ($_SESSION['glpishow_count_on_tabs']) { + $nb = (new DbUtils())->countElementsInTable(self::getTable(), [ + 'plugin_formcreator_forms_id' => $item->getID(), + ]); + } return self::createTabEntry( self::getTypeName(Session::getPluralNumber()), $nb From 3d2dfb4ee123d374697c2687c04303ef87203f19 Mon Sep 17 00:00:00 2001 From: btry Date: Mon, 5 Jun 2023 09:45:27 +0200 Subject: [PATCH 10/58] bugfix(selectfield): bad encoding when business rules test the value --- inc/field/radiosfield.class.php | 3 +- inc/field/selectfield.class.php | 4 +- inc/targetticket.class.php | 2 +- .../PluginFormcreatorTargetTicket.php | 1 + .../Formcreator/Field/ActorField.php | 43 ++++++++++- .../Formcreator/Field/CheckboxesField.php | 76 +++++++++---------- .../Formcreator/Field/RadiosField.php | 34 ++++++++- .../Formcreator/Field/SelectField.php | 34 ++++++++- .../Formcreator/Field/TextareaField.php | 12 +++ tests/3-unit/PluginFormcreatorCategory.php | 2 +- tests/src/CommonAbstractFieldTestCase.php | 71 +++++++++++++++++ 11 files changed, 230 insertions(+), 52 deletions(-) create mode 100644 tests/src/CommonAbstractFieldTestCase.php diff --git a/inc/field/radiosfield.class.php b/inc/field/radiosfield.class.php index 7d5f331dc..4026d1179 100644 --- a/inc/field/radiosfield.class.php +++ b/inc/field/radiosfield.class.php @@ -38,6 +38,7 @@ use Toolbox; use PluginFormcreatorFormAnswer; use Glpi\Application\View\TemplateRenderer; +use Glpi\Toolbox\Sanitizer; class RadiosField extends PluginFormcreatorAbstractField { @@ -174,7 +175,7 @@ public function getValueForDesign(): string { } public function getValueForTargetText($domain, $richText): ?string { - return __($this->value, $domain); + return Sanitizer::unsanitize(__($this->value, $domain)); } public function moveUploads() { diff --git a/inc/field/selectfield.class.php b/inc/field/selectfield.class.php index 27c257cf9..9296b24cc 100644 --- a/inc/field/selectfield.class.php +++ b/inc/field/selectfield.class.php @@ -37,6 +37,7 @@ use Session; use Toolbox; use Glpi\Application\View\TemplateRenderer; +use Glpi\Toolbox\Sanitizer; class SelectField extends RadiosField { @@ -71,7 +72,8 @@ public function getRenderedHtml($domain, $canEdit = true): string { if (!empty($this->question->fields['values'])) { foreach ($values as $value) { if ((trim($value) != '')) { - $translatedValues[$value] = __($value, $domain); + $unsanitized = Sanitizer::unsanitize(__($value, $domain)); + $translatedValues[$unsanitized] = $unsanitized; } } diff --git a/inc/targetticket.class.php b/inc/targetticket.class.php index ab66212c0..a822d4c3f 100644 --- a/inc/targetticket.class.php +++ b/inc/targetticket.class.php @@ -813,7 +813,7 @@ public function save(PluginFormcreatorFormAnswer $formanswer): ?CommonDBTM { $richText = true; $domain = PluginFormcreatorForm::getTranslationDomain($form->getID()); $data['name'] = $this->prepareTemplate( - __($this->fields['target_name'], $domain), + Sanitizer::unsanitize(__($this->fields['target_name'], $domain)), $formanswer, false ); diff --git a/tests/2-integration/PluginFormcreatorTargetTicket.php b/tests/2-integration/PluginFormcreatorTargetTicket.php index c3bb7c919..fbfe297dd 100644 --- a/tests/2-integration/PluginFormcreatorTargetTicket.php +++ b/tests/2-integration/PluginFormcreatorTargetTicket.php @@ -30,6 +30,7 @@ */ namespace tests\units; use GlpiPlugin\Formcreator\Tests\CommonTestCase; +use Entity; /** * @engine inline diff --git a/tests/3-unit/GlpiPlugin/Formcreator/Field/ActorField.php b/tests/3-unit/GlpiPlugin/Formcreator/Field/ActorField.php index 7d4ceb6aa..534cb87f7 100644 --- a/tests/3-unit/GlpiPlugin/Formcreator/Field/ActorField.php +++ b/tests/3-unit/GlpiPlugin/Formcreator/Field/ActorField.php @@ -29,11 +29,11 @@ * --------------------------------------------------------------------- */ namespace GlpiPlugin\Formcreator\Field\tests\units; -use GlpiPlugin\Formcreator\Tests\CommonTestCase; +use GlpiPlugin\Formcreator\Tests\CommonAbstractFieldTestCase; use GlpiPlugin\Formcreator\Exception\ComparisonException; use PluginFormcreatorFormAnswer; use User; -class ActorField extends CommonTestCase { +class ActorField extends CommonAbstractFieldTestCase { public function testGetName() { $itemtype = $this->getTestedClassName(); $output = $itemtype::getName(); @@ -475,4 +475,43 @@ public function testGetValueForApi($input, $expected) { $output = $instance->getValueForApi(); $this->array($output)->isEqualTo($expected); } + + public function providerGetValueForTargetText() { + $fieldtype = 'actor'; + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + ]), + 'value' => '', + 'expectedValue' => '', + 'expectedRichValue' => '
' + ]; + + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + ]), + 'value' => json_encode(['foo@bar.com']), + 'expectedValue' => 'foo@bar.com', + 'expectedRichValue' => '
foo@bar.com' + ]; + + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + ]), + 'value' => json_encode([User::getIdByName('glpi')]), + 'expectedValue' => 'glpi', + 'expectedRichValue' => '
glpi' + ]; + + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + ]), + 'value' => json_encode(['foo@bar.com', User::getIdByName('glpi')]), + 'expectedValue' => 'foo@bar.com, glpi', + 'expectedRichValue' => '
foo@bar.com
glpi', + ]; + } } diff --git a/tests/3-unit/GlpiPlugin/Formcreator/Field/CheckboxesField.php b/tests/3-unit/GlpiPlugin/Formcreator/Field/CheckboxesField.php index 2cdc421e5..247ea52eb 100644 --- a/tests/3-unit/GlpiPlugin/Formcreator/Field/CheckboxesField.php +++ b/tests/3-unit/GlpiPlugin/Formcreator/Field/CheckboxesField.php @@ -29,10 +29,10 @@ * --------------------------------------------------------------------- */ namespace GlpiPlugin\Formcreator\Field\tests\units; -use GlpiPlugin\Formcreator\Tests\CommonTestCase; +use GlpiPlugin\Formcreator\Tests\CommonAbstractFieldTestCase; use PluginFormcreatorFormAnswer; -class CheckboxesField extends CommonTestCase { +class CheckboxesField extends CommonAbstractFieldTestCase { public function testGetName() { $itemtype = $this->getTestedClassName(); $output = $itemtype::getName(); @@ -295,61 +295,53 @@ public function testisPublicFormCompatible() { } public function providerGetValueForTargetText() { - return [ - [ - 'question' => $this->getQuestion([ - 'values' => "[]" - ]), - 'value' => json_encode(['a']), - 'expected' => '' - ], - [ - 'question' => $this->getQuestion([ - 'values' => json_encode(['a', 'b', 'c']) - ]), - 'value' => json_encode(['a']), - 'expected' => 'a' - ], - [ - 'question' => $this->getQuestion([ - 'values' => json_encode(['a', 'b', 'c']) - ]), - 'value' => json_encode(['a', 'c']), - 'expected' => 'a
c' - ], + $fieldtype = 'checkboxes'; + + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + 'values' => "[]" + ]), + 'value' => 'a', + 'expectedValue' => '', ]; - } - /** - * @dataprovider providerGetValueForTargetText - */ - public function testGetValueForTargetText($question, $value, $expected) { - $instance = $this->newTestedInstance($question); - $instance->deserializeValue($value); + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + 'values' => 'a\r\nb\r\nc' + ]), + 'value' => json_encode(['a']), + 'expectedValue' => 'a', + ]; - $output = $instance->getValueForTargetText('', true); - $this->string($output)->isEqualTo($expected); + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + 'values' => 'a\r\nb\r\nc' + ]), + 'value' => json_encode(['a', 'c']), + 'expectedValue' => 'a, c', + 'expectedRichValue' => 'a
c' + ]; } public function providerGetValueForDesign() { + $fieldtype = 'checkboxes'; + return [ [ 'question' => $this->getQuestion([ - 'values' => "" - ]), - 'value' => "", - 'expected' => '' - ], - [ - 'question' => $this->getQuestion([ - 'values' => json_encode(['a', 'b', 'c']) + 'fieldtype' => $fieldtype, + 'values' => 'a\r\nb\r\nc' ]), 'value' => json_encode(['a']), 'expected' => 'a' ], [ 'question' => $this->getQuestion([ - 'values' => json_encode(['a', 'b', 'c']) + 'fieldtype' => $fieldtype, + 'values' => 'a\r\nb\r\nc' ]), 'value' => json_encode(['a', 'c']), 'expected' => "a\r\nc" diff --git a/tests/3-unit/GlpiPlugin/Formcreator/Field/RadiosField.php b/tests/3-unit/GlpiPlugin/Formcreator/Field/RadiosField.php index 53dc4ecd3..172ac3343 100644 --- a/tests/3-unit/GlpiPlugin/Formcreator/Field/RadiosField.php +++ b/tests/3-unit/GlpiPlugin/Formcreator/Field/RadiosField.php @@ -30,10 +30,10 @@ */ namespace GlpiPlugin\Formcreator\Field\tests\units; -use GlpiPlugin\Formcreator\Tests\CommonTestCase; +use GlpiPlugin\Formcreator\Tests\CommonAbstractFieldTestCase; use PluginFormcreatorFormAnswer; -class RadiosField extends CommonTestCase { +class RadiosField extends CommonAbstractFieldTestCase { public function testPrepareQuestionInputForSave() { $question = $this->getQuestion([ 'fieldtype' => 'radios', @@ -405,4 +405,34 @@ public function testGetValueForApi($input, $expected) { $output = $instance->getValueForApi(); $this->string($output)->isEqualTo($expected); } + + public function providerGetValueForTargetText() { + $fieldtype = 'select'; + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + 'values' => 'foo\r\nbar', + ]), + 'value' => '', + 'expectedValue' => '', + ]; + + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + 'values' => 'foo\r\nbar', + ]), + 'value' => 'foo', + 'expectedValue' => 'foo', + ]; + + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + 'values' => 'foo > baz\r\nbar', // Saved sanitized in DB + ]), + 'value' => 'foo > baz', // Sanitized when used in a form + 'expectedValue' => 'foo > baz', + ]; + } } diff --git a/tests/3-unit/GlpiPlugin/Formcreator/Field/SelectField.php b/tests/3-unit/GlpiPlugin/Formcreator/Field/SelectField.php index 871bf682f..93fcf0558 100644 --- a/tests/3-unit/GlpiPlugin/Formcreator/Field/SelectField.php +++ b/tests/3-unit/GlpiPlugin/Formcreator/Field/SelectField.php @@ -30,10 +30,10 @@ */ namespace GlpiPlugin\Formcreator\Field\tests\units; -use GlpiPlugin\Formcreator\Tests\CommonTestCase; +use GlpiPlugin\Formcreator\Tests\CommonAbstractFieldTestCase; use PluginFormcreatorFormAnswer; -class SelectField extends CommonTestCase { +class SelectField extends CommonAbstractFieldTestCase { public function providerGetAvailableValue() { $dataset = [ @@ -464,4 +464,34 @@ public function testGetValueForApi($input, $expected) { $output = $instance->getValueForApi(); $this->string($output)->isEqualTo($expected); } + + public function providerGetValueForTargetText() { + $fieldtype = 'select'; + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + 'values' => 'foo\r\nbar', + ]), + 'value' => '', + 'expectedValue' => '', + ]; + + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + 'values' => 'foo\r\nbar', + ]), + 'value' => 'foo', + 'expectedValue' => 'foo', + ]; + + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + 'values' => 'foo > baz\r\nbar', // Saved sanitized in DB + ]), + 'value' => 'foo > baz', // Sanitized when used in a form + 'expectedValue' => 'foo > baz', + ]; + } } diff --git a/tests/3-unit/GlpiPlugin/Formcreator/Field/TextareaField.php b/tests/3-unit/GlpiPlugin/Formcreator/Field/TextareaField.php index e4b57b6f3..813346869 100644 --- a/tests/3-unit/GlpiPlugin/Formcreator/Field/TextareaField.php +++ b/tests/3-unit/GlpiPlugin/Formcreator/Field/TextareaField.php @@ -325,4 +325,16 @@ public function testGetRenderedHtml() { $output = $instance->getRenderedHtml('no_domain', true); $this->string($output)->contains('">'); } + + public function providerGetValueForTargetText() { + $fieldtype = 'textarea'; + yield [ + 'question' => $this->getQuestion([ + 'fieldtype' => $fieldtype, + ]), + 'value' => '

foo

bar

', + 'expectedValue' => 'foobar', + 'expectedRichValue' => '

foo

bar

', + ]; + } } diff --git a/tests/3-unit/PluginFormcreatorCategory.php b/tests/3-unit/PluginFormcreatorCategory.php index c9b4d3470..7f4a60934 100644 --- a/tests/3-unit/PluginFormcreatorCategory.php +++ b/tests/3-unit/PluginFormcreatorCategory.php @@ -29,8 +29,8 @@ * --------------------------------------------------------------------- */ namespace tests\units; -use GlpiPlugin\Formcreator\Tests\CommonTestCase; use Entity; +use GlpiPlugin\Formcreator\Tests\CommonTestCase; use PluginFormcreatorForm; use Session; diff --git a/tests/src/CommonAbstractFieldTestCase.php b/tests/src/CommonAbstractFieldTestCase.php new file mode 100644 index 000000000..26396a160 --- /dev/null +++ b/tests/src/CommonAbstractFieldTestCase.php @@ -0,0 +1,71 @@ +. + * --------------------------------------------------------------------- + * @copyright Copyright © 2011 - 2021 Teclib' + * @license http://www.gnu.org/licenses/gpl.txt GPLv3+ + * @link https://github.com/pluginsGLPI/formcreator/ + * @link https://pluginsglpi.github.io/formcreator/ + * @link http://plugins.glpi-project.org/#/plugin/formcreator + * --------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Formcreator\Tests; + +use Glpi\Toolbox\Sanitizer; + +abstract class CommonAbstractFieldTestCase extends CommonTestCase { + + /** + * @dataProvider providerGetValueForTargetText + * + * @return void + */ + public function testGetValueForTargetText($question, $value, $expectedValue, $expectedRichValue = null) { + $instance = $this->newTestedInstance($question); + $output = $instance->parseAnswerValues([ + 'formcreator_field_' . $question->getID() => $value + ]); + + // Simple text output + $output = $instance->getValueForTargetText('', false); + if ($expectedValue === null) { + $this->variable($output)->isNull(); + } else { + $this->string($output) + ->isEqualTo($expectedValue); + } + + // Rich text output + $output = $instance->getValueForTargetText('', true); + if ($expectedValue === null) { + $this->variable($output)->isNull(); + return; + } + + if ($expectedRichValue === null) { + $expectedRichValue = $expectedValue; + } + $this->string($output) + ->isEqualTo($expectedRichValue); + } +} From 88559d2b1a51b35848db4e226a12df557839b57c Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Mon, 5 Jun 2023 09:31:53 +0200 Subject: [PATCH 11/58] docs(locale): fix typo in french --- locales/fr_FR.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/fr_FR.po b/locales/fr_FR.po index e50978d9b..bbb82a124 100644 --- a/locales/fr_FR.po +++ b/locales/fr_FR.po @@ -2450,7 +2450,7 @@ msgid "" "ignored." msgstr "" "Le mini tableau de bord de Formcreator n'est pas utilisable comme défaut. Ce" -" paramètres a été ignoré." +" paramètre a été ignoré." #: js/scripts.js:296 msgid "No form found. Please choose a form below instead." From 7841cd71b4af2a5c7c07738eae8366b4c662027f Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 6 Jun 2023 09:25:06 +0200 Subject: [PATCH 12/58] refactor(dropdownfield): remove dead code itemtype has been migrated from JSON encoded string in values column, to the dedicated itemtype column un 2.13.0 --- inc/field/dropdownfield.class.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/inc/field/dropdownfield.class.php b/inc/field/dropdownfield.class.php index d4cd38ea5..733bf84e8 100644 --- a/inc/field/dropdownfield.class.php +++ b/inc/field/dropdownfield.class.php @@ -713,17 +713,8 @@ public function parseObjectProperties( $TRANSLATE->setLocale("en_GB"); // Load target item from DB - // $itemtype = $question->getField('values'); $itemtype = $this->question->fields['itemtype']; - // Itemtype is stored in plaintext for GlpiselectField and in - // json for DropdownField - $json = json_decode($itemtype); - - if ($json) { - $itemtype = $json->itemtype; - } - // Safe check if (empty($itemtype) || !class_exists($itemtype)) { return $content; From 2539e366c20427c63ef6f0dd1c8c800622ca01b3 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Mon, 12 Jun 2023 12:58:52 +0200 Subject: [PATCH 13/58] fix(dropdownfield): SQL error for GLPI objects / tickets and some specific rights --- inc/field/dropdownfield.class.php | 34 ++++++++++++------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/inc/field/dropdownfield.class.php b/inc/field/dropdownfield.class.php index 733bf84e8..8de0c67b3 100644 --- a/inc/field/dropdownfield.class.php +++ b/inc/field/dropdownfield.class.php @@ -57,6 +57,7 @@ use SLA; use SLM; use OLA; +use QueryExpression; use QuerySubQuery; use QueryUnion; use GlpiPlugin\Formcreator\Exception\ComparisonException; @@ -227,9 +228,11 @@ public function buildParams($rand = null) { $currentUser = Session::getLoginUserID(); if (!Session::haveRight(Ticket::$rightname, Ticket::READMY) && !Session::haveRight(Ticket::$rightname, Ticket::READGROUP)) { // No right to view any ticket, then force the dropdown to be empty - $dparams_cond_crit['OR'] = new \QueryExpression('0=1'); + $dparams_cond_crit['OR'] = new QueryExpression('0=1'); break; } + $tickets_filter = ['users_id_recipient' => $currentUser]; + if (Session::haveRight(Ticket::$rightname, Ticket::READMY)) { $requestersObserversQuery = new QuerySubQuery([ 'SELECT' => 'tickets_id', @@ -239,34 +242,23 @@ public function buildParams($rand = null) { 'type' => [CommonITILActor::REQUESTER, CommonITILActor::OBSERVER] ], ]); - $dparams_cond_crit['OR'] = [ + $tickets_filter[] = [ 'id' => $requestersObserversQuery, - 'users_id_recipient' => $currentUser, ]; } - if (Session::haveRight(Ticket::$rightname, Ticket::READGROUP)) { - $sub_query = [ + + if (Session::haveRight(Ticket::$rightname, Ticket::READGROUP) && count($_SESSION['glpigroups']) > '0') { + $requestersObserversGroupsQuery = new QuerySubQuery([ 'SELECT' => 'tickets_id', 'FROM' => Group_Ticket::getTable(), 'WHERE' => [ - 'type' => [CommonITILActor::REQUESTER, CommonITILActor::OBSERVER] + 'type' => [CommonITILActor::REQUESTER, CommonITILActor::OBSERVER], + 'groups_id' => $_SESSION['glpigroups'], ], - ]; - if (count($_SESSION['glpigroups']) > '0') { - $sub_query['WHERE']['groups_id'] = $_SESSION['glpigroups']; - } - $requestersObserversGroupsQuery = new QuerySubQuery($sub_query); - if (!isset($dparams_cond_crit['OR']['id'])) { - $dparams_cond_crit['OR'] = [ - 'id' => $requestersObserversGroupsQuery, - ]; - } else { - $dparams_cond_crit['OR']['id'] = new QueryUnion([ - $dparams_cond_crit['OR']['id'], - $requestersObserversGroupsQuery, - ]); - } + ]); + $tickets_filter[] = ['id' => $requestersObserversGroupsQuery]; } + $dparams_cond_crit['OR'] = $tickets_filter; break; default: From 5af78d22bffd2f959ea68f94ee19aa7d423e71aa Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 13 Jun 2023 10:08:37 +0200 Subject: [PATCH 14/58] docs: specify GLPI version required to clean fix from the plugin --- css/styles.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/css/styles.scss b/css/styles.scss index a93d0deeb..d080b9d94 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -1068,7 +1068,7 @@ a.plugin_formcreator_formTile_title { } } -/* TODO when the following PR is merged and minimal GLPI version is above the version containing it, remove this CSS */ +/* remove this CSS when requirement is GLPI 10.0.1 or later */ /* https://github.com/glpi-project/glpi/pull/11524 */ .formcreator_dashboard_container .dashboard .big-number .label { font-size: 12px !important; From ad5a9b2acfe828a18163fb1f6b9d37cd22b79713 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Mon, 12 Jun 2023 13:50:11 +0200 Subject: [PATCH 15/58] refactor(textareafield): drop useless code current GLPI implementation of a rich text input renders a file input, then no need to render ourselve --- inc/field/textareafield.class.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/inc/field/textareafield.class.php b/inc/field/textareafield.class.php index 316b15d1b..26613b5eb 100644 --- a/inc/field/textareafield.class.php +++ b/inc/field/textareafield.class.php @@ -33,7 +33,6 @@ namespace GlpiPlugin\Formcreator\Field; use PluginFormcreatorCommon; -use PluginFormcreatorQuestion; use PluginFormcreatorForm; use PluginFormcreatorFormAnswer; use Html; @@ -165,15 +164,6 @@ public function getRenderedHtml($domain, $canEdit = true): string { 'enable_fileupload' => false, 'uploads' => $this->uploads, ]); - // The following file upload area is needed to allow embedded pics in the textarea - $html .= '
'; - Html::file(['editor_id' => "$fieldName$rand", - 'filecontainer' => "filecontainer$rand", - 'onlyimages' => true, - 'showtitle' => false, - 'multiple' => true, - 'display' => false]); - $html .= '
'; $html .= Html::scriptBlock("$(function() { pluginFormcreatorInitializeTextarea('$fieldName', '$rand'); });"); From 49f8fc0749d496109b1cd06e2271126dee7bb0f7 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 7 Jun 2023 08:53:29 +0200 Subject: [PATCH 16/58] fix(dropdownfield): prevent language switching and log error --- inc/field/dropdownfield.class.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/inc/field/dropdownfield.class.php b/inc/field/dropdownfield.class.php index 8de0c67b3..17193ffb4 100644 --- a/inc/field/dropdownfield.class.php +++ b/inc/field/dropdownfield.class.php @@ -700,10 +700,6 @@ public function parseObjectProperties( // $questionID = $question->fields['id']; $questionID = $this->getQuestion()->getID(); - // We need english locale to search searchOptions by name - $oldLocale = $TRANSLATE->getLocale(); - $TRANSLATE->setLocale("en_GB"); - // Load target item from DB $itemtype = $this->question->fields['itemtype']; @@ -712,6 +708,10 @@ public function parseObjectProperties( return $content; } + // We need english locale to search searchOptions by name + $oldLocale = $TRANSLATE->getLocale(); + $TRANSLATE->setLocale("en_GB"); + $item = new $itemtype; $item->getFromDB($answer); @@ -726,6 +726,11 @@ public function parseObjectProperties( // Convert Property_Name to Property Name $property = str_replace("_", " ", $property); $searchOption = $item->getSearchOptionByField("name", $property); + if (count($searchOption) == 0) { + trigger_error("No search option found for $property", E_USER_WARNING); + $TRANSLATE->setLocale($oldLocale); + return $content; + } // Execute search $data = Search::prepareDatasForSearch(get_class($item), [ From a6f9c41c3b53da230922ecefc89c433e7f776c51 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 30 May 2023 18:36:08 +0200 Subject: [PATCH 17/58] fix(section): duplicate form may lead to bad question id in condition --- inc/condition.class.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/inc/condition.class.php b/inc/condition.class.php index e2b5db8ad..1635baea9 100644 --- a/inc/condition.class.php +++ b/inc/condition.class.php @@ -153,14 +153,8 @@ public static function import(PluginFormcreatorLinker $linker, array $input = [] // set ID for linked objects $linked = $linker->getObject($input['plugin_formcreator_questions_id'], PluginFormcreatorQuestion::class); if ($linked === false) { - $linked = new PluginFormcreatorQuestion(); - $linked->getFromDBByCrit([ - $idKey => $input['plugin_formcreator_questions_id'] - ]); - if ($linked->isNewItem()) { - $linker->postpone($input[$idKey], $item->getType(), $input, $containerId); - return false; - } + $linker->postpone($input[$idKey], $item->getType(), $input, $containerId); + return false; } /** @var CommonDBTM $linked */ $input['plugin_formcreator_questions_id'] = $linked->getID(); From 883a12278fe80911f949d38b47fe4add43f4cc4e Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 23 May 2023 15:21:31 +0200 Subject: [PATCH 18/58] fix(section): condition rule loss after duplicate / import --- tests/3-unit/PluginFormcreatorSection.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/3-unit/PluginFormcreatorSection.php b/tests/3-unit/PluginFormcreatorSection.php index 4301c0fcd..6896a5836 100644 --- a/tests/3-unit/PluginFormcreatorSection.php +++ b/tests/3-unit/PluginFormcreatorSection.php @@ -32,6 +32,7 @@ use GlpiPlugin\Formcreator\Tests\CommonTestCase; use PluginFormcreatorCommon; use PluginFormcreatorCondition; +use PluginFormcreatorConditionnableInterface; use PluginFormcreatorForm; use PluginFormcreatorLinker; use PluginFormcreatorQuestion; From acbcd09fbbcb44e22cd57d347df301c26c84194c Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 14 Jun 2023 09:18:55 +0200 Subject: [PATCH 19/58] refactor(integerfield): factorize with float --- inc/field/floatfield.class.php | 6 ++++- inc/field/integerfield.class.php | 42 +++++--------------------------- 2 files changed, 11 insertions(+), 37 deletions(-) diff --git a/inc/field/floatfield.class.php b/inc/field/floatfield.class.php index 19f58dcba..38a36f3aa 100644 --- a/inc/field/floatfield.class.php +++ b/inc/field/floatfield.class.php @@ -152,7 +152,11 @@ public function isValidValue($value): bool { $regex = $parameters['regex']->fields['regex']; if ($regex !== null && strlen($regex) > 0) { if (!preg_match($regex, $value)) { - Session::addMessageAfterRedirect(sprintf(__('Specific format does not match: %s', 'formcreator'), $this->question->fields['name']), false, ERROR); + Session::addMessageAfterRedirect( + sprintf(__('Specific format does not match: %s', 'formcreator'), $this->question->fields['name']), + false, + ERROR + ); return false; } } diff --git a/inc/field/integerfield.class.php b/inc/field/integerfield.class.php index 21825ed13..04588b409 100644 --- a/inc/field/integerfield.class.php +++ b/inc/field/integerfield.class.php @@ -56,45 +56,15 @@ public function isValidValue($value): bool { } if (!empty($value) && !ctype_digit((string) $value)) { - Session::addMessageAfterRedirect(sprintf(__('This is not an integer: %s', 'formcreator'), $this->getTtranslatedLabel()), false, ERROR); + Session::addMessageAfterRedirect( + sprintf(__('This is not an integer: %s', 'formcreator'), $this->getTtranslatedLabel()), + false, + ERROR + ); return false; } - $parameters = $this->getParameters(); - - // Check the field matches the format regex - if (!$parameters['regex']->isNewItem()) { - $regex = $parameters['regex']->fields['regex']; - if ($regex !== null && strlen($regex) > 0) { - if (!preg_match($regex, $value)) { - Session::addMessageAfterRedirect( - sprintf(__('Specific format does not match: %s', 'formcreator'), $this->getTtranslatedLabel()), - false, - ERROR - ); - return false; - } - } - } - - // Check the field is in the range - if (!$parameters['range']->isNewItem()) { - $rangeMin = $parameters['range']->fields['range_min']; - $rangeMax = $parameters['range']->fields['range_max']; - if ($rangeMin > 0 && $value < $rangeMin) { - $message = sprintf(__('The following number must be greater than %d: %s', 'formcreator'), $rangeMin, $this->getTtranslatedLabel()); - Session::addMessageAfterRedirect($message, false, ERROR); - return false; - } - - if ($rangeMax > 0 && $value > $rangeMax) { - $message = sprintf(__('The following number must be lower than %d: %s', 'formcreator'), $rangeMax, $this->getTtranslatedLabel()); - Session::addMessageAfterRedirect($message, false, ERROR); - return false; - } - } - - return true; + return parent::isValidValue($value); } public static function getName(): string { From 66585193ee70c41dcc8f318e5625a93482c7cb2d Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 14 Jun 2023 10:21:27 +0200 Subject: [PATCH 20/58] fix(checkboxesfield,radiosfield,selectfield): add missing error messages --- inc/field/checkboxesfield.class.php | 10 ++++++++++ inc/field/radiosfield.class.php | 12 +++++++++++- inc/field/selectfield.class.php | 11 ++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/inc/field/checkboxesfield.class.php b/inc/field/checkboxesfield.class.php index 07cdc072e..eeb7fdde0 100644 --- a/inc/field/checkboxesfield.class.php +++ b/inc/field/checkboxesfield.class.php @@ -204,9 +204,19 @@ public function isValidValue($value): bool { foreach ($value as $item) { if (trim($item) == '') { + Session::addMessageAfterRedirect( + sprintf(__('Empty values are not allowed: %s', 'formcreator'), $this->getTtranslatedLabel()), + false, + ERROR + ); return false; } if (!in_array($item, $this->getAvailableValues())) { + Session::addMessageAfterRedirect( + sprintf(__('This value %1$s is not alowed: %2$s', 'formcreator'), $item, $this->getTtranslatedLabel()), + false, + ERROR + ); return false; } } diff --git a/inc/field/radiosfield.class.php b/inc/field/radiosfield.class.php index 4026d1179..5d8049ed2 100644 --- a/inc/field/radiosfield.class.php +++ b/inc/field/radiosfield.class.php @@ -204,8 +204,18 @@ public function isValidValue($value): bool { if ($value == '') { return true; } + $value = trim($value); - return in_array($value, $this->getAvailableValues()); + if (!in_array($value, $this->getAvailableValues())) { + Session::addMessageAfterRedirect( + sprintf(__('This value %1$s is not allowed: %2$s', 'formcreator'), $value, $this->getTtranslatedLabel()), + false, + ERROR + ); + return false; + } + + return true; } public static function canRequire(): bool { diff --git a/inc/field/selectfield.class.php b/inc/field/selectfield.class.php index 9296b24cc..68e6b402b 100644 --- a/inc/field/selectfield.class.php +++ b/inc/field/selectfield.class.php @@ -118,7 +118,16 @@ public function isValidValue($value): bool { return true; } $value = trim($value); - return in_array($value, $this->getAvailableValues()); + if (!in_array($value, $this->getAvailableValues())) { + Session::addMessageAfterRedirect( + sprintf(__('This value %1$s is not allowed: %2$s', 'formcreator'), $value, $this->getTtranslatedLabel()), + false, + ERROR + ); + return false; + } + + return true; } public function equals($value): bool { From d630302d0792c9156976aba5e6d8714f9f052655 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 14 Jun 2023 10:03:09 +0200 Subject: [PATCH 21/58] fix(formanswer): prevent silent rejection of answers --- inc/formanswer.class.php | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/inc/formanswer.class.php b/inc/formanswer.class.php index 3bda2a636..f66c4b082 100644 --- a/inc/formanswer.class.php +++ b/inc/formanswer.class.php @@ -1397,12 +1397,32 @@ protected function validateFormAnswer($input): bool { $this->isAnswersValid = !in_array(false, $fieldValidities, true); if ($this->isAnswersValid) { + $form = $this->getForm(); + $domain = PluginFormcreatorForm::getTranslationDomain($form->getID()); foreach ($this->questionFields as $id => $field) { if (!$this->questionFields[$id]->isPrerequisites()) { continue; } + // Count the errors in session + $errors_count = $_SESSION['MESSAGE_AFTER_REDIRECT'][ERROR] + ? count($_SESSION['MESSAGE_AFTER_REDIRECT'][ERROR]) + : 0; if (PluginFormcreatorFields::isVisible($field->getQuestion(), $this->questionFields) && !$this->questionFields[$id]->isValid()) { - $this->isAnswersValid = false; + $new_errors_count = $_SESSION['MESSAGE_AFTER_REDIRECT'][ERROR] + ? count($_SESSION['MESSAGE_AFTER_REDIRECT'][ERROR]) + : 0; + + if ($new_errors_count <= $errors_count) { + // If there are new errors, we add a message to the user + $field_name = __($field->getQuestion()->fields['name'], $domain); + Session::addMessageAfterRedirect( + sprintf(__('Answer is invalid in %1$s', 'formcreator'), $field_name), + true, + ERROR + ); + } + + $this->isAnswersValid = false; } } } From ce078990fe3f793ce296024c8b2f49df01d2ab69 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 14 Jun 2023 17:42:33 +0200 Subject: [PATCH 22/58] fix(formanswer): php warning --- inc/formanswer.class.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/inc/formanswer.class.php b/inc/formanswer.class.php index f66c4b082..a5ff1f575 100644 --- a/inc/formanswer.class.php +++ b/inc/formanswer.class.php @@ -1404,9 +1404,10 @@ protected function validateFormAnswer($input): bool { continue; } // Count the errors in session - $errors_count = $_SESSION['MESSAGE_AFTER_REDIRECT'][ERROR] - ? count($_SESSION['MESSAGE_AFTER_REDIRECT'][ERROR]) - : 0; + $errors_count = 0; + if (isset($_SESSION['MESSAGE_AFTER_REDIRECT'][ERROR])) { + $errors_count = count($_SESSION['MESSAGE_AFTER_REDIRECT'][ERROR]); + } if (PluginFormcreatorFields::isVisible($field->getQuestion(), $this->questionFields) && !$this->questionFields[$id]->isValid()) { $new_errors_count = $_SESSION['MESSAGE_AFTER_REDIRECT'][ERROR] ? count($_SESSION['MESSAGE_AFTER_REDIRECT'][ERROR]) From be4831c7d1f6a2873fa180d9c8854830bbe4d316 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 13 Jun 2023 11:48:08 +0200 Subject: [PATCH 23/58] fix(datefield, datetimefield): comparison against empty string --- inc/field/datefield.class.php | 6 ++++++ inc/field/datetimefield.class.php | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/inc/field/datefield.class.php b/inc/field/datefield.class.php index a7414885a..847dee41f 100644 --- a/inc/field/datefield.class.php +++ b/inc/field/datefield.class.php @@ -163,9 +163,15 @@ public function greaterThan($value): bool { } else { $answer = $this->value; } + if (empty($value)) { + $value = '0000-00-00'; + } $answerDatetime = DateTime::createFromFormat(self::DATE_FORMAT, $answer); $answerDatetime->setTime(0, 0, 0, 0); $compareDatetime = DateTime::createFromFormat(self::DATE_FORMAT, $value); + if ($compareDatetime === false) { + return true; + } $compareDatetime->setTime(0, 0, 0, 0); return $answerDatetime > $compareDatetime; } diff --git a/inc/field/datetimefield.class.php b/inc/field/datetimefield.class.php index bdcc4beb8..17ba83ade 100644 --- a/inc/field/datetimefield.class.php +++ b/inc/field/datetimefield.class.php @@ -164,8 +164,14 @@ public function greaterThan($value): bool { } else { $answer = $this->value; } + if (empty($value)) { + $value = '0000-00-00'; + } $answerDatetime = DateTime::createFromFormat(self::DATE_FORMAT, $answer); $compareDatetime = DateTime::createFromFormat(self::DATE_FORMAT, $value); + if ($compareDatetime === false) { + return true; + } return $answerDatetime > $compareDatetime; } From c15f9246ba873a7c0276b85f2de7d5e7b92d5146 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 13 Jun 2023 13:36:10 +0200 Subject: [PATCH 24/58] test(datefield,datetimefield): add test cases --- .../3-unit/GlpiPlugin/Formcreator/Field/DateField.php | 11 ++++++++++- .../GlpiPlugin/Formcreator/Field/DatetimeField.php | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/3-unit/GlpiPlugin/Formcreator/Field/DateField.php b/tests/3-unit/GlpiPlugin/Formcreator/Field/DateField.php index b0c67b904..35d856963 100644 --- a/tests/3-unit/GlpiPlugin/Formcreator/Field/DateField.php +++ b/tests/3-unit/GlpiPlugin/Formcreator/Field/DateField.php @@ -176,6 +176,11 @@ public function providerEquals() { 'answer' => '2019-01-01', 'expected' => true, ], + [ + 'value' => '', + 'answer' => '2019-01-01', + 'expected' => false, + ], ]; } @@ -206,7 +211,11 @@ public function providerNotEquals() { 'answer' => '2019-01-01', 'expected' => false, ], - + [ + 'value' => '', + 'answer' => '2019-01-01', + 'expected' => true, + ], ]; } diff --git a/tests/3-unit/GlpiPlugin/Formcreator/Field/DatetimeField.php b/tests/3-unit/GlpiPlugin/Formcreator/Field/DatetimeField.php index 1fd0c79a9..3c494d6e9 100644 --- a/tests/3-unit/GlpiPlugin/Formcreator/Field/DatetimeField.php +++ b/tests/3-unit/GlpiPlugin/Formcreator/Field/DatetimeField.php @@ -236,6 +236,11 @@ public function providerEquals() { 'answer' => '2019-01-01 03:00:00', 'expected' => true, ], + [ + 'value' => '', + 'answer' => '2019-01-01 03:00:00', + 'expected' => false, + ], ]; } @@ -266,6 +271,11 @@ public function providerNotEquals() { 'answer' => '2019-01-01 03:00:00', 'expected' => false, ], + [ + 'value' => '', + 'answer' => '2019-01-01 03:00:00', + 'expected' => true, + ], ]; } From 34591b40e70922b44fac025a1643aedc9fffbc89 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 13 Jun 2023 13:44:47 +0200 Subject: [PATCH 25/58] refactor(datefield): factorize code --- inc/field/datefield.class.php | 158 +++--------------------------- inc/field/datetimefield.class.php | 39 ++++---- 2 files changed, 33 insertions(+), 164 deletions(-) diff --git a/inc/field/datefield.class.php b/inc/field/datefield.class.php index 847dee41f..572b07d65 100644 --- a/inc/field/datefield.class.php +++ b/inc/field/datefield.class.php @@ -32,7 +32,6 @@ namespace GlpiPlugin\Formcreator\Field; -use PluginFormcreatorAbstractField; use Html; use DateTime; use Session; @@ -40,25 +39,10 @@ use GlpiPlugin\Formcreator\Exception\ComparisonException; use Glpi\Application\View\TemplateRenderer; -class DateField extends PluginFormcreatorAbstractField +class DateField extends DatetimeField { const DATE_FORMAT = 'Y-m-d'; - public function isPrerequisites(): bool { - return true; - } - - public function showForm(array $options): void { - $template = '@formcreator/field/' . $this->question->fields['fieldtype'] . 'field.html.twig'; - - $this->question->fields['default_values'] = Html::entities_deep($this->question->fields['default_values']); - $this->deserializeValue($this->question->fields['default_values']); - TemplateRenderer::getInstance()->display($template, [ - 'item' => $this->question, - 'params' => $options, - ]); - } - public function getRenderedHtml($domain, $canEdit = true): string { if (!$canEdit) { return $this->value; @@ -81,143 +65,25 @@ public function getRenderedHtml($domain, $canEdit = true): string { return $html; } - public function serializeValue(PluginFormcreatorFormAnswer $formanswer): string { - return $this->value; - } - - public function deserializeValue($value) { - $this->value = $value; - } - - public function getValueForDesign(): string { - return $this->value; - } - - public function getValueForTargetText($domain, $richText): ?string { - return Html::convDate($this->value); - } - - public function hasInput($input): bool { - return isset($input['formcreator_field_' . $this->question->getID()]); - } - - public function moveUploads() { - } - - public function getDocumentsForTarget(): array { - return []; - } - - public function isValid(): bool { - // If the field is required it can't be empty - if ($this->isRequired() && (strtotime($this->value) == '')) { - Session::addMessageAfterRedirect( - sprintf(__('A required field is empty: %s', 'formcreator'), $this->getTtranslatedLabel()), - false, - ERROR - ); - return false; - } - - // All is OK - return $this->isValidValue($this->value); - } - - public function isValidValue($value): bool { - if (!$this->isRequired() && empty($value)) { - return true; - } - - $check = DateTime::createFromFormat(self::DATE_FORMAT, $value); - return $check !== false; - } - public static function getName(): string { return __('Date'); } - public static function canRequire(): bool { - return true; - } - - public function equals($value): bool { - if ($this->value === '') { - $answer = '0000-00-00'; - } else { - $answer = $this->value; - } - $answerDatetime = DateTime::createFromFormat(self::DATE_FORMAT, $answer); - $answerDatetime->setTime(0, 0, 0, 0); - $compareDatetime = DateTime::createFromFormat(self::DATE_FORMAT, $value); - $compareDatetime->setTime(0, 0, 0, 0); - return $answerDatetime == $compareDatetime; - } - - public function notEquals($value): bool { - return !$this->equals($value); - } - - public function greaterThan($value): bool { - if (empty($this->value)) { - $answer = '0000-00-00'; - } else { - $answer = $this->value; - } + /** + * Convert a string value into DateTime object + * + * @param string $value + * @return false|DateTime + */ + protected function getDateFromValue(string $value) { if (empty($value)) { $value = '0000-00-00'; } - $answerDatetime = DateTime::createFromFormat(self::DATE_FORMAT, $answer); - $answerDatetime->setTime(0, 0, 0, 0); - $compareDatetime = DateTime::createFromFormat(self::DATE_FORMAT, $value); - if ($compareDatetime === false) { - return true; + $datetime = DateTime::createFromFormat(self::DATE_FORMAT, $value); + if ($datetime !== false) { + $datetime->setTime(0, 0, 0, 0); } - $compareDatetime->setTime(0, 0, 0, 0); - return $answerDatetime > $compareDatetime; - } - - public function lessThan($value): bool { - return !$this->greaterThan($value) && !$this->equals($value); - } - - public function regex($value): bool { - throw new ComparisonException('Meaningless comparison'); - } - - public function parseAnswerValues($input, $nonDestructive = false): bool { - $key = 'formcreator_field_' . $this->question->getID(); - if (!isset($input[$key])) { - $input[$key] = ''; - } - - if (!is_string($input[$key])) { - return false; - } - - if ($input[$key] != '' - && DateTime::createFromFormat(self::DATE_FORMAT, $input[$key]) === false - ) { - return false; - } - - $this->value = $input[$key]; - return true; - } - - public function isPublicFormCompatible(): bool { - return true; - } - - public function getHtmlIcon(): string { - return ''; - } - - public function isVisibleField(): bool { - return true; - } - - public function isEditableField(): bool { - return true; + return $datetime; } public function getValueForApi() { diff --git a/inc/field/datetimefield.class.php b/inc/field/datetimefield.class.php index 17ba83ade..dd84acddf 100644 --- a/inc/field/datetimefield.class.php +++ b/inc/field/datetimefield.class.php @@ -131,7 +131,7 @@ public function isValidValue($value): bool { return true; } - $check = DateTime::createFromFormat(self::DATE_FORMAT, $value); + $check = $this->getDateFromValue($value); return $check !== false; } @@ -143,14 +143,25 @@ public static function canRequire(): bool { return true; } + /** + * Convert a string value into DateTime object + * + * @param string $value + * @return false|DateTime + */ + protected function getDateFromValue(string $value) { + if (empty($value)) { + $value = '0000-00-00 00:00:00'; + } + return DateTime::createFromFormat(self::DATE_FORMAT, $value); + } + public function equals($value): bool { - if ($this->value === '') { - $answer = '0000-00-00 00:00:00'; - } else { - $answer = $this->value; + $answerDatetime = $this->getDateFromValue($this->value ?? ''); + $compareDatetime = $this->getDateFromValue($value); + if ($compareDatetime === false) { + return false; } - $answerDatetime = DateTime::createFromFormat(self::DATE_FORMAT, $answer); - $compareDatetime = DateTime::createFromFormat(self::DATE_FORMAT, $value); return $answerDatetime == $compareDatetime; } @@ -159,16 +170,8 @@ public function notEquals($value): bool { } public function greaterThan($value): bool { - if (empty($this->value)) { - $answer = '0000-00-00 00:00:00'; - } else { - $answer = $this->value; - } - if (empty($value)) { - $value = '0000-00-00'; - } - $answerDatetime = DateTime::createFromFormat(self::DATE_FORMAT, $answer); - $compareDatetime = DateTime::createFromFormat(self::DATE_FORMAT, $value); + $answerDatetime = $this->getDateFromValue($this->value ?? ''); + $compareDatetime = $this->getDateFromValue($value); if ($compareDatetime === false) { return true; } @@ -193,7 +196,7 @@ public function parseAnswerValues($input, $nonDestructive = false): bool { } if ($input[$key] != '' - && DateTime::createFromFormat(self::DATE_FORMAT, $input[$key]) === false + && $this->getDateFromValue($input[$key]) === false ) { return false; } From 6328fc6b14d8aded7ab913a9c922e8ae743ef741 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 13 Jun 2023 14:34:22 +0200 Subject: [PATCH 26/58] style(datefield): code style --- inc/field/datefield.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/field/datefield.class.php b/inc/field/datefield.class.php index 572b07d65..49c813144 100644 --- a/inc/field/datefield.class.php +++ b/inc/field/datefield.class.php @@ -75,7 +75,7 @@ public static function getName(): string { * @param string $value * @return false|DateTime */ - protected function getDateFromValue(string $value) { + protected function getDateFromValue(string $value) { if (empty($value)) { $value = '0000-00-00'; } From 9f498e4141a93c8dd4143c0707cb8a258a36d438 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 13 Jun 2023 14:41:59 +0200 Subject: [PATCH 27/58] style(datefield, datetimefield: use constant --- inc/field/datefield.class.php | 3 ++- inc/field/datetimefield.class.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/inc/field/datefield.class.php b/inc/field/datefield.class.php index 49c813144..651886580 100644 --- a/inc/field/datefield.class.php +++ b/inc/field/datefield.class.php @@ -42,6 +42,7 @@ class DateField extends DatetimeField { const DATE_FORMAT = 'Y-m-d'; + const DATE_ZERO = '0000-00-00'; public function getRenderedHtml($domain, $canEdit = true): string { if (!$canEdit) { @@ -77,7 +78,7 @@ public static function getName(): string { */ protected function getDateFromValue(string $value) { if (empty($value)) { - $value = '0000-00-00'; + $value = self::DATE_ZERO; } $datetime = DateTime::createFromFormat(self::DATE_FORMAT, $value); if ($datetime !== false) { diff --git a/inc/field/datetimefield.class.php b/inc/field/datetimefield.class.php index dd84acddf..62b305c27 100644 --- a/inc/field/datetimefield.class.php +++ b/inc/field/datetimefield.class.php @@ -46,6 +46,7 @@ class DatetimeField extends PluginFormcreatorAbstractField protected $fields = null; const DATE_FORMAT = 'Y-m-d H:i:s'; + const DATE_ZERO = '0000-00-00 00:00:00'; public function isPrerequisites(): bool { return true; @@ -151,7 +152,7 @@ public static function canRequire(): bool { */ protected function getDateFromValue(string $value) { if (empty($value)) { - $value = '0000-00-00 00:00:00'; + $value = self::DATE_ZERO; } return DateTime::createFromFormat(self::DATE_FORMAT, $value); } From 20e4a83f92c212f76943f7956dbfa21de4aa5ecf Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 13 Jun 2023 14:43:08 +0200 Subject: [PATCH 28/58] style(datefield): clean unused 'use' statements --- inc/field/datefield.class.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/inc/field/datefield.class.php b/inc/field/datefield.class.php index 651886580..4ab9006c9 100644 --- a/inc/field/datefield.class.php +++ b/inc/field/datefield.class.php @@ -34,10 +34,6 @@ use Html; use DateTime; -use Session; -use PluginFormcreatorFormAnswer; -use GlpiPlugin\Formcreator\Exception\ComparisonException; -use Glpi\Application\View\TemplateRenderer; class DateField extends DatetimeField { From 57fabc56f5dc3ed282676be8c9799c51fec6eebc Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Mon, 19 Jun 2023 11:27:44 +0200 Subject: [PATCH 29/58] docs(locales): update --- locales/en.mo | Bin 37099 -> 0 bytes locales/en.po | 2427 ---------------------------------------------- locales/en_US.mo | Bin 14723 -> 14480 bytes locales/fr_FR.mo | Bin 43465 -> 43464 bytes 4 files changed, 2427 deletions(-) delete mode 100644 locales/en.mo delete mode 100644 locales/en.po diff --git a/locales/en.mo b/locales/en.mo deleted file mode 100644 index e131f3cb3cf809c974ef03cc124f904d988592b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37099 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, YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-10-26 14:38+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: \n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" - -#: ajax/question_update.php:36 ajax/section_update.php:37 -msgid "Bad request" -msgstr "Bad request" - -#: ajax/question_update.php:45 ajax/question_move.php:45 -#: ajax/question_delete.php:42 ajax/question_toggle_required.php:49 -msgid "Question not found" -msgstr "Question not found" - -#: ajax/question_update.php:51 ajax/question_duplicate.php:49 -#: ajax/question_move.php:50 ajax/section_add.php:38 -#: ajax/section_delete.php:50 ajax/section_move.php:55 -#: ajax/section_duplicate.php:50 ajax/question_delete.php:49 -#: ajax/question_toggle_required.php:55 ajax/section_update.php:44 -msgid "You don't have right for this action" -msgstr "You don't have right for this action" - -#: ajax/question_duplicate.php:43 -msgid "Source question not found" -msgstr "Source question not found" - -#: ajax/question_move.php:73 -msgid "Could not move some questions" -msgstr "Could not move some questions" - -#: ajax/section_add.php:44 -msgid "Could not add the section" -msgstr "Could not add the section" - -#: ajax/commontree.php:55 entrée standard:109 standard:92 -msgid "Subtree root" -msgstr "Subtree root" - -#: ajax/commontree.php:59 -msgid "Selectable" -msgstr "Selectable" - -#: ajax/commontree.php:74 entrée standard:118 standard:101 -msgid "Limit subtree depth" -msgstr "Limit subtree depth" - -#: ajax/commontree.php:84 -msgid "No limit" -msgstr "No limit" - -#: ajax/homepage_link.php:36 inc/formlist.class.php:46 -#: inc/entityconfig.class.php:82 inc/form.class.php:111 inc/form.class.php:569 -#: inc/form.class.php:1951 -msgid "Form" -msgid_plural "Forms" -msgstr[0] "Form" -msgstr[1] "Forms" - -#: ajax/section_delete.php:44 ajax/section_move.php:49 -#: ajax/section_duplicate.php:44 -msgid "Source section not found" -msgstr "Source section not found" - -#: ajax/section_delete.php:56 -msgid "Could not delete the section" -msgstr "Could not delete the section" - -#: ajax/question_add.php:45 -msgid "Could not add the question" -msgstr "Could not add the question" - -#: ajax/section_move.php:66 -msgid "Could not move the section" -msgstr "Could not move the section" - -#: ajax/target_actor.php:51 -msgid "Failed to add the actor" -msgstr "Failed to add the actor" - -#: ajax/target_actor.php:62 -msgid "Failed to delete the actor" -msgstr "Failed to delete the actor" - -#: ajax/section_duplicate.php:56 -msgid "Could not duplicate the section" -msgstr "Could not duplicate the section" - -#: ajax/section_update.php:50 -msgid "Could not update the section" -msgstr "Could not update the section" - -#: front/knowbaseitem.php:41 front/knowbaseitem.php:43 front/wizard.php:44 -#: front/wizard.php:46 front/wizardfeeds.php:49 front/wizardfeeds.php:51 -#: front/issue.php:43 front/issue.php:46 front/formanswer.php:44 -#: front/reservation.php:46 front/reservation.php:48 -#: front/knowbaseitem.form.php:48 front/knowbaseitem.form.php:50 -#: front/reservationitem.php:42 front/reservationitem.php:44 -#: front/formanswer.form.php:75 front/reservation.form.php:46 -#: front/reservation.form.php:48 -msgid "Service catalog" -msgstr "Service catalog" - -#: front/issue.form.php:46 -msgid "Item not found" -msgstr "Item not found" - -#: front/targetticket.form.php:46 front/targetticket.form.php:56 -#: front/targetticket.form.php:81 front/targetchange.form.php:46 -#: front/targetproblem.form.php:46 -msgid "No right to update this item." -msgstr "No right to update this item." - -#: front/targetticket.form.php:75 -msgid "Bad request while deleting an actor." -msgstr "Bad request while deleting an actor." - -#: front/targetticket.form.php:95 front/targetchange.form.php:81 -#: front/formanswer.php:47 front/targetproblem.form.php:81 -#: front/formanswer.form.php:78 front/form.php:44 inc/common.class.php:689 -#: inc/common.class.php:696 -msgid "Form Creator" -msgstr "Form Creator" - -#: front/targetticket.form.php:105 front/targetchange.form.php:90 -#: front/targetproblem.form.php:90 -#, php-format -msgid "%1$s = %2$s" -msgstr "%1$s = %2$s" - -#: front/formlist.php:45 front/formlist.php:48 inc/common.class.php:686 -msgid "Form list" -msgstr "Form list" - -#: front/formdisplay.php:90 inc/formanswer.class.php:889 -#: inc/formanswer.class.php:1120 inc/formanswer.class.php:1170 -msgid "The form has been successfully saved!" -msgstr "The form has been successfully saved!" - -#. TRANS: %s is the user login -#: front/reservation.form.php:71 -#, php-format -msgid "%1$s purges the reservation for item %2$s" -msgstr "%1$s purges the reservation for item %2$s" - -#: front/reservation.form.php:124 -#, php-format -msgid "%1$s adds the reservation %2$s for item %3$s" -msgstr "%1$s adds the reservation %2$s for item %3$s" - -#: inc/knowbase.class.php:60 inc/form.class.php:646 -msgid "Category" -msgid_plural "Categories" -msgstr[0] "Category" -msgstr[1] "Categories" - -#: inc/knowbase.class.php:62 inc/form.class.php:649 -msgid "See all" -msgstr "See all" - -#: inc/knowbase.class.php:83 -msgid "Please, describe your need here" -msgstr "Please, describe your need here" - -#: inc/field/textareafield.class.php:183 -msgid "Textarea" -msgstr "Textarea" - -#: inc/field/textareafield.class.php:242 inc/field/dropdownfield.class.php:440 -#: inc/field/ldapselectfield.class.php:114 inc/field/textfield.class.php:125 -#: inc/field/urgencyfield.class.php:165 inc/field/tagfield.class.php:163 -#: inc/field/timefield.class.php:113 inc/field/fieldsfield.class.php:488 -#: inc/field/requesttypefield.class.php:160 -msgid "A required field is empty:" -msgstr "A required field is empty:" - -#: inc/field/textareafield.class.php:260 inc/field/textfield.class.php:178 -#: inc/field/integerfield.class.php:112 inc/field/floatfield.class.php:193 -#: inc/conditionnabletrait.class.php:70 -msgid "The regular expression is invalid" -msgstr "The regular expression is invalid" - -#: inc/field/dropdownfield.class.php:73 inc/filter/entityfilter.class.php:48 -msgid "User and form" -msgstr "User and form" - -#: inc/field/dropdownfield.class.php:431 entrée standard:38 -msgid "Dropdown" -msgid_plural "Dropdowns" -msgstr[0] "Dropdown" -msgstr[1] "Dropdowns" - -#: inc/field/dropdownfield.class.php:462 -msgid "Invalid value for " -msgstr "Invalid value for " - -#: inc/field/dropdownfield.class.php:474 -#, php-format -msgid "The itemtype field is required: %s" -msgstr "The itemtype field is required: %s" - -#: inc/field/dropdownfield.class.php:490 -#, php-format -msgid "Invalid dropdown type: %s" -msgstr "Invalid dropdown type: %s" - -#: inc/field/dropdownfield.class.php:821 entrée standard:143 standard:126 -msgid "Entity restriction" -msgstr "Entity restriction" - -#: inc/field/dropdownfield.class.php:830 -msgid "" -"To respect the GLPI entity system, \"Form\" should be selected. Others " -"settings will break the entity restrictions" -msgstr "" -"To respect the GLPI entity system, \"Form\" should be selected. Others " -"settings will break the entity restrictions" - -#: inc/field/ldapselectfield.class.php:95 -msgid "LDAP Select" -msgstr "LDAP Select" - -#: inc/field/ldapselectfield.class.php:139 -msgid "LDAP directory not defined!" -msgstr "LDAP directory not defined!" - -#: inc/field/ldapselectfield.class.php:146 -msgid "LDAP directory not found!" -msgstr "LDAP directory not found!" - -#: inc/field/textfield.class.php:146 inc/field/integerfield.class.php:71 -#: inc/field/floatfield.class.php:155 -#, php-format -msgid "Specific format does not match: %s" -msgstr "Specific format does not match: %s" - -#: inc/field/textfield.class.php:155 -#, php-format -msgid "The text is too short (minimum %d characters): %s" -msgstr "The text is too short (minimum %d characters): %s" - -#: inc/field/textfield.class.php:160 -#, php-format -msgid "The text is too long (maximum %d characters): %s" -msgstr "The text is too long (maximum %d characters): %s" - -#: inc/field/textfield.class.php:168 -msgid "Text" -msgstr "Text" - -#: inc/field/textfield.class.php:212 inc/field/floatfield.class.php:234 -#: inc/questionregex.class.php:62 entrée standard:42 -msgid "Regular expression" -msgstr "Regular expression" - -#: inc/field/textfield.class.php:217 inc/field/floatfield.class.php:239 -msgid "Range" -msgstr "Range" - -#: inc/field/textfield.class.php:223 inc/field/floatfield.class.php:245 -msgid "Additional validation" -msgstr "Additional validation" - -#: inc/field/radiosfield.class.php:109 -msgid "Radios" -msgstr "Radios" - -#: inc/field/radiosfield.class.php:115 inc/field/glpiselectfield.class.php:93 -#: inc/field/fieldsfield.class.php:512 inc/field/checkboxesfield.class.php:229 -msgid "The field value is required:" -msgstr "The field value is required:" - -#: inc/field/radiosfield.class.php:193 inc/field/selectfield.class.php:104 -#: inc/field/datetimefield.class.php:118 inc/field/actorfield.class.php:257 -#: inc/field/checkboxesfield.class.php:175 inc/field/floatfield.class.php:124 -#: inc/field/datefield.class.php:115 -#, php-format -msgid "A required field is empty: %s" -msgstr "A required field is empty: %s" - -#: inc/field/integerfield.class.php:59 -#, php-format -msgid "This is not an integer: %s" -msgstr "This is not an integer: %s" - -#: inc/field/integerfield.class.php:85 inc/field/floatfield.class.php:166 -#, php-format -msgid "The following number must be greater than %d: %s" -msgstr "The following number must be greater than %d: %s" - -#: inc/field/integerfield.class.php:91 inc/field/floatfield.class.php:172 -#, php-format -msgid "The following number must be lower than %d: %s" -msgstr "The following number must be lower than %d: %s" - -#: inc/field/integerfield.class.php:101 -msgid "Integer" -msgstr "Integer" - -#: inc/field/undefinedfield.class.php:44 -msgid "Undefined" -msgstr "Undefined" - -#: inc/field/ipfield.class.php:122 -msgid "IP address" -msgid_plural "IP addresses" -msgstr[0] "IP address" -msgstr[1] "IP addresses" - -#: inc/field/urgencyfield.class.php:85 inc/abstractitiltarget.class.php:994 -msgid "Urgency" -msgstr "Urgency" - -#: inc/field/urgencyfield.class.php:119 -msgctxt "urgency" -msgid "Very high" -msgstr "Very high" - -#: inc/field/urgencyfield.class.php:120 -msgctxt "urgency" -msgid "High" -msgstr "High" - -#: inc/field/urgencyfield.class.php:121 -msgctxt "urgency" -msgid "Medium" -msgstr "Medium" - -#: inc/field/urgencyfield.class.php:122 -msgctxt "urgency" -msgid "Low" -msgstr "Low" - -#: inc/field/urgencyfield.class.php:123 -msgctxt "urgency" -msgid "Very low" -msgstr "Very low" - -#: inc/field/tagfield.class.php:51 -msgid "Warning: Tag plugin is disabled or missing" -msgstr "Warning: Tag plugin is disabled or missing" - -#: inc/field/tagfield.class.php:197 -msgid "Tag" -msgid_plural "Tags" -msgstr[0] "Tag" -msgstr[1] "Tags" - -#: inc/field/glpiselectfield.class.php:78 entrée standard:38 -msgid "GLPI object" -msgid_plural "GLPI objects" -msgstr[0] "GLPI object" -msgstr[1] "GLPI objects" - -#: inc/field/hostnamefield.class.php:115 -msgid "Hostname" -msgid_plural "Hostnames" -msgstr[0] "Hostname" -msgstr[1] "Hostnames" - -#: inc/field/timefield.class.php:129 -msgid "Time" -msgstr "Time" - -#: inc/field/emailfield.class.php:88 -#, php-format -msgid "This is not a valid e-mail: %s" -msgstr "This is not a valid e-mail: %s" - -#: inc/field/emailfield.class.php:99 -msgid "Email" -msgid_plural "Emails" -msgstr[0] "Email" -msgstr[1] "Emails" - -#: inc/field/selectfield.class.php:97 -msgid "Select" -msgstr "Select" - -#: inc/field/datetimefield.class.php:139 -msgid "Date & time" -msgstr "Date & time" - -#: inc/field/actorfield.class.php:83 -msgid "Actor" -msgid_plural "Actors" -msgstr[0] "Actor" -msgstr[1] "Actors" - -#: inc/field/actorfield.class.php:267 -#, php-format -msgid "Invalid value: %s" -msgstr "Invalid value: %s" - -#: inc/field/actorfield.class.php:290 -#, php-format -msgid "User not found or invalid email address: %s" -msgstr "User not found or invalid email address: %s" - -#: inc/field/filefield.class.php:105 -msgid "No attached document" -msgstr "No attached document" - -#: inc/field/filefield.class.php:114 inc/field/filefield.class.php:252 -#: inc/field/filefield.class.php:259 -msgid "Attached document" -msgstr "Attached document" - -#: inc/field/filefield.class.php:157 -#, php-format -msgid "A required file is missing: %s" -msgstr "A required file is missing: %s" - -#: inc/field/filefield.class.php:174 -msgid "File" -msgstr "File" - -#: inc/field/multiselectfield.class.php:86 -msgid "Multiselect" -msgstr "Multiselect" - -#: inc/field/fieldsfield.class.php:154 -msgid "Warning: Additional Fields plugin is disabled or missing" -msgstr "Warning: Additional Fields plugin is disabled or missing" - -#: inc/field/fieldsfield.class.php:167 -msgid "Block" -msgstr "Block" - -#: inc/field/fieldsfield.class.php:171 inc/targetticket.class.php:339 -msgid "Field" -msgstr "Field" - -#: inc/field/fieldsfield.class.php:253 -msgid "show" -msgstr "show" - -#: inc/field/fieldsfield.class.php:389 -#, php-format -msgid "Field '%1$s' type not implemented yet!" -msgstr "Field '%1$s' type not implemented yet!" - -#: inc/field/fieldsfield.class.php:466 -msgid "Some numeric fields contains non numeric values" -msgstr "Some numeric fields contains non numeric values" - -#: inc/field/fieldsfield.class.php:471 -msgid "Some URL fields contains invalid links" -msgstr "Some URL fields contains invalid links" - -#: inc/field/fieldsfield.class.php:565 -msgid "Additionnal fields" -msgstr "Additionnal fields" - -#: inc/field/checkboxesfield.class.php:117 -msgid "Checkboxes" -msgstr "Checkboxes" - -#: inc/field/checkboxesfield.class.php:211 -#, php-format -msgid "The following question needs at least %d answers" -msgstr "The following question needs at least %d answers" - -#: inc/field/checkboxesfield.class.php:217 -#, php-format -msgid "The following question does not accept more than %d answers" -msgstr "The following question does not accept more than %d answers" - -#: inc/field/checkboxesfield.class.php:289 -msgid "Range min" -msgstr "Range min" - -#: inc/field/checkboxesfield.class.php:290 -msgid "Range max" -msgstr "Range max" - -#: inc/field/requesttypefield.class.php:86 inc/targetticket.class.php:1099 -msgid "Request type" -msgstr "Request type" - -#: inc/field/floatfield.class.php:141 -#, php-format -msgid "This is not a number: %s" -msgstr "This is not a number: %s" - -#: inc/field/floatfield.class.php:182 -msgid "Float" -msgstr "Float" - -#: inc/field/datefield.class.php:136 -msgid "Date" -msgstr "Date" - -#: inc/field/descriptionfield.class.php:105 inc/form.class.php:165 -#: inc/question.class.php:166 entrée standard:82 standard:52 standard:113 -msgid "Description" -msgstr "Description" - -#: inc/field/descriptionfield.class.php:112 -msgid "A description field should have a description:" -msgstr "A description field should have a description:" - -#: inc/field/hiddenfield.class.php:95 -msgid "Hidden field" -msgid_plural "Hidden fields" -msgstr[0] "Hidden field" -msgstr[1] "Hidden fields" - -#: inc/condition.class.php:65 -msgid "Condition" -msgid_plural "Conditions" -msgstr[0] "Condition" -msgstr[1] "Conditions" - -#: inc/condition.class.php:104 -msgid "is visible" -msgstr "is visible" - -#: inc/condition.class.php:105 -msgid "is not visible" -msgstr "is not visible" - -#: inc/condition.class.php:106 -msgid "regular expression matches" -msgstr "regular expression matches" - -#: inc/condition.class.php:117 -msgid "Always displayed" -msgstr "Always displayed" - -#: inc/condition.class.php:118 -msgid "Hidden unless" -msgstr "Hidden unless" - -#: inc/condition.class.php:119 -msgid "Displayed unless" -msgstr "Displayed unless" - -#: inc/condition.class.php:179 inc/target_actor.class.php:215 -#: inc/form_language.class.php:540 inc/form_validator.class.php:379 -#: inc/targetproblem.class.php:540 inc/questionrange.class.php:196 -#: inc/form.class.php:1844 inc/targetchange.class.php:303 -#: inc/section.class.php:379 inc/restrictedformcriteria.class.php:200 -#: inc/question.class.php:828 inc/questionparameter/range.class.php:202 -#: inc/questionregex.class.php:185 inc/questiondependency.class.php:196 -#: inc/item_targetticket.class.php:154 inc/targetticket.class.php:1408 -#, php-format -msgid "Failed to add or update the %1$s %2$s" -msgstr "Failed to add or update the %1$s %2$s" - -#: inc/condition.class.php:201 inc/target_actor.class.php:236 -#: inc/form_language.class.php:556 inc/form_validator.class.php:403 -#: inc/targetproblem.class.php:375 inc/questionrange.class.php:131 -#: inc/form.class.php:1535 inc/targetchange.class.php:148 -#: inc/section.class.php:404 inc/restrictedformcriteria.class.php:226 -#: inc/question.class.php:877 inc/questionparameter/range.class.php:137 -#: inc/questionregex.class.php:120 inc/questiondependency.class.php:211 -#: inc/item_targetticket.class.php:64 inc/targetticket.class.php:1447 -#, php-format -msgid "Cannot export an empty object: %s" -msgstr "Cannot export an empty object: %s" - -#: inc/condition.class.php:269 -msgid "Conditions" -msgstr "Conditions" - -#: inc/linker.class.php:78 -msgid "Importing" -msgstr "Importing" - -#: inc/linker.class.php:80 -msgid "Import in progress" -msgstr "Import in progress" - -#: inc/issue.class.php:43 -msgid "Issue" -msgid_plural "Issues" -msgstr[0] "Issue" -msgstr[1] "Issues" - -#: inc/issue.class.php:56 -msgid "Update issue data from tickets and form answers" -msgstr "Update issue data from tickets and form answers" - -#: inc/issue.class.php:392 -msgid "Satisfaction survey expired" -msgstr "Satisfaction survey expired" - -#: inc/issue.class.php:521 inc/form_language.class.php:213 -#: inc/form.class.php:156 inc/form.class.php:2148 entrée standard:52 -#: standard:49 standard:57 standard:38 standard:39 -msgid "Name" -msgstr "Name" - -#: inc/issue.class.php:534 inc/formanswer.class.php:199 -#: inc/formanswer.class.php:273 inc/targetproblem.class.php:623 -#: inc/form.class.php:147 inc/targetchange.class.php:334 -#: inc/section.class.php:95 inc/question.class.php:156 -#: inc/targetticket.class.php:178 -msgid "ID" -msgstr "ID" - -#: inc/issue.class.php:543 inc/form.class.php:503 inc/form.class.php:2157 -#: entrée standard:65 -msgid "Type" -msgid_plural "Types" -msgstr[0] "Type" -msgstr[1] "Types" - -#: inc/issue.class.php:556 inc/formanswer.class.php:260 -msgid "Status" -msgstr "Status" - -#: inc/issue.class.php:568 -msgid "Opening date" -msgstr "Opening date" - -#: inc/issue.class.php:577 -msgid "Last update" -msgstr "Last update" - -#: inc/issue.class.php:586 inc/abstracttarget.class.php:518 -msgid "Entity" -msgid_plural "Entities" -msgstr[0] "Entity" -msgstr[1] "Entities" - -#: inc/issue.class.php:596 inc/notificationtargetformanswer.class.php:79 -#: inc/target_actor.class.php:83 inc/formanswer.class.php:219 -#: inc/formanswer.class.php:618 inc/abstractitiltarget.class.php:1724 -msgid "Requester" -msgid_plural "Requesters" -msgstr[0] "Requester" -msgstr[1] "Requesters" - -#: inc/issue.class.php:614 inc/formanswer.class.php:229 -msgid "Form approver" -msgstr "Form approver" - -#: inc/issue.class.php:630 inc/formanswer.class.php:544 -#: inc/formanswer.class.php:551 inc/formanswer.class.php:633 -#: inc/form_language.class.php:227 -msgid "Comment" -msgstr "Comment" - -#: inc/issue.class.php:642 -msgid "Ticket approver" -msgstr "Ticket approver" - -#: inc/issue.class.php:676 -msgid "Technician" -msgstr "Technician" - -#: inc/issue.class.php:708 -msgid "Technician group" -msgstr "Technician group" - -#: inc/issue.class.php:741 inc/formanswer.class.php:249 -msgid "Form approver group" -msgstr "Form approver group" - -#: inc/issue.class.php:853 -#, php-format -msgid "%1$s %2$s" -msgstr "%1$s %2$s" - -#: inc/issue.class.php:1115 inc/filter/itilcategoryfilter.class.php:56 -#: hook.php:629 -msgid "All" -msgstr "All" - -#: inc/issue.class.php:1121 hook.php:630 -msgid "New" -msgstr "New" - -#: inc/issue.class.php:1127 hook.php:631 -msgid "Assigned" -msgstr "Assigned" - -#: inc/issue.class.php:1133 inc/formanswer.class.php:76 -#: inc/form_validator.class.php:69 hook.php:632 -msgid "Waiting" -msgstr "Waiting" - -#: inc/issue.class.php:1139 hook.php:633 -msgid "To validate" -msgstr "To validate" - -#: inc/issue.class.php:1145 hook.php:634 -msgid "Solved" -msgstr "Solved" - -#: inc/issue.class.php:1151 hook.php:635 -msgid "Closed" -msgstr "Closed" - -#: inc/category.class.php:50 hook.php:72 -msgid "Form category" -msgid_plural "Form categories" -msgstr[0] "Form category" -msgstr[1] "Form categories" - -#: inc/category.class.php:72 -msgid "Knowbase category" -msgstr "Knowbase category" - -#: inc/category.class.php:78 -msgid "As child of" -msgstr "As child of" - -#: inc/notificationtargetformanswer.class.php:43 -msgid "The form as been saved" -msgstr "The form as been saved" - -#: inc/notificationtargetformanswer.class.php:44 install/install.php:408 -msgid "A form need to be validate" -msgstr "A form need to be validate" - -#: inc/notificationtargetformanswer.class.php:45 install/install.php:414 -msgid "The form is refused" -msgstr "The form is refused" - -#: inc/notificationtargetformanswer.class.php:46 install/install.php:420 -msgid "The form is accepted" -msgstr "The form is accepted" - -#: inc/notificationtargetformanswer.class.php:47 install/install.php:426 -msgid "The form is deleted" -msgstr "The form is deleted" - -#: inc/notificationtargetformanswer.class.php:77 -msgid "Form #" -msgstr "Form #" - -#: inc/notificationtargetformanswer.class.php:78 -msgid "Form name" -msgstr "Form name" - -#: inc/notificationtargetformanswer.class.php:80 -msgctxt "tag" -msgid "Validator" -msgstr "Validator" - -#: inc/notificationtargetformanswer.class.php:81 inc/formanswer.class.php:240 -msgid "Creation date" -msgstr "Creation date" - -#: inc/notificationtargetformanswer.class.php:82 -msgid "Full form answers" -msgstr "Full form answers" - -#: inc/notificationtargetformanswer.class.php:83 -msgid "Refused comment" -msgstr "Refused comment" - -#: inc/notificationtargetformanswer.class.php:84 -msgid "Validation link" -msgstr "Validation link" - -#: inc/notificationtargetformanswer.class.php:85 -msgid "Request #" -msgstr "Request #" - -#: inc/notificationtargetformanswer.class.php:97 -msgid "Author" -msgstr "Author" - -#: inc/notificationtargetformanswer.class.php:98 -#: inc/abstractitiltarget.class.php:1289 -msgid "Approver" -msgstr "Approver" - -#: inc/target_actor.class.php:66 inc/abstractitiltarget.class.php:2048 -msgid "Form author" -msgstr "Form author" - -#: inc/target_actor.class.php:67 inc/abstractitiltarget.class.php:2051 -msgid "Form validator" -msgstr "Form validator" - -#: inc/target_actor.class.php:68 -msgid "Specific person" -msgstr "Specific person" - -#: inc/target_actor.class.php:69 inc/abstractitiltarget.class.php:2061 -msgid "Person from the question" -msgstr "Person from the question" - -#: inc/target_actor.class.php:70 -msgid "Specific group" -msgstr "Specific group" - -#: inc/target_actor.class.php:71 inc/abstractitiltarget.class.php:2072 -msgid "Group from the question" -msgstr "Group from the question" - -#: inc/target_actor.class.php:72 -msgid "Group from an object" -msgstr "Group from an object" - -#: inc/target_actor.class.php:73 -msgid "Tech group from an object" -msgstr "Tech group from an object" - -#: inc/target_actor.class.php:74 -msgid "Specific supplier" -msgstr "Specific supplier" - -#: inc/target_actor.class.php:75 inc/abstractitiltarget.class.php:2101 -msgid "Supplier from the question" -msgstr "Supplier from the question" - -#: inc/target_actor.class.php:76 inc/abstractitiltarget.class.php:2090 -msgid "Actors from the question" -msgstr "Actors from the question" - -#: inc/target_actor.class.php:77 inc/abstractitiltarget.class.php:2105 -msgid "Form author's supervisor" -msgstr "Form author's supervisor" - -#: inc/target_actor.class.php:84 -msgid "Observer" -msgstr "Observer" - -#: inc/target_actor.class.php:85 inc/abstractitiltarget.class.php:1738 -msgid "Assigned to" -msgstr "Assigned to" - -#: inc/target_actor.class.php:91 -msgid "Target actor" -msgid_plural "Target actors" -msgstr[0] "Target actor" -msgstr[1] "Target actors" - -#: inc/target_actor.class.php:97 inc/target_actor.class.php:113 -#: inc/target_actor.class.php:122 -msgid "Bad request while adding an actor." -msgstr "Bad request while adding an actor." - -#: inc/target_actor.class.php:179 -#, php-format -msgid "Failed to find a user: %1$s" -msgstr "Failed to find a user: %1$s" - -#: inc/target_actor.class.php:188 -#, php-format -msgid "Failed to find a group: %1$s" -msgstr "Failed to find a group: %1$s" - -#: inc/target_actor.class.php:197 -#, php-format -msgid "Failed to find a supplier: %1$s" -msgstr "Failed to find a supplier: %1$s" - -#: inc/formanswer.class.php:77 inc/form_validator.class.php:71 -msgid "Refused" -msgstr "Refused" - -#: inc/formanswer.class.php:78 inc/form_validator.class.php:70 -msgid "Accepted" -msgstr "Accepted" - -#: inc/formanswer.class.php:184 -msgid "Form answer" -msgid_plural "Form answers" -msgstr[0] "Form answer" -msgstr[1] "Form answers" - -#: inc/formanswer.class.php:529 -msgid "Print this form" -msgstr "Print this form" - -#: inc/formanswer.class.php:554 -msgid "Form accepted by validator." -msgstr "Form accepted by validator." - -#: inc/formanswer.class.php:556 -msgid "Form successfully saved." -msgstr "Form successfully saved." - -#: inc/formanswer.class.php:626 inc/formaccesstype.class.php:122 -msgid "Save" -msgstr "Save" - -#: inc/formanswer.class.php:638 -msgid "Required if refused" -msgstr "Required if refused" - -#: inc/formanswer.class.php:644 -msgid "Refuse" -msgstr "Refuse" - -#: inc/formanswer.class.php:652 -msgid "Edit answers" -msgstr "Edit answers" - -#: inc/formanswer.class.php:658 -msgid "Cancel edition" -msgstr "Cancel edition" - -#: inc/formanswer.class.php:665 -msgid "Accept" -msgstr "Accept" - -#: inc/formanswer.class.php:688 -msgid "Refused comment is required!" -msgstr "Refused comment is required!" - -#: inc/formanswer.class.php:762 -msgid "You are not the validator of these answers" -msgstr "You are not the validator of these answers" - -#: inc/formanswer.class.php:895 -#, php-format -msgid "Item sucessfully added: %1$s (%2$s: %3$s)" -msgstr "Item sucessfully added: %1$s (%2$s: %3$s)" - -#: inc/formanswer.class.php:977 inc/formanswer.class.php:979 -msgid "Form data" -msgstr "Form data" - -#: inc/formanswer.class.php:1105 inc/formanswer.class.php:1157 -msgid "Cannot generate targets!" -msgstr "Cannot generate targets!" - -#: inc/formanswer.class.php:1281 -msgid "No turing test set" -msgstr "No turing test set" - -#: inc/formanswer.class.php:1286 -msgid "You failed the Turing test" -msgstr "You failed the Turing test" - -#: inc/formanswer.class.php:1326 -msgid "You must select validator!" -msgstr "You must select validator!" - -#: inc/common.class.php:229 -msgid "You cannot delete this issue. Maybe it is taken into account." -msgstr "You cannot delete this issue. Maybe it is taken into account." - -#: inc/common.class.php:234 -msgid "Failed to delete this issue. An internal error occured." -msgstr "Failed to delete this issue. An internal error occured." - -#: inc/common.class.php:780 -msgid "Seek assistance" -msgstr "Seek assistance" - -#: inc/common.class.php:785 -msgid "My requests for assistance" -msgstr "My requests for assistance" - -#: inc/common.class.php:815 -msgid "Consult feeds" -msgstr "Consult feeds" - -#: inc/formaccesstype.class.php:39 inc/formaccesstype.class.php:64 -msgid "Access type" -msgid_plural "Access types" -msgstr[0] "Access type" -msgstr[1] "Access types" - -#: inc/formaccesstype.class.php:78 -msgid "Link to the form" -msgstr "Link to the form" - -#: inc/formaccesstype.class.php:91 -msgid "Please activate the form to view the link" -msgstr "Please activate the form to view the link" - -#: inc/formaccesstype.class.php:99 -msgid "Enable captcha" -msgstr "Enable captcha" - -#: inc/formaccesstype.class.php:109 -msgid "Restricted to" -msgstr "Restricted to" - -#: inc/form_language.class.php:51 -msgid "Form language" -msgid_plural "Form languages" -msgstr[0] "Form language" -msgstr[1] "Form languages" - -#: inc/form_language.class.php:72 -msgid "Translation" -msgid_plural "Translations" -msgstr[0] "Translation" -msgstr[1] "Translations" - -#: inc/form_language.class.php:111 inc/form.class.php:1076 -#: inc/form.class.php:1201 inc/abstracttarget.class.php:161 -#: inc/abstractitiltarget.class.php:1544 -msgid "The name cannot be empty!" -msgstr "The name cannot be empty!" - -#: inc/form_language.class.php:119 -msgid "The language must be associated to a form!" -msgstr "The language must be associated to a form!" - -#: inc/form_language.class.php:249 -msgid "Add a translation" -msgstr "Add a translation" - -#: inc/form_language.class.php:283 js/scripts.js:1156 -msgid "Update a translation" -msgstr "Update a translation" - -#: inc/form_language.class.php:313 inc/form_language.class.php:315 -msgid "New translation" -msgstr "New translation" - -#: inc/form_language.class.php:318 -msgid "Filter list" -msgstr "Filter list" - -#: inc/form_language.class.php:323 inc/form_language.class.php:413 -msgid "No translation found" -msgstr "No translation found" - -#: inc/form_language.class.php:328 -msgid "Do you want to delete the selected items?" -msgstr "Do you want to delete the selected items?" - -#: inc/form_language.class.php:337 inc/form_language.class.php:376 -#: inc/form.class.php:527 inc/abstractitiltarget.class.php:1629 -msgid "Delete" -msgstr "Delete" - -#: inc/form_language.class.php:347 -msgid "Original string" -msgstr "Original string" - -#: inc/form_language.class.php:399 -msgid "Add a new language" -msgstr "Add a new language" - -#: inc/form_language.class.php:432 inc/form_language.class.php:464 -#: inc/form.class.php:192 entrée standard:72 -msgid "Language" -msgstr "Language" - -#: inc/form_validator.class.php:68 inc/targetticket.class.php:97 -#: inc/abstractitiltarget.class.php:178 -msgid "None" -msgstr "None" - -#: inc/form_validator.class.php:76 -msgid "Validator" -msgid_plural "Validators" -msgstr[0] "Validator" -msgstr[1] "Validators" - -#: inc/form_validator.class.php:114 -msgid "Need validaton?" -msgstr "Need validaton?" - -#: inc/form_validator.class.php:118 inc/abstractitiltarget.class.php:2042 -msgid "No" -msgstr "No" - -#: inc/form_validator.class.php:295 inc/targetproblem.class.php:146 -#: inc/entityconfig.class.php:411 inc/targetchange.class.php:483 -#: inc/targetticket.class.php:316 inc/targetticket.class.php:351 -#: inc/abstractitiltarget.class.php:2031 -msgctxt "button" -msgid "Save" -msgstr "Save" - -#: inc/form_validator.class.php:709 inc/abstractitiltarget.class.php:1269 -msgid "Validation" -msgstr "Validation" - -#: inc/form_validator.class.php:711 -msgid "Choose a validator" -msgstr "Choose a validator" - -#: inc/targetproblem.class.php:42 entrée standard:43 -msgid "Target problem" -msgid_plural "Target problems" -msgstr[0] "Target problem" -msgstr[1] "Target problems" - -#: inc/targetproblem.class.php:108 inc/targetproblem.class.php:578 -#: inc/targetchange.class.php:104 inc/targetchange.class.php:440 -#: inc/targetticket.class.php:133 inc/targetticket.class.php:236 -msgid "Properties" -msgstr "Properties" - -#: inc/targetproblem.class.php:522 inc/targetchange.class.php:285 -#: inc/targetticket.class.php:1390 -#, php-format -msgid "" -"Failed to add or update the %1$s %2$s: a question is missing and is used in " -"a parameter of the target" -msgstr "" -"Failed to add or update the %1$s %2$s: a question is missing and is used in " -"a parameter of the target" - -#: inc/targetproblem.class.php:579 inc/targetchange.class.php:105 -#: inc/targetticket.class.php:134 inc/abstractitiltarget.class.php:1171 -msgid "Actors" -msgstr "Actors" - -#: inc/targetproblem.class.php:632 entrée standard:48 -msgid "Problem title" -msgstr "Problem title" - -#: inc/targetproblem.class.php:642 inc/targetchange.class.php:353 -#: inc/targetticket.class.php:197 -msgid "Content" -msgstr "Content" - -#: inc/targetproblem.class.php:652 inc/targetchange.class.php:363 -msgid "Impact" -msgstr "Impact" - -#: inc/targetproblem.class.php:662 entrée standard:56 -msgid "Cause" -msgstr "Cause" - -#: inc/targetproblem.class.php:672 entrée standard:58 -msgid "Symptom" -msgstr "Symptom" - -#: inc/entityconfig.class.php:90 inc/entityconfig.class.php:99 -#: inc/entityconfig.class.php:107 inc/entityconfig.class.php:115 -#: inc/entityconfig.class.php:123 inc/entityconfig.class.php:131 -#: inc/entityconfig.class.php:139 inc/entityconfig.class.php:147 -#: inc/entityconfig.class.php:155 -msgid "Inheritance of the parent entity" -msgstr "Inheritance of the parent entity" - -#: inc/entityconfig.class.php:91 -msgid "GLPi's helpdesk" -msgstr "GLPi's helpdesk" - -#: inc/entityconfig.class.php:92 -msgid "Service catalog simplified" -msgstr "Service catalog simplified" - -#: inc/entityconfig.class.php:93 -msgid "Service catalog extended" -msgstr "Service catalog extended" - -#: inc/entityconfig.class.php:100 -msgid "All available forms" -msgstr "All available forms" - -#: inc/entityconfig.class.php:101 -msgid "Only default forms" -msgstr "Only default forms" - -#: inc/entityconfig.class.php:108 -msgid "Popularity sort" -msgstr "Popularity sort" - -#: inc/entityconfig.class.php:109 -msgid "Alphabetic sort" -msgstr "Alphabetic sort" - -#: inc/entityconfig.class.php:116 -msgid "Merged with Forms" -msgstr "Merged with Forms" - -#: inc/entityconfig.class.php:117 -msgid "Distinct menu entry" -msgstr "Distinct menu entry" - -#: inc/entityconfig.class.php:124 inc/entityconfig.class.php:132 -#: inc/entityconfig.class.php:140 inc/entityconfig.class.php:148 -#: inc/form.class.php:285 entrée standard:100 -msgid "Visible" -msgstr "Visible" - -#: inc/entityconfig.class.php:125 inc/entityconfig.class.php:133 -#: inc/entityconfig.class.php:141 inc/entityconfig.class.php:149 -msgid "Hidden" -msgstr "Hidden" - -#: inc/entityconfig.class.php:156 -msgid "Variable height" -msgstr "Variable height" - -#: inc/entityconfig.class.php:157 -msgid "Uniform height" -msgstr "Uniform height" - -#: inc/entityconfig.class.php:253 -msgid "Helpdesk" -msgstr "Helpdesk" - -#: inc/entityconfig.class.php:261 inc/entityconfig.class.php:425 entrée -#: standard:44 -msgid "Helpdesk mode" -msgstr "Helpdesk mode" - -#: inc/entityconfig.class.php:272 -msgid "Default Form list mode" -msgstr "Default Form list mode" - -#: inc/entityconfig.class.php:290 inc/entityconfig.class.php:435 -msgid "Sort order" -msgstr "Sort order" - -#: inc/entityconfig.class.php:306 inc/entityconfig.class.php:445 -msgid "Knowledge base" -msgstr "Knowledge base" - -#: inc/entityconfig.class.php:321 -msgid "Search" -msgstr "Search" - -#: inc/entityconfig.class.php:337 -msgid "Counters dashboard" -msgstr "Counters dashboard" - -#: inc/entityconfig.class.php:353 -msgid "Header message" -msgstr "Header message" - -#: inc/entityconfig.class.php:369 -msgid "Search issue" -msgstr "Search issue" - -#: inc/entityconfig.class.php:385 -msgid "Tile design" -msgstr "Tile design" - -#: inc/entityconfig.class.php:397 inc/entityconfig.class.php:475 -#: inc/form.class.php:239 entrée standard:84 -msgid "Header" -msgid_plural "Headers" -msgstr[0] "Header" -msgstr[1] "Headers" - -#: inc/entityconfig.class.php:455 -msgid "Display search field" -msgstr "Display search field" - -#: inc/entityconfig.class.php:465 -msgid "Display header" -msgstr "Display header" - -#: inc/questionrange.class.php:52 inc/questionparameter/range.class.php:56 -msgid "Question range" -msgid_plural "Question ranges" -msgstr[0] "Question range" -msgstr[1] "Question ranges" - -#: inc/questionrange.class.php:62 inc/questionparameter/range.class.php:66 -msgid "Minimum range" -msgstr "Minimum range" - -#: inc/questionrange.class.php:71 inc/questionparameter/range.class.php:75 -msgid "maximum range" -msgstr "maximum range" - -#: inc/form.class.php:66 inc/form.class.php:432 -msgid "Public access" -msgstr "Public access" - -#: inc/form.class.php:67 inc/form.class.php:436 -msgid "Private access" -msgstr "Private access" - -#: inc/form.class.php:68 inc/form.class.php:440 -msgid "Restricted access" -msgstr "Restricted access" - -#: inc/form.class.php:122 -msgid "Answers waiting for validation" -msgstr "Answers waiting for validation" - -#: inc/form.class.php:124 inc/form.class.php:1619 inc/form.class.php:1645 -msgid "Import forms" -msgstr "Import forms" - -#: inc/form.class.php:140 -msgid "Characteristics" -msgstr "Characteristics" - -#: inc/form.class.php:183 -msgid "Recursive" -msgstr "Recursive" - -#: inc/form.class.php:204 -msgid "Homepage" -msgstr "Homepage" - -#: inc/form.class.php:217 -msgid "Access" -msgstr "Access" - -#: inc/form.class.php:248 inc/form.class.php:330 inc/form.class.php:397 entrée -#: standard:54 -msgid "Active" -msgstr "Active" - -#: inc/form.class.php:261 entrée standard:65 -msgid "Icon" -msgstr "Icon" - -#: inc/form.class.php:269 entrée standard:67 -msgid "Icon color" -msgstr "Icon color" - -#: inc/form.class.php:277 entrée standard:80 -msgid "Background color" -msgstr "Background color" - -#: inc/form.class.php:300 inc/form.class.php:341 inc/form.class.php:416 -msgid "Default form" -msgstr "Default form" - -#: inc/form.class.php:329 inc/form.class.php:394 -msgid "Inactive" -msgstr "Inactive" - -#: inc/form.class.php:340 inc/form.class.php:413 -msgid "Not default form" -msgstr "Not default form" - -#: inc/form.class.php:364 inc/form.class.php:448 entrée standard:75 -msgid "All languages" -msgstr "All languages" - -#: inc/form.class.php:502 inc/form.class.php:561 -msgid "Target" -msgid_plural "Targets" -msgstr[0] "Target" -msgstr[1] "Targets" - -#: inc/form.class.php:504 -msgid "Actions" -msgstr "Actions" - -#: inc/form.class.php:544 inc/form.class.php:2145 -msgid "Add a target" -msgstr "Add a target" - -#: inc/form.class.php:564 -msgid "Preview" -msgstr "Preview" - -#: inc/form.class.php:565 -msgid "properties" -msgstr "properties" - -#: inc/form.class.php:884 -msgid "What are you looking for?" -msgstr "What are you looking for?" - -#: inc/form.class.php:893 -#, php-format -msgid "My %1$d last forms (requester)" -msgstr "My %1$d last forms (requester)" - -#: inc/form.class.php:920 -msgid "No form posted yet" -msgstr "No form posted yet" - -#: inc/form.class.php:948 -msgid "All my forms (requester)" -msgstr "All my forms (requester)" - -#: inc/form.class.php:961 -#, php-format -msgid "My %1$d last forms (validator)" -msgstr "My %1$d last forms (validator)" - -#: inc/form.class.php:988 -msgid "No form waiting for validation" -msgstr "No form waiting for validation" - -#: inc/form.class.php:1016 -msgid "All my forms (validator)" -msgstr "All my forms (validator)" - -#: inc/form.class.php:1212 -msgid "Cannot use empty name for form answers. Keeping the previous value." -msgstr "Cannot use empty name for form answers. Keeping the previous value." - -#: inc/form.class.php:1307 -#, php-format -msgid "The question %s is not compatible with public forms" -msgstr "The question %s is not compatible with public forms" - -#: inc/form.class.php:1387 -msgid "Errored duplicate" -msgstr "Errored duplicate" - -#: inc/form.class.php:1398 -msgid "Duplicate" -msgstr "Duplicate" - -#: inc/form.class.php:1445 -msgctxt "button" -msgid "Post" -msgstr "Post" - -#: inc/form.class.php:1463 -#, php-format -msgid "Form duplicated: %s" -msgstr "Form duplicated: %s" - -#: inc/form.class.php:1474 -#, php-format -msgid "Form Transfered: %s" -msgstr "Form Transfered: %s" - -#: inc/form.class.php:1493 -msgid "Back" -msgstr "Back" - -#: inc/form.class.php:1592 -msgid "Upload of JSON files not allowed." -msgstr "Upload of JSON files not allowed." - -#: inc/form.class.php:1595 -msgid "You may allow JSON files right now." -msgstr "You may allow JSON files right now." - -#: inc/form.class.php:1596 -msgctxt "button" -msgid "Create" -msgstr "Create" - -#: inc/form.class.php:1599 inc/form.class.php:1610 -msgid "Please contact your GLPI administrator." -msgstr "Please contact your GLPI administrator." - -#: inc/form.class.php:1600 inc/form.class.php:1611 -msgctxt "button" -msgid "Back" -msgstr "Back" - -#: inc/form.class.php:1603 -msgid "Upload of JSON files not enabled." -msgstr "Upload of JSON files not enabled." - -#: inc/form.class.php:1606 inc/form.class.php:1609 -msgid "You may enable JSON files right now." -msgstr "You may enable JSON files right now." - -#: inc/form.class.php:1607 -msgctxt "button" -msgid "Enable" -msgstr "Enable" - -#: inc/form.class.php:1654 -msgctxt "button" -msgid "Send" -msgstr "Send" - -#: inc/form.class.php:1673 -msgid "Forms import impossible, the file is empty" -msgstr "Forms import impossible, the file is empty" - -#: inc/form.class.php:1677 inc/form.class.php:1681 -msgid "Forms import impossible, the file seems corrupt" -msgstr "Forms import impossible, the file seems corrupt" - -#: inc/form.class.php:1687 -msgid "Forms import impossible, the file was generated with another version" -msgstr "Forms import impossible, the file was generated with another version" - -#: inc/form.class.php:1694 -msgid "" -"The file does not specifies the schema version. It was probably generated " -"with a version older than 2.10. Giving up." -msgstr "" -"The file does not specifies the schema version. It was probably generated " -"with a version older than 2.10. Giving up." - -#: inc/form.class.php:1720 -#, php-format -msgid "Failed to import %s" -msgstr "Failed to import %s" - -#: inc/form.class.php:1725 -#, php-format -msgid "Forms successfully imported from %s" -msgstr "Forms successfully imported from %s" - -#: inc/form.class.php:1788 -#, php-format -msgid "The form %1$s already exists and is in an unmodifiable entity." -msgstr "The form %1$s already exists and is in an unmodifiable entity." - -#: inc/form.class.php:1796 -#, php-format -msgid "You don't have right to update the entity %1$s." -msgstr "You don't have right to update the entity %1$s." - -#: inc/form.class.php:1806 -#, php-format -msgid "The entity %1$s is required for the form %2$s." -msgstr "The entity %1$s is required for the form %2$s." - -#: inc/form.class.php:1888 -msgid "Failed to create JSON document type" -msgstr "Failed to create JSON document type" - -#: inc/form.class.php:1895 -msgid "JSON document type not found" -msgstr "JSON document type not found" - -#: inc/form.class.php:1902 -msgid "Failed to update JSON document type" -msgstr "Failed to update JSON document type" - -#: inc/form.class.php:1922 -msgid "Forms without category" -msgstr "Forms without category" - -#: inc/form.class.php:1943 -msgid "No form available" -msgstr "No form available" - -#: inc/form.class.php:2176 inc/targetticket.class.php:391 -#: inc/abstractitiltarget.class.php:1748 inc/abstractitiltarget.class.php:2031 -msgid "Add" -msgstr "Add" - -#: inc/form.class.php:2194 inc/form.class.php:2217 -msgid "Unsupported target type." -msgstr "Unsupported target type." - -#: inc/form.class.php:2251 -msgid "plugin_formcreator_load_check" -msgstr "plugin_formcreator_load_check" - -#: inc/targetchange.class.php:43 entrée standard:43 -msgid "Target change" -msgid_plural "Target changes" -msgstr[0] "Target change" -msgstr[1] "Target changes" - -#: inc/targetchange.class.php:343 entrée standard:48 -msgid "Change title" -msgstr "Change title" - -#: inc/targetchange.class.php:373 entrée standard:56 -msgid "Control list" -msgstr "Control list" - -#: inc/targetchange.class.php:383 entrée standard:58 -msgid "Deployment plan" -msgstr "Deployment plan" - -#: inc/targetchange.class.php:393 entrée standard:60 -msgid "Backup plan" -msgstr "Backup plan" - -#: inc/targetchange.class.php:403 -msgid "Check list" -msgstr "Check list" - -#: inc/section.class.php:71 entrée standard:53 standard:44 -msgid "Section" -msgid_plural "Sections" -msgstr[0] "Section" -msgstr[1] "Sections" - -#: inc/section.class.php:123 inc/section.class.php:164 -#: inc/question.class.php:312 -msgid "The title is required" -msgstr "The title is required" - -#: inc/restrictedformcriteria.class.php:179 -#, php-format -msgid "Failed to find %1$s %2$s" -msgstr "Failed to find %1$s %2$s" - -#: inc/question.class.php:70 inc/abstractitiltarget.class.php:1082 entrée -#: standard:41 -msgid "Question" -msgid_plural "Questions" -msgstr[0] "Question" -msgstr[1] "Questions" - -#: inc/question.class.php:228 entrée standard:37 -msgid "Count of conditions" -msgstr "Count of conditions" - -#: inc/question.class.php:320 -msgid "The field type is required" -msgstr "The field type is required" - -#: inc/question.class.php:327 -msgid "The section is required" -msgstr "The section is required" - -#: inc/question.class.php:339 -#, php-format -msgid "Field type %1$s is not available for question %2$s." -msgstr "Field type %1$s is not available for question %2$s." - -#: inc/question.class.php:353 -msgid "This type of question is not compatible with public forms." -msgstr "This type of question is not compatible with public forms." - -#: inc/question.class.php:362 -msgid "This type of question requires parameters" -msgstr "This type of question requires parameters" - -#: inc/question.class.php:368 -msgid "A parameter is missing for this question type" -msgstr "A parameter is missing for this question type" - -#: inc/question.class.php:1178 -msgid "Service levels" -msgstr "Service levels" - -#: inc/question.class.php:1179 inc/abstractitiltarget.class.php:805 -msgid "SLA" -msgstr "SLA" - -#: inc/question.class.php:1180 inc/abstractitiltarget.class.php:878 -msgid "OLA" -msgstr "OLA" - -#: inc/question.class.php:1197 inc/question.class.php:1238 -#: inc/question.class.php:1241 -msgid "Assets" -msgstr "Assets" - -#: inc/question.class.php:1211 hook.php:643 hook.php:660 -msgid "Assistance" -msgstr "Assistance" - -#: inc/question.class.php:1217 -msgid "Management" -msgstr "Management" - -#: inc/question.class.php:1226 -msgid "Tools" -msgstr "Tools" - -#: inc/question.class.php:1227 -msgid "Notes" -msgstr "Notes" - -#: inc/question.class.php:1228 -msgid "RSS feed" -msgstr "RSS feed" - -#: inc/question.class.php:1230 -msgid "Administration" -msgstr "Administration" - -#: inc/question.class.php:1238 inc/question.class.php:1241 -msgid "Plugin" -msgid_plural "Plugins" -msgstr[0] "Plugin" -msgstr[1] "Plugins" - -#: inc/abstractquestionparameter.class.php:92 -msgid "Parameter" -msgstr "Parameter" - -#: inc/abstractquestionparameter.class.php:99 -msgid "Field name" -msgstr "Field name" - -#: inc/abstracttarget.class.php:96 -msgid "Current active entity" -msgstr "Current active entity" - -#: inc/abstracttarget.class.php:97 -msgid "Default requester user's entity" -msgstr "Default requester user's entity" - -#: inc/abstracttarget.class.php:98 -msgid "First dynamic requester user's entity (alphabetical)" -msgstr "First dynamic requester user's entity (alphabetical)" - -#: inc/abstracttarget.class.php:99 -msgid "Last dynamic requester user's entity (alphabetical)" -msgstr "Last dynamic requester user's entity (alphabetical)" - -#: inc/abstracttarget.class.php:100 -msgid "The form entity" -msgstr "The form entity" - -#: inc/abstracttarget.class.php:101 -msgid "Default entity of the validator" -msgstr "Default entity of the validator" - -#: inc/abstracttarget.class.php:102 -msgid "Specific entity" -msgstr "Specific entity" - -#: inc/abstracttarget.class.php:103 -msgid "Default entity of a user type question answer" -msgstr "Default entity of a user type question answer" - -#: inc/abstracttarget.class.php:104 -msgid "From a GLPI object > Entity type question answer" -msgstr "From a GLPI object > Entity type question answer" - -#: inc/abstracttarget.class.php:115 -msgid "Always generated" -msgstr "Always generated" - -#: inc/abstracttarget.class.php:116 -msgid "Disabled unless" -msgstr "Disabled unless" - -#: inc/abstracttarget.class.php:117 -msgid "Generated unless" -msgstr "Generated unless" - -#: inc/abstracttarget.class.php:128 -msgid "A target must be associated to a form." -msgstr "A target must be associated to a form." - -#: inc/abstracttarget.class.php:133 -msgid "A target must be associated to an existing form." -msgstr "A target must be associated to an existing form." - -#: inc/abstracttarget.class.php:138 -msgid "Name is required." -msgstr "Name is required." - -#: inc/abstracttarget.class.php:503 -msgid "Destination entity" -msgstr "Destination entity" - -#: inc/abstracttarget.class.php:519 -msgid "User type question" -msgstr "User type question" - -#: inc/abstracttarget.class.php:520 -msgid "Entity type question" -msgstr "Entity type question" - -#: inc/filter/itilcategoryfilter.class.php:52 -#: inc/filter/itilcategoryfilter.class.php:54 -msgid "Request categories" -msgstr "Request categories" - -#: inc/filter/itilcategoryfilter.class.php:53 -#: inc/filter/itilcategoryfilter.class.php:54 -msgid "Incident categories" -msgstr "Incident categories" - -#: inc/filter/itilcategoryfilter.class.php:55 -msgid "Change categories" -msgstr "Change categories" - -#: inc/questionregex.class.php:52 -msgid "Question regular expression" -msgid_plural "Question regular expressions" -msgstr[0] "Question regular expression" -msgstr[1] "Question regular expressions" - -#: inc/questiondependency.class.php:66 -msgid "Question dependency" -msgid_plural "Question dependencies" -msgstr[0] "Question dependency" -msgstr[1] "Question dependencies" - -#: inc/answer.class.php:66 entrée standard:43 -msgid "Answer" -msgid_plural "Answers" -msgstr[0] "Answer" -msgstr[1] "Answers" - -#: inc/item_targetticket.class.php:52 -msgid "Composite ticket relation" -msgid_plural "Composite ticket relations" -msgstr[0] "Composite ticket relation" -msgstr[1] "Composite ticket relations" - -#: inc/targetticket.class.php:55 entrée standard:43 -msgid "Target ticket" -msgid_plural "Target tickets" -msgstr[0] "Target ticket" -msgstr[1] "Target tickets" - -#: inc/targetticket.class.php:98 -msgid "Specific asset" -msgstr "Specific asset" - -#: inc/targetticket.class.php:99 inc/targetticket.class.php:115 -#: inc/abstractitiltarget.class.php:198 inc/abstractitiltarget.class.php:206 -#: inc/abstractitiltarget.class.php:214 inc/abstractitiltarget.class.php:222 -#: inc/abstractitiltarget.class.php:231 -msgid "Equals to the answer to the question" -msgstr "Equals to the answer to the question" - -#: inc/targetticket.class.php:100 inc/abstractitiltarget.class.php:223 -#: inc/abstractitiltarget.class.php:232 -msgid "Last valid answer" -msgstr "Last valid answer" - -#: inc/targetticket.class.php:106 -msgid "Source from template or user default or GLPI default" -msgstr "Source from template or user default or GLPI default" - -#: inc/targetticket.class.php:107 -msgid "Formcreator" -msgstr "Formcreator" - -#: inc/targetticket.class.php:113 -msgid "Default or from a template" -msgstr "Default or from a template" - -#: inc/targetticket.class.php:114 -msgid "Specific type" -msgstr "Specific type" - -#: inc/targetticket.class.php:187 entrée standard:48 -msgid "Ticket title" -msgstr "Ticket title" - -#: inc/targetticket.class.php:300 -msgid "Add validation message as first ticket followup" -msgstr "Add validation message as first ticket followup" - -#: inc/targetticket.class.php:334 -msgid "Add a field" -msgstr "Add a field" - -#: inc/targetticket.class.php:362 -msgid "Managed fields" -msgstr "Managed fields" - -#: inc/targetticket.class.php:369 -msgid "No managed field" -msgstr "No managed field" - -#: inc/targetticket.class.php:389 -msgid "Link to an other ticket" -msgstr "Link to an other ticket" - -#: inc/targetticket.class.php:398 -msgid "An other destination of this form" -msgstr "An other destination of this form" - -#: inc/targetticket.class.php:399 -msgid "An existing ticket" -msgstr "An existing ticket" - -#: inc/targetticket.class.php:400 -msgid "A ticket from an answer to a question" -msgstr "A ticket from an answer to a question" - -#: inc/targetticket.class.php:481 -msgctxt "button" -msgid "Delete permanently" -msgstr "Delete permanently" - -#: inc/targetticket.class.php:722 -msgid "Invalid link type" -msgstr "Invalid link type" - -#: inc/targetticket.class.php:742 -msgid "Invalid linked item type" -msgstr "Invalid linked item type" - -#: inc/targetticket.class.php:755 -msgid "Linked item does not exists" -msgstr "Linked item does not exists" - -#: inc/targetticket.class.php:768 -msgid "Failed to link the item" -msgstr "Failed to link the item" - -#: inc/targetticket.class.php:924 install/install.php:421 -msgid "Your form has been accepted by the validator" -msgstr "Your form has been accepted by the validator" - -#: inc/targetticket.class.php:1086 -msgid "Request source" -msgstr "Request source" - -#: inc/targetticket.class.php:1111 -msgid "Type " -msgstr "Type " - -#: inc/targetticket.class.php:1139 -msgid "Associated elements" -msgstr "Associated elements" - -#: inc/targetticket.class.php:1150 -msgid "Item " -msgstr "Item " - -#: inc/translation.class.php:153 -msgid "No more string to translate" -msgstr "No more string to translate" - -#: inc/translation.class.php:216 -msgid "Language not found." -msgstr "Language not found." - -#: inc/translation.class.php:221 -msgid "Form not found." -msgstr "Form not found." - -#: inc/translation.class.php:234 -msgid "Failed to add the translation." -msgstr "Failed to add the translation." - -#: inc/abstractitiltarget.class.php:179 -msgid "Tags from questions" -msgstr "Tags from questions" - -#: inc/abstractitiltarget.class.php:180 -msgid "Specific tags" -msgstr "Specific tags" - -#: inc/abstractitiltarget.class.php:181 -msgid "Tags from questions and specific tags" -msgstr "Tags from questions and specific tags" - -#: inc/abstractitiltarget.class.php:182 -msgid "Tags from questions or specific tags" -msgstr "Tags from questions or specific tags" - -#: inc/abstractitiltarget.class.php:188 -msgid "equals to the answer to the question" -msgstr "equals to the answer to the question" - -#: inc/abstractitiltarget.class.php:189 -msgid "calculated from the ticket creation date" -msgstr "calculated from the ticket creation date" - -#: inc/abstractitiltarget.class.php:190 -msgid "calculated from the answer to the question" -msgstr "calculated from the answer to the question" - -#: inc/abstractitiltarget.class.php:196 -msgid "SLA from template or none" -msgstr "SLA from template or none" - -#: inc/abstractitiltarget.class.php:197 -msgid "Specific SLA" -msgstr "Specific SLA" - -#: inc/abstractitiltarget.class.php:204 -msgid "OLA from template or none" -msgstr "OLA from template or none" - -#: inc/abstractitiltarget.class.php:205 -msgid "Specific OLA" -msgstr "Specific OLA" - -#: inc/abstractitiltarget.class.php:212 -msgid "Urgency from template or Medium" -msgstr "Urgency from template or Medium" - -#: inc/abstractitiltarget.class.php:213 -msgid "Specific urgency" -msgstr "Specific urgency" - -#: inc/abstractitiltarget.class.php:220 -msgid "Category from template or none" -msgstr "Category from template or none" - -#: inc/abstractitiltarget.class.php:221 -msgid "Specific category" -msgstr "Specific category" - -#: inc/abstractitiltarget.class.php:229 -msgid "Location from template or none" -msgstr "Location from template or none" - -#: inc/abstractitiltarget.class.php:230 -msgid "Specific location" -msgstr "Specific location" - -#: inc/abstractitiltarget.class.php:238 -msgid "No validation" -msgstr "No validation" - -#: inc/abstractitiltarget.class.php:239 -msgid "Specific user or group" -msgstr "Specific user or group" - -#: inc/abstractitiltarget.class.php:240 -msgid "User from question answer" -msgstr "User from question answer" - -#: inc/abstractitiltarget.class.php:241 -msgid "Group from question answer" -msgstr "Group from question answer" - -#: inc/abstractitiltarget.class.php:740 -msgid "Time to resolve" -msgstr "Time to resolve" - -#: inc/abstractitiltarget.class.php:793 -msgid "Minute" -msgid_plural "Minutes" -msgstr[0] "Minute" -msgstr[1] "Minutes" - -#: inc/abstractitiltarget.class.php:794 -msgid "Hour" -msgid_plural "Hours" -msgstr[0] "Hour" -msgstr[1] "Hours" - -#: inc/abstractitiltarget.class.php:795 -msgid "Day" -msgid_plural "Days" -msgstr[0] "Day" -msgstr[1] "Days" - -#: inc/abstractitiltarget.class.php:796 -msgid "Month" -msgid_plural "Months" -msgstr[0] "Month" -msgstr[1] "Months" - -#: inc/abstractitiltarget.class.php:828 -msgid "SLA (TTO/TTR)" -msgstr "SLA (TTO/TTR)" - -#: inc/abstractitiltarget.class.php:829 inc/abstractitiltarget.class.php:902 -msgid "Question (TTO/TTR)" -msgstr "Question (TTO/TTR)" - -#: inc/abstractitiltarget.class.php:901 -msgid "OLA (TTO/TTR)" -msgstr "OLA (TTO/TTR)" - -#: inc/abstractitiltarget.class.php:1005 -msgid "Urgency " -msgstr "Urgency " - -#: inc/abstractitiltarget.class.php:1035 -msgid "Ticket tags" -msgstr "Ticket tags" - -#: inc/abstractitiltarget.class.php:1083 -msgid "Tags" -msgstr "Tags" - -#: inc/abstractitiltarget.class.php:1202 -msgid "Location" -msgstr "Location" - -#: inc/abstractitiltarget.class.php:1214 -msgid "Location " -msgstr "Location " - -#: inc/abstractitiltarget.class.php:1554 -msgid "The description cannot be empty!" -msgstr "The description cannot be empty!" - -#: inc/abstractitiltarget.class.php:1731 -msgid "Watcher" -msgid_plural "Watchers" -msgstr[0] "Watcher" -msgstr[1] "Watchers" - -#: inc/abstractitiltarget.class.php:1750 -msgid "Cancel" -msgstr "Cancel" - -#: inc/abstractitiltarget.class.php:2025 inc/abstractitiltarget.class.php:2041 -#: inc/abstractitiltarget.class.php:2042 -msgid "Email followup" -msgstr "Email followup" - -#: inc/abstractitiltarget.class.php:2038 inc/abstractitiltarget.class.php:2056 -msgid "User" -msgstr "User" - -#: inc/abstractitiltarget.class.php:2039 inc/abstractitiltarget.class.php:2067 -msgid "Group" -msgstr "Group" - -#: inc/abstractitiltarget.class.php:2040 inc/abstractitiltarget.class.php:2096 -msgid "Supplier" -msgstr "Supplier" - -#: inc/abstractitiltarget.class.php:2041 -msgid "Yes" -msgstr "Yes" - -#: inc/abstractitiltarget.class.php:2078 -msgid "Group from the object" -msgstr "Group from the object" - -#: inc/abstractitiltarget.class.php:2084 -msgid "Tech group from the object" -msgstr "Tech group from the object" - -#: install/install.php:130 -#, php-format -msgid "Upgrade tables to innoDB; run %s" -msgstr "Upgrade tables to innoDB; run %s" - -#: install/install.php:160 -#, php-format -msgid "" -"The database schema is not consistent with the installed Formcreator %s. To " -"see the logs run the command %s" -msgstr "" -"The database schema is not consistent with the installed Formcreator %s. To " -"see the logs run the command %s" - -#: install/install.php:169 -#, php-format -msgid "To ignore the inconsistencies and upgrade anyway run %s" -msgstr "To ignore the inconsistencies and upgrade anyway run %s" - -#: install/install.php:187 -msgid "" -"Upgrade from version older than 2.5.0 is no longer supported. Please upgrade" -" to GLPI 9.5.7, upgrade Formcreator to version 2.12.5, then upgrade again to" -" GLPI 10 or later and Formcreator 2.13 or later." -msgstr "" -"Upgrade from version older than 2.5.0 is no longer supported. Please upgrade" -" to GLPI 9.5.7, upgrade Formcreator to version 2.12.5, then upgrade again to" -" GLPI 10 or later and Formcreator 2.13 or later." - -#: install/install.php:239 -#, php-format -msgid "" -"The database schema is not consistent with the installed Formcreator %s. To " -"see the logs enable the plugin and run the command %s" -msgstr "" -"The database schema is not consistent with the installed Formcreator %s. To " -"see the logs enable the plugin and run the command %s" - -#: install/install.php:250 -msgid "The tables of the plugin passed the schema integrity check." -msgstr "The tables of the plugin passed the schema integrity check." - -#: install/install.php:402 -msgid "A form has been created" -msgstr "A form has been created" - -#: install/install.php:403 -msgid "Your request has been saved" -msgstr "Your request has been saved" - -#: install/install.php:404 -msgid "" -"Hi,\\nYour request from GLPI has been successfully saved with number " -"##formcreator.request_id## and transmitted to the helpdesk team.\\nYou can " -"see your answers onto the following link:\\n##formcreator.validation_link##" -msgstr "" -"Hi,\\nYour request from GLPI has been successfully saved with number " -"##formcreator.request_id## and transmitted to the helpdesk team.\\nYou can " -"see your answers onto the following link:\\n##formcreator.validation_link##" - -#: install/install.php:409 -msgid "A form from GLPI need to be validate" -msgstr "A form from GLPI need to be validate" - -#: install/install.php:410 -msgid "" -"Hi,\\nA form from GLPI need to be validate and you have been choosen as the " -"validator.\\nYou can access it by clicking onto this " -"link:\\n##formcreator.validation_link##" -msgstr "" -"Hi,\\nA form from GLPI need to be validate and you have been choosen as the " -"validator.\\nYou can access it by clicking onto this " -"link:\\n##formcreator.validation_link##" - -#: install/install.php:415 -msgid "Your form has been refused by the validator" -msgstr "Your form has been refused by the validator" - -#: install/install.php:416 -msgid "" -"Hi,\\nWe are sorry to inform you that your form has been refused by the " -"validator for the reason " -"below:\\n##formcreator.validation_comment##\\n\\nYou can still modify and " -"resubmit it by clicking onto this link:\\n##formcreator.validation_link##" -msgstr "" -"Hi,\\nWe are sorry to inform you that your form has been refused by the " -"validator for the reason " -"below:\\n##formcreator.validation_comment##\\n\\nYou can still modify and " -"resubmit it by clicking onto this link:\\n##formcreator.validation_link##" - -#: install/install.php:422 -msgid "" -"Hi,\\nWe are pleased to inform you that your form has been accepted by the " -"validator.\\nYour request will be considered soon." -msgstr "" -"Hi,\\nWe are pleased to inform you that your form has been accepted by the " -"validator.\\nYour request will be considered soon." - -#: install/install.php:427 -msgid "Your form has been deleted by an administrator" -msgstr "Your form has been deleted by an administrator" - -#: install/install.php:428 -msgid "" -"Hi,\\nWe are sorry to inform you that your request cannot be considered and " -"has been deleted by an administrator." -msgstr "" -"Hi,\\nWe are sorry to inform you that your request cannot be considered and " -"has been deleted by an administrator." - -#: install/install.php:654 -msgid "Formcreator - Sync service catalog issues" -msgstr "Formcreator - Sync service catalog issues" - -#: install/install.php:842 -msgid "Failed to check the sanity of the tables!" -msgstr "Failed to check the sanity of the tables!" - -#: install/install.php:856 -#, php-format -msgid "Table schema differs for table \"%s\"." -msgstr "Table schema differs for table \"%s\"." - -#: install/install.php:859 -#, php-format -msgid "Table \"%s\" is missing." -msgstr "Table \"%s\" is missing." - -#: install/install.php:862 -#, php-format -msgid "Unknown table \"%s\" has been found in database." -msgstr "Unknown table \"%s\" has been found in database." - -#: hook.php:317 -msgctxt "button" -msgid "Duplicate" -msgstr "Duplicate" - -#: hook.php:318 -msgid "Transfer" -msgstr "Transfer" - -#: hook.php:319 -msgctxt "button" -msgid "Export" -msgstr "Export" - -#: hook.php:619 -msgid "Cancel my ticket" -msgstr "Cancel my ticket" - -#: hook.php:637 -msgid "Old" -msgstr "Old" - -#: hook.php:644 -#, php-format -msgid "Number of %s" -msgstr "Number of %s" - -#: hook.php:661 -msgid "Issues summary" -msgstr "Issues summary" - -#: hook.php:699 -msgid "" -"Formcreator's mini dashboard not usable as default. This Setting has been " -"ignored." -msgstr "" -"Formcreator's mini dashboard not usable as default. This Setting has been " -"ignored." - -#: js/scripts.js:296 -msgid "No form found. Please choose a form below instead." -msgstr "No form found. Please choose a form below instead." - -#: js/scripts.js:298 -msgid "No form found." -msgstr "No form found." - -#: js/scripts.js:302 -msgid "No FAQ item found." -msgstr "No FAQ item found." - -#: js/scripts.js:686 -msgid "Are you sure you want to delete this question?" -msgstr "Are you sure you want to delete this question?" - -#: js/scripts.js:869 -msgid "Are you sure you want to delete this section?" -msgstr "Are you sure you want to delete this section?" - -#: js/scripts.js:1109 -msgid "Add translations" -msgstr "Add translations" - -#: js/scripts.js:1256 js/scripts.js:1280 -msgid "An error occured while querying forms" -msgstr "An error occured while querying forms" - -#: js/scripts.js:1396 entrée standard:139 -msgid "Send" -msgstr "Send" - -#: js/scripts.js:1405 -msgid "An internal error occurred. Please report it to administrator." -msgstr "An internal error occurred. Please report it to administrator." - -#: js/scripts.js:1446 -msgid "Are you sure you want to delete this target:" -msgstr "Are you sure you want to delete this target:" - -#: entrée standard:43 standard:50 standard:44 standard:49 standard:78 -msgid "Required" -msgstr "Required" - -#: entrée standard:57 standard:61 standard:60 standard:59 standard:43 -#: standard:69 standard:52 standard:37 -msgid "Default values" -msgstr "Default values" - -#: entrée standard:52 standard:59 standard:58 -msgid "Show empty" -msgstr "Show empty" - -#: entrée standard:39 -msgid "LDAP directory" -msgid_plural "LDAP directories" -msgstr[0] "LDAP directory" -msgstr[1] "LDAP directories" - -#: entrée standard:68 -msgid "Filter" -msgstr "Filter" - -#: entrée standard:78 -msgid "Attribute" -msgstr "Attribute" - -#: entrée standard:70 standard:68 -msgid "Values" -msgstr "Values" - -#: entrée standard:90 -msgid "Show ticket categories" -msgstr "Show ticket categories" - -#: entrée standard:127 standard:110 -msgid "Selectable root" -msgstr "Selectable root" - -#: entrée standard:63 -msgid "Direct access on homepage" -msgstr "Direct access on homepage" - -#: entrée standard:86 -msgid "Default form in service catalog" -msgstr "Default form in service catalog" - -#: entrée standard:113 standard:114 -msgid "Are you a robot ?" -msgstr "Are you a robot ?" - -#: entrée standard:64 -msgid "Condition to show the section" -msgstr "Condition to show the section" - -#: entrée standard:40 -msgid "Condition to generate the target" -msgstr "Condition to generate the target" - -#: entrée standard:127 -msgid "Condition to show the question" -msgstr "Condition to show the question" - -#: entrée standard:54 -msgid "Impacts" -msgstr "Impacts" - -#: entrée standard:62 -msgid "Checklist" -msgstr "Checklist" - -#: entrée standard:36 -msgid "Answers title" -msgstr "Answers title" - -#: entrée standard:45 -msgid "Add a section" -msgstr "Add a section" - -#: entrée standard:55 -msgid "Condition to show the submit button" -msgstr "Condition to show the submit button" - -#: entrée standard:83 -msgid "Add a question" -msgstr "Add a question" - -#: entrée standard:39 -msgid "List of available tags" -msgstr "List of available tags" - -#: entrée standard:42 -msgid "Title" -msgstr "Title" - -#: entrée standard:47 -msgid "Full form" -msgstr "Full form" - -#: entrée standard:42 -msgid "Min" -msgstr "Min" - -#: entrée standard:53 -msgid "Max" -msgstr "Max" diff --git a/locales/en_US.mo b/locales/en_US.mo index 11699b8f832290946e091fe6fe2795c4b3192052..45829010899c14f88042d52013aabd220ef6101e 100644 GIT binary patch delta 4192 zcmYk;3viXi8Gzx1BuEl20YW0sLK4EIH8Bu_AccwnFGy>-h=^QTg9wpSV~ir8IW$nP zP)rcKky;fEMJtK~LliGVt0NAbiPmWct7Tf4Qp?~(u;VziWBb16tTXKJoo9D*&i=dK z?*7BNyPEGz9P6L{aG<S!D1}P2_YY^#KE`-OYz>= z-h~Vi4n+?~JMlvL|BQXG3wwu<2wzhvqoY^95C-BT^oz5jE0AZ0^~hJlb{v7N*dLEz zAs#~~YNrz_L%PBu%)~p;iLFA%UyDO|et4WpFFHCf3*SNhh4=aJ2Pg0XJcZ0SoJA)Z z283Xe^3Vqs;V_&Tt&KLLk882o|FYm=gQ1!-T1+iXAm*du?iXEf72UFD(2Tq^nEbmZN9ZuM|3GIth`+i= zW6>{G^5M!B<4|0VX}B@E86CI@86vbG$0W3)-+vFC_@|hTXV3|LnV>R?N?)ew;Teyn zY+iI3n);P!1~#C3za8E4me_t8{oQWlU+Cb&3H%A2_@}Xb7M)1Ow^Nx*^r2$PiqHWn z&<9M5?HQO%CAzYD^p-RsyB2n!zkeD1{qNBUe;E6Z$NqoEb~@>BA$drK6QP)j1CK*f zGZWp@x#&HwMsGz^{QG`%1+QWO{to^931o5MYjk2mNT(AjN5`o|E=E|6j(>mBLGrLiqwc3j+&M_q`M+(w>Umf(A^c9Nqg4^iaMX+aF*V?Z2Yq_2xs%_;3NU za9D!MO;p^g)#!j*@Voc~dd&`_890ruv|mvOC0K&K@#f=2_yBU8!hUo@@1v>y1U<~B zV*5Yn_?Zlz7)_;uiVs+X&D}z1L?0kiu ziGCwf6DmM6bMZ*_pLa-DOov~rk8VLTu?wAfJ2FOi7tPdXNHUUF$B7nkg`ChV^e`sS zQ@<5^U<*3_PULumgXmWMWfb}MH2;$h2R@7bAcM4AfW6QZ=AsiVLQ^{dec&|Yn1s6M zL(zTcIDbUX)<@_0n# zL(vtDKu>o$dKRui7f==ZYcZ4d`q)l97&~@GUqDmUj_z3}@~m(SonTK+n%AoY$KX_S zz)K6bG1yu5c>4 z!kOq6-GV;22Ay~V`W|=`-O~M-jqjov`4HWbF1&>2hfJ2?OebRw&PBg?EBfF@^w4a^ zG<-h#B0BIs^j5ryKJX*-`=`<0XOB(2*mBVc4nmGuD96)zM98>UW?Scn;m; z1L&T=8QX88zdM4i_+xYeU!hx)U7p&if#^g^(9Dg)emETy4zPfV4_JY=>(H4tqAP2` zENn;j{t!CAQS|$#&#F|XzcwFi% zOhWJb^*9l4LvKMVx}r{W@BfY-%Fkl^9G21UacOG2OQScUhjlgjzG%e$xHCb;8NY(u zu<#Cg%|1snkUKuL!po2g5^g{)Mp%d3ps)`;tjEwyokO?sf9M(LF(K8?LC4R>(O8L& zpIAYKSAMeG8=Ztt5e{5USXL6Q%)9#r@i=iiK?1`qgyn}sEpep{%4A|&vPLE`mw1kN zl5mogMBx7g$(h;maJ)>g8_E5HWHI%Y7UEjsKH{f@WqOJ*5(|iF#Loz`YWXo?>d!BE zG=57gbozHwSw&n!%p**T<@FTFyKL3{^3WZ$LGeIZRuh#(l?{qFOI|d64a6d%HU7Z^c@;5}U>n0a!s31}BiONIc{S?E{vNS`*c|)T;}T*8@dM&= zVk_}9v6jdrULz77Cd-->$0IkA-3L@XwD6Lo|ym@5cN z4e^^~E%hS1E7oV@FNjj27t!7QpGCzx-AFt_>?FQVJV02|iC-scA^Ze=af~7!CB7*e zzp3DZvAzW_BgPPS#6G#|InBA>X9u*@eOBA&28DNK?4+|K7?L|g1D zii&T>vBaG=D8C}+5I-XBCoGw_@-f3&+pL`C?%U>#Ue(q$`e0hyg!~a%ZB>PPyKgHi zt{-~+^6I5^b*l<0?_NfwU{ZZmvNEN9>5`i2sSm(p6tEt=E99_OUC!@{(t%- BlzIRF delta 4445 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 JzOj5++W))Iy2Ahf delta 2889 zcmXZddra0<9LMnkh?v|(t|AhO0)ilD>b#7Y3MK}d*3@!3wP}g8nKd=_rxM?*2T2eqAdruu9GhBkLUdLI_Lb(<$J#8oag!Ynt#VN|I-bz z-c!by#LdP`!Cjb-7jY5#Z!snlAID+12NSUchu|gWbxfh&-EW;?QtzaU53MXmM4o;yWzUn$$clDn!i1t2=#=kHe!(K2Z7?V)n zGcX2o@qV0xnr{u}<2p>jcGNuG9)$!7JvbBtDy?ytPdy72SUCn_4QgOL=HZ*Dg>GRg z2JE!s(@_D=z_Iu+>IgPD>rerEZ4|WddpHe0MeQJDm$`Q|BT)fN$5>qE+~B_Nci&ra z0N=Zu-8hQ+m#8D{#~=*bO^_IaWWqBEu3-x5QcXt%P>MRURj9Li4t06h64p zn(%Mb_L`{&iZDjYdDS})LT)JzJpreJnGVPU@-RJ zK>Q6y<6Vrvlqzc;4yHa6wV@Ks!8MqL4X7ji1U;qtHU;fqK(&o94%ME4iu^%TYL{XN zuES9DP|vFx^}QA6;04qr4f2t09FAqU5(nYu7>Zx{$iH^dLxU#hb^7l!=057ts7o`# zIR^PWu_7}agA$lLiK+e!?6=b;Mb_5xVw-1D@CFEZ9_V0hf`5UP=uPW z7_=Azgjyk1{K&i)b~P+!iA^|mLW&)86SmlG#tWYyo}o6 zk2n+q57|^FppIZPD&@0KJ1D^kScV$cj7sfAOvWpigSVYYbvBR^9IyAkg2DrIID~l` zfEj4&?F3_;#i)tbVl-|*y<;Ehj@06DJccK+kbf#Y&py<=v4`z^b5Xw&Wmv)briMZ; zM!#$=!fDi>$H{okc?Xrcj3YLHV${x-qcU?4m4P_hd7Y_Q)8Q2m#qmrr3k z1wE%rn1H|FSPXiFw~u+K6hDg-u@#5mO;rDWOvczo`@=FBXHkC)byu2EcjYQ3;w@AL z|7|4yx)ej3Y(pCA%xB=eSK;a_P^sR4x>Q?Td%bIa1Lx7+hWr>BbJQMH73%k;9`#%s zQNMhxs7u*()U*FuH)v3YAKZst)Xq(_jko}ZQ(cOya0^EGaY=DJ^*@f;ou<8NeFXIk zcR2TAD)j@Xb_nIBJ2}eNdLXm8b=) zQJ3-qRDi!@BqqFW`)8suHW_t Date: Mon, 19 Jun 2023 11:51:28 +0200 Subject: [PATCH 30/58] build(locales): update mo files build code --- RoboFilePlugin.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/RoboFilePlugin.php b/RoboFilePlugin.php index 398c8395c..c67724083 100644 --- a/RoboFilePlugin.php +++ b/RoboFilePlugin.php @@ -130,7 +130,16 @@ public function localesPull($percent = 70) { * @return void */ public function localesMo() { - $this->_exec('./tools/release --compile-mo'); + $po_files = preg_grep('/\.po$/', scandir('./locales')); + foreach ($po_files as $po_file) { + $mo_file = preg_replace('/\.po$/', '.mo', $po_file); + echo("Processing {$po_file}\n"); + passthru("cd ./locales && msgfmt -f -o {$mo_file} {$po_file}", $exit_code); + if ($exit_code > 0) { + exit($exit_code); + } + } + return $this; } From 8aaec8acb6dd868d2351337667cc9de7a4d92214 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Fri, 16 Jun 2023 15:21:22 +0200 Subject: [PATCH 31/58] fix(selectfield,multiselectfield): fix possible encoding problem --- inc/field/multiselectfield.class.php | 5 +- inc/formanswer.class.php | 2 +- install/install.php | 1 + .../mysql/plugin_formcreator_2.13.7_empty.sql | 352 ++++++++++++++++++ install/upgrade_to_2.13.7.php | 86 +++++ setup.php | 4 +- 6 files changed, 446 insertions(+), 4 deletions(-) create mode 100644 install/mysql/plugin_formcreator_2.13.7_empty.sql create mode 100644 install/upgrade_to_2.13.7.php diff --git a/inc/field/multiselectfield.class.php b/inc/field/multiselectfield.class.php index ce59a0979..4923d05e0 100644 --- a/inc/field/multiselectfield.class.php +++ b/inc/field/multiselectfield.class.php @@ -34,6 +34,7 @@ use Dropdown; use Html; +use Glpi\Toolbox\Sanitizer; class MultiSelectField extends CheckboxesField { @@ -55,8 +56,10 @@ public function getRenderedHtml($domain, $canEdit = true): string { $fieldName = 'formcreator_field_' . $id; $values = $this->getAvailableValues(); $translatedValues = []; + foreach ($values as $key => $value) { - $translatedValues[$key] = __($value, $domain); + $unsanitized = Sanitizer::unsanitize(__($value, $domain)); + $translatedValues[$key] = $unsanitized; } if (!empty($values)) { $html .= Dropdown::showFromArray($fieldName, $translatedValues, [ diff --git a/inc/formanswer.class.php b/inc/formanswer.class.php index a5ff1f575..92f5aab61 100644 --- a/inc/formanswer.class.php +++ b/inc/formanswer.class.php @@ -1423,7 +1423,7 @@ protected function validateFormAnswer($input): bool { ); } - $this->isAnswersValid = false; + $this->isAnswersValid = false; } } } diff --git a/install/install.php b/install/install.php index f4e9bb8ca..47e245654 100644 --- a/install/install.php +++ b/install/install.php @@ -82,6 +82,7 @@ class PluginFormcreatorInstall { '2.13.3' => '2.13.4', '2.13.4' => '2.13.5', '2.13.5' => '2.13.6', + '2.13.6' => '2.13.7', ]; protected bool $resyncIssues = false; diff --git a/install/mysql/plugin_formcreator_2.13.7_empty.sql b/install/mysql/plugin_formcreator_2.13.7_empty.sql new file mode 100644 index 000000000..6838b92fb --- /dev/null +++ b/install/mysql/plugin_formcreator_2.13.7_empty.sql @@ -0,0 +1,352 @@ +-- Database schema +-- Do NOT drop anything here + +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_answers` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `plugin_formcreator_formanswers_id` int unsigned NOT NULL DEFAULT '0', + `plugin_formcreator_questions_id` int unsigned NOT NULL DEFAULT '0', + `answer` longtext, + PRIMARY KEY (`id`), + INDEX `plugin_formcreator_formanswers_id` (`plugin_formcreator_formanswers_id`), + INDEX `plugin_formcreator_questions_id` (`plugin_formcreator_questions_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_categories` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL DEFAULT '', + `comment` mediumtext, + `completename` varchar(255) DEFAULT NULL, + `plugin_formcreator_categories_id` int unsigned NOT NULL DEFAULT '0', + `level` int(11) NOT NULL DEFAULT '1', + `sons_cache` longtext, + `ancestors_cache` longtext, + `knowbaseitemcategories_id` int unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + INDEX `name` (`name`), + INDEX `knowbaseitemcategories_id` (`knowbaseitemcategories_id`), + INDEX `plugin_formcreator_categories_id` (`plugin_formcreator_categories_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_entityconfigs` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `entities_id` int unsigned NOT NULL DEFAULT '0', + `replace_helpdesk` int(11) NOT NULL DEFAULT '-2', + `default_form_list_mode` int(11) NOT NULL DEFAULT '-2', + `sort_order` int(11) NOT NULL DEFAULT '-2', + `is_kb_separated` int(11) NOT NULL DEFAULT '-2', + `is_search_visible` int(11) NOT NULL DEFAULT '-2', + `is_dashboard_visible` int(11) NOT NULL DEFAULT '-2', + `is_header_visible` int(11) NOT NULL DEFAULT '-2', + `is_search_issue_visible` int(11) NOT NULL DEFAULT '-2', + `tile_design` int(11) NOT NULL DEFAULT '-2', + `header` text, + `service_catalog_home` int(11) NOT NULL DEFAULT '-2', + PRIMARY KEY (`id`), + UNIQUE KEY `unicity` (`entities_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_forms` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL DEFAULT '', + `entities_id` int unsigned NOT NULL DEFAULT '0', + `is_recursive` tinyint(1) NOT NULL DEFAULT '0', + `icon` varchar(255) NOT NULL DEFAULT '', + `icon_color` varchar(255) NOT NULL DEFAULT '', + `background_color` varchar(255) NOT NULL DEFAULT '', + `access_rights` tinyint(1) NOT NULL DEFAULT '1', + `description` varchar(255) DEFAULT NULL, + `content` longtext, + `plugin_formcreator_categories_id` int unsigned NOT NULL DEFAULT '0', + `is_active` tinyint(1) NOT NULL DEFAULT '0', + `language` varchar(255) NOT NULL DEFAULT '', + `helpdesk_home` tinyint(1) NOT NULL DEFAULT '0', + `is_deleted` tinyint(1) NOT NULL DEFAULT '0', + `validation_required` tinyint(1) NOT NULL DEFAULT '0', + `usage_count` int(11) NOT NULL DEFAULT '0', + `is_default` tinyint(1) NOT NULL DEFAULT '0', + `is_captcha_enabled` tinyint(1) NOT NULL DEFAULT '0', + `show_rule` int(11) NOT NULL DEFAULT '1' COMMENT 'Conditions setting to show the submit button', + `formanswer_name` varchar(255) NOT NULL DEFAULT '', + `is_visible` tinyint NOT NULL DEFAULT 1, + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `entities_id` (`entities_id`), + INDEX `plugin_formcreator_categories_id` (`plugin_formcreator_categories_id`), + FULLTEXT KEY `Search` (`name`,`description`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_formanswers` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL DEFAULT '', + `entities_id` int unsigned NOT NULL DEFAULT '0', + `is_recursive` tinyint(1) NOT NULL DEFAULT '0', + `plugin_formcreator_forms_id` int unsigned NOT NULL DEFAULT '0', + `requester_id` int unsigned NOT NULL DEFAULT '0', + `users_id_validator` int unsigned NOT NULL DEFAULT '0' COMMENT 'User in charge of validation', + `groups_id_validator` int unsigned NOT NULL DEFAULT '0' COMMENT 'Group in charge of validation', + `request_date` timestamp NULL, + `status` int(11) NOT NULL DEFAULT '101', + `comment` mediumtext, + PRIMARY KEY (`id`), + INDEX `plugin_formcreator_forms_id` (`plugin_formcreator_forms_id`), + INDEX `entities_id_is_recursive` (`entities_id`, `is_recursive`), + INDEX `requester_id` (`requester_id`), + INDEX `users_id_validator` (`users_id_validator`), + INDEX `groups_id_validator` (`groups_id_validator`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_forms_profiles` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `plugin_formcreator_forms_id` int unsigned NOT NULL DEFAULT '0', + `profiles_id` int unsigned NOT NULL DEFAULT '0', + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `unicity` (`plugin_formcreator_forms_id`,`profiles_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_forms_users` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `plugin_formcreator_forms_id` int unsigned NOT NULL, + `users_id` int unsigned NOT NULL, + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `unicity` (`plugin_formcreator_forms_id`,`users_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_forms_groups` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `plugin_formcreator_forms_id` int unsigned NOT NULL, + `groups_id` int unsigned NOT NULL, + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `unicity` (`plugin_formcreator_forms_id`,`groups_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_forms_validators` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `plugin_formcreator_forms_id` int unsigned NOT NULL DEFAULT '0', + `itemtype` varchar(255) NOT NULL DEFAULT '', + `items_id` int unsigned NOT NULL DEFAULT '0', + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `unicity` (`plugin_formcreator_forms_id`,`itemtype`,`items_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_questions` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL DEFAULT '', + `plugin_formcreator_sections_id` int unsigned NOT NULL DEFAULT '0', + `fieldtype` varchar(30) NOT NULL DEFAULT 'text', + `required` tinyint(1) NOT NULL DEFAULT '0', + `show_empty` tinyint(1) NOT NULL DEFAULT '0', + `default_values` mediumtext, + `itemtype` varchar(255) NOT NULL DEFAULT '' COMMENT 'itemtype used for glpi objects and dropdown question types', + `values` mediumtext, + `description` mediumtext, + `row` int(11) NOT NULL DEFAULT '0', + `col` int(11) NOT NULL DEFAULT '0', + `width` int(11) NOT NULL DEFAULT '0', + `show_rule` int(11) NOT NULL DEFAULT '1', + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `plugin_formcreator_sections_id` (`plugin_formcreator_sections_id`), + FULLTEXT KEY `Search` (`name`,`description`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_conditions` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `itemtype` varchar(255) NOT NULL DEFAULT '' COMMENT 'itemtype of the item affected by the condition', + `items_id` int unsigned NOT NULL DEFAULT '0' COMMENT 'item ID of the item affected by the condition', + `plugin_formcreator_questions_id` int unsigned NOT NULL DEFAULT '0' COMMENT 'question to test for the condition', + `show_condition` int(11) NOT NULL DEFAULT '0', + `show_value` mediumtext NULL DEFAULT NULL, + `show_logic` int(11) NOT NULL DEFAULT '1', + `order` int(11) NOT NULL DEFAULT '1', + `uuid` varchar(255) NULL DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `plugin_formcreator_questions_id` (`plugin_formcreator_questions_id`), + INDEX `item` (`itemtype`, `items_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_sections` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL DEFAULT '', + `plugin_formcreator_forms_id` int unsigned NOT NULL DEFAULT '0', + `order` int(11) NOT NULL DEFAULT '0', + `show_rule` int(11) NOT NULL DEFAULT '1', + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `plugin_formcreator_forms_id` (`plugin_formcreator_forms_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_targetchanges` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL DEFAULT '', + `plugin_formcreator_forms_id` int unsigned NOT NULL DEFAULT '0', + `target_name` varchar(255) NOT NULL DEFAULT '', + `changetemplates_id` int unsigned NOT NULL DEFAULT '0', + `content` longtext, + `impactcontent` longtext, + `controlistcontent` longtext, + `rolloutplancontent` longtext, + `backoutplancontent` longtext, + `checklistcontent` longtext, + `due_date_rule` int(11) NOT NULL DEFAULT '1', + `due_date_question` int unsigned NOT NULL DEFAULT '0', + `due_date_value` tinyint(4) DEFAULT NULL, + `due_date_period` int(11) NOT NULL DEFAULT '0', + `urgency_rule` int(11) NOT NULL DEFAULT '1', + `urgency_question` int unsigned NOT NULL DEFAULT '0', + `validation_followup` tinyint(1) NOT NULL DEFAULT '1', + `destination_entity` int(11) NOT NULL DEFAULT '1', + `destination_entity_value` int unsigned NOT NULL DEFAULT '0', + `tag_type` int(11) NOT NULL DEFAULT '1', + `tag_questions` varchar(255) NOT NULL DEFAULT '', + `tag_specifics` varchar(255) NOT NULL DEFAULT '', + `category_rule` int(11) NOT NULL DEFAULT '1', + `category_question` int unsigned NOT NULL DEFAULT '0', + `commonitil_validation_rule` int(11) NOT NULL DEFAULT '1', + `commonitil_validation_question` varchar(255) DEFAULT NULL, + `show_rule` int(11) NOT NULL DEFAULT '1', + `sla_rule` int(11) NOT NULL DEFAULT '1', + `sla_question_tto` int unsigned NOT NULL DEFAULT '0', + `sla_question_ttr` int unsigned NOT NULL DEFAULT '0', + `ola_rule` int(11) NOT NULL DEFAULT '1', + `ola_question_tto` int unsigned NOT NULL DEFAULT '0', + `ola_question_ttr` int unsigned NOT NULL DEFAULT '0', + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_targettickets` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL DEFAULT '', + `plugin_formcreator_forms_id` int unsigned NOT NULL DEFAULT '0', + `target_name` varchar(255) NOT NULL DEFAULT '', + `source_rule` int(11) NOT NULL DEFAULT '0', + `source_question` int(11) NOT NULL DEFAULT '0', + `type_rule` int(11) NOT NULL DEFAULT '0', + `type_question` int unsigned NOT NULL DEFAULT '0', + `tickettemplates_id` int unsigned NOT NULL DEFAULT '0', + `content` longtext, + `due_date_rule` int(11) NOT NULL DEFAULT '1', + `due_date_question` int unsigned NOT NULL DEFAULT '0', + `due_date_value` tinyint(4) DEFAULT NULL, + `due_date_period` int(11) NOT NULL DEFAULT '0', + `urgency_rule` int(11) NOT NULL DEFAULT '1', + `urgency_question` int unsigned NOT NULL DEFAULT '0', + `validation_followup` tinyint(1) NOT NULL DEFAULT '1', + `destination_entity` int(11) NOT NULL DEFAULT '1', + `destination_entity_value` int unsigned NOT NULL DEFAULT '0', + `tag_type` int(11) NOT NULL DEFAULT '1', + `tag_questions` varchar(255) NOT NULL DEFAULT '', + `tag_specifics` varchar(255) NOT NULL DEFAULT '', + `category_rule` int(11) NOT NULL DEFAULT '1', + `category_question` int unsigned NOT NULL DEFAULT '0', + `associate_rule` int(11) NOT NULL DEFAULT '1', + `associate_question` int unsigned NOT NULL DEFAULT '0', + `location_rule` int(11) NOT NULL DEFAULT '1', + `location_question` int unsigned NOT NULL DEFAULT '0', + `commonitil_validation_rule` int(11) NOT NULL DEFAULT '1', + `commonitil_validation_question` varchar(255) DEFAULT NULL, + `show_rule` int(11) NOT NULL DEFAULT '1', + `sla_rule` int(11) NOT NULL DEFAULT '1', + `sla_question_tto` int unsigned NOT NULL DEFAULT '0', + `sla_question_ttr` int unsigned NOT NULL DEFAULT '0', + `ola_rule` int(11) NOT NULL DEFAULT '1', + `ola_question_tto` int unsigned NOT NULL DEFAULT '0', + `ola_question_ttr` int unsigned NOT NULL DEFAULT '0', + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `tickettemplates_id` (`tickettemplates_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_targetproblems` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL DEFAULT '', + `plugin_formcreator_forms_id` int unsigned NOT NULL DEFAULT '0', + `target_name` varchar(255) NOT NULL DEFAULT '', + `problemtemplates_id` int unsigned NOT NULL DEFAULT '0', + `content` longtext, + `impactcontent` longtext, + `causecontent` longtext, + `symptomcontent` longtext, + `urgency_rule` int(11) NOT NULL DEFAULT '1', + `urgency_question` int unsigned NOT NULL DEFAULT '0', + `destination_entity` int(11) NOT NULL DEFAULT '1', + `destination_entity_value` int unsigned NOT NULL DEFAULT '0', + `tag_type` int(11) NOT NULL DEFAULT '1', + `tag_questions` varchar(255) NOT NULL DEFAULT '', + `tag_specifics` varchar(255) NOT NULL DEFAULT '', + `category_rule` int(11) NOT NULL DEFAULT '1', + `category_question` int unsigned NOT NULL DEFAULT '0', + `show_rule` int(11) NOT NULL DEFAULT '1', + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `problemtemplates_id` (`problemtemplates_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_targets_actors` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `itemtype` varchar(255) DEFAULT NULL, + `items_id` int unsigned NOT NULL DEFAULT '0', + `actor_role` int(11) NOT NULL DEFAULT '1', + `actor_type` int(11) NOT NULL DEFAULT '1', + `actor_value` int unsigned NOT NULL DEFAULT '0', + `use_notification` tinyint(1) NOT NULL DEFAULT '1', + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `item` (`itemtype`, `items_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_issues` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NULL DEFAULT NULL, + `display_id` varchar(255) NOT NULL, + `items_id` int unsigned NOT NULL DEFAULT '0', + `itemtype` varchar(255) NOT NULL DEFAULT '', + `status` varchar(255) NOT NULL DEFAULT '', + `date_creation` timestamp NULL, + `date_mod` timestamp NULL, + `entities_id` int unsigned NOT NULL DEFAULT '0', + `is_recursive` tinyint(1) NOT NULL DEFAULT '0', + `requester_id` int unsigned NOT NULL DEFAULT '0', + `comment` longtext, + `users_id_recipient` int unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + INDEX `item` (`itemtype`, `items_id`), + INDEX `entities_id` (`entities_id`), + INDEX `requester_id` (`requester_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_items_targettickets` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `plugin_formcreator_targettickets_id` int unsigned NOT NULL DEFAULT '0', + `link` int(11) NOT NULL DEFAULT '0', + `itemtype` varchar(255) NOT NULL DEFAULT '', + `items_id` int unsigned NOT NULL DEFAULT '0', + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `plugin_formcreator_targettickets_id` (`plugin_formcreator_targettickets_id`), + INDEX `item` (`itemtype`,`items_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_questiondependencies` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `plugin_formcreator_questions_id` int unsigned NOT NULL DEFAULT '0', + `plugin_formcreator_questions_id_2` int unsigned NOT NULL DEFAULT '0', + `fieldname` varchar(255) DEFAULT NULL, + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `plugin_formcreator_questions_id` (`plugin_formcreator_questions_id`), + INDEX `plugin_formcreator_questions_id_2` (`plugin_formcreator_questions_id_2`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_questionregexes` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `plugin_formcreator_questions_id` int unsigned NOT NULL DEFAULT '0', + `regex` mediumtext DEFAULT NULL, + `fieldname` varchar(255) DEFAULT NULL, + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `plugin_formcreator_questions_id` (`plugin_formcreator_questions_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_questionranges` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `plugin_formcreator_questions_id` int unsigned NOT NULL DEFAULT '0', + `range_min` varchar(255) DEFAULT NULL, + `range_max` varchar(255) DEFAULT NULL, + `fieldname` varchar(255) DEFAULT NULL, + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `plugin_formcreator_questions_id` (`plugin_formcreator_questions_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `glpi_plugin_formcreator_forms_languages` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `plugin_formcreator_forms_id` int unsigned NOT NULL DEFAULT '0', + `name` varchar(255) DEFAULT NULL, + `comment` text, + `uuid` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; \ No newline at end of file diff --git a/install/upgrade_to_2.13.7.php b/install/upgrade_to_2.13.7.php new file mode 100644 index 000000000..c1b99d387 --- /dev/null +++ b/install/upgrade_to_2.13.7.php @@ -0,0 +1,86 @@ +. + * --------------------------------------------------------------------- + * @copyright Copyright © 2011 - 2021 Teclib' + * @license http://www.gnu.org/licenses/gpl.txt GPLv3+ + * @link https://github.com/pluginsGLPI/formcreator/ + * @link https://pluginsglpi.github.io/formcreator/ + * @link http://plugins.glpi-project.org/#/plugin/formcreator + * --------------------------------------------------------------------- + */ + +use Glpi\Toolbox\Sanitizer; + +class PluginFormcreatorUpgradeTo2_13_7 { + /** @var Migration */ + protected $migration; + + public function isResyncIssuesRequired() { + return false; + } + + /** + * @param Migration $migration + */ + public function upgrade(Migration $migration) { + $this->migration = $migration; + $this->fixEncodingInQuestions(); + } + + /** + * Select and multiseiect questions pay contain RAW ampersand (&) + * it must be encoded, or select / multiselect fields will not validate answers + * containing this character + * + * @return void + */ + public function fixEncodingInQuestions() { + global $DB; + + $table = 'glpi_plugin_formcreator_questions'; + $result = $DB->request([ + 'SELECT' => 'id', + 'FROM' => $table, + 'WHERE' => [ + 'fieldtype' => ['select', 'multiselect'], + 'values' => ['REGEXP', $DB->escape('&(?!#38;)')], + ], + ]); + + foreach ($result as $row) { + $values = json_decode($row['values']); + if (!is_array($values) || $values === null) { + continue; + } + foreach ($values as &$value) { + $value = Sanitizer::encodeHtmlSpecialChars($value); + } + $values = json_encode($values); + $DB->update( + $table, + ['values' => $values], + ['id' => $row['id']] + ); + } + } +} diff --git a/setup.php b/setup.php index a14ea3385..85d4ffc20 100644 --- a/setup.php +++ b/setup.php @@ -33,11 +33,11 @@ global $CFG_GLPI; // Version of the plugin (major.minor.bugfix) -define('PLUGIN_FORMCREATOR_VERSION', '2.13.6'); +define('PLUGIN_FORMCREATOR_VERSION', '2.13.7'); // Schema version of this version (major.minor only) define('PLUGIN_FORMCREATOR_SCHEMA_VERSION', '2.13'); // is or is not an official release of the plugin -define('PLUGIN_FORMCREATOR_IS_OFFICIAL_RELEASE', true); +define('PLUGIN_FORMCREATOR_IS_OFFICIAL_RELEASE', false); // Minimal GLPI version, inclusive define ('PLUGIN_FORMCREATOR_GLPI_MIN_VERSION', '10.0'); From 1b71d65272e54bf33f441d695f96a7816ca40bba Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Mon, 12 Jun 2023 11:00:36 +0200 Subject: [PATCH 32/58] fix(textfield): target ticket title need html encoding GLPI 10.0.7 HTML encodes data in ticket's title --- inc/field/textfield.class.php | 6 +----- tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/inc/field/textfield.class.php b/inc/field/textfield.class.php index e2fc5a93b..047f8b154 100644 --- a/inc/field/textfield.class.php +++ b/inc/field/textfield.class.php @@ -108,11 +108,7 @@ public function getValueForDesign(): string { } public function getValueForTargetText($domain, $richText): ?string { - if ($richText) { - return Sanitizer::encodeHtmlSpecialChars($this->value); - } - - return $this->value; + return Sanitizer::encodeHtmlSpecialChars($this->value); } public function moveUploads() { diff --git a/tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php b/tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php index 4a1c8c40d..434958506 100644 --- a/tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php +++ b/tests/3-unit/GlpiPlugin/Formcreator/Field/TextField.php @@ -401,7 +401,7 @@ public function providerGetValueForTargetText() { 'question' => $this->getQuestion(), 'value' => '">', 'expected' => true, - 'expectedValue' => '">', + 'expectedValue' => '"><img src=x onerror="alert(1337)" x=x>', ], ]; } From 0c47776a5093203708b3c1f4063e685e0ab29ef7 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 21 Jun 2023 10:24:04 +0200 Subject: [PATCH 33/58] fix(install): missing row in sql query, causing PHP warning --- install/upgrade_to_2.13.6.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/upgrade_to_2.13.6.php b/install/upgrade_to_2.13.6.php index d5a74d185..04c131cc6 100644 --- a/install/upgrade_to_2.13.6.php +++ b/install/upgrade_to_2.13.6.php @@ -71,7 +71,7 @@ public function migrateToRichText() { foreach ($tables as $table => $fields) { $request = [ - 'SELECT' => ['id'] + $fields, + 'SELECT' => array_merge(['id'], $fields), 'FROM' => $table ]; foreach ($DB->request($request) as $row) { From bd0b1a38a781ea4453afe7a736a1ed9754908ba3 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 21 Jun 2023 10:26:43 +0200 Subject: [PATCH 34/58] refactror(question): simplify code --- inc/abstracttarget.class.php | 8 +++++--- inc/question.class.php | 4 +--- inc/targetticket.class.php | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/inc/abstracttarget.class.php b/inc/abstracttarget.class.php index 8c9be59c3..f5da61431 100644 --- a/inc/abstracttarget.class.php +++ b/inc/abstracttarget.class.php @@ -217,11 +217,11 @@ protected function prepareTemplate($template, PluginFormcreatorFormAnswer $formA /** * Append fields data to input * - * @param PluginFormcreatorFormanswer $formanswer the source formanswer * @param array $input data of the generated target - * @return void + * @param PluginFormcreatorFormanswer $formanswer the source formanswer + * @return array */ - protected function appendFieldsData(PluginFormcreatorFormanswer $formanswer, &$input): void { + protected function appendFieldsData(array$input, PluginFormcreatorFormanswer $formanswer): array { global $DB; //get all PluginFormcreatorAnswer @@ -262,6 +262,8 @@ protected function appendFieldsData(PluginFormcreatorFormanswer $formanswer, &$i } $input['c_id'] = $blocks_field; } + + return $input; } diff --git a/inc/question.class.php b/inc/question.class.php index 419639a83..18edf3bde 100644 --- a/inc/question.class.php +++ b/inc/question.class.php @@ -279,8 +279,6 @@ public function getRenderedHtml($domain, $canEdit = true, ?PluginFormcreatorForm return ''; } - $html = ''; - $field = $this->getSubField(); if (!$field->isPrerequisites()) { return ''; @@ -292,7 +290,7 @@ public function getRenderedHtml($domain, $canEdit = true, ?PluginFormcreatorForm $x = $this->fields['col']; $width = $this->fields['width']; $hiddenAttribute = $isVisible ? '' : 'hidden=""'; - $html .= 'prepareUploadedFiles($data, $formanswer); - $this->appendFieldsData($formanswer, $data); + $data = $this->appendFieldsData($data, $formanswer); // Cleanup actors array $data = $this->cleanActors($data); From ab1ceac9caf21e2c9e612e2a93738f08c77af390 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 21 Jun 2023 12:26:26 +0200 Subject: [PATCH 35/58] style(abstracttarget): code style --- inc/abstracttarget.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/abstracttarget.class.php b/inc/abstracttarget.class.php index f5da61431..db46feff2 100644 --- a/inc/abstracttarget.class.php +++ b/inc/abstracttarget.class.php @@ -221,7 +221,7 @@ protected function prepareTemplate($template, PluginFormcreatorFormAnswer $formA * @param PluginFormcreatorFormanswer $formanswer the source formanswer * @return array */ - protected function appendFieldsData(array$input, PluginFormcreatorFormanswer $formanswer): array { + protected function appendFieldsData(array $input, PluginFormcreatorFormanswer $formanswer): array { global $DB; //get all PluginFormcreatorAnswer From 0a857d7f881750d2754ca85be7b171a9e70cd6df Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 21 Jun 2023 13:22:08 +0200 Subject: [PATCH 36/58] fix(textfield): exception while displaying counters text field with a null value cannot be HTML encoded --- inc/field/textfield.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/field/textfield.class.php b/inc/field/textfield.class.php index 047f8b154..044c6c0ee 100644 --- a/inc/field/textfield.class.php +++ b/inc/field/textfield.class.php @@ -108,7 +108,7 @@ public function getValueForDesign(): string { } public function getValueForTargetText($domain, $richText): ?string { - return Sanitizer::encodeHtmlSpecialChars($this->value); + return Sanitizer::encodeHtmlSpecialChars($this->value ?? ''); } public function moveUploads() { From 016696ab4ce6c02e780d84ed176389b205ae6f8e Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 21 Jun 2023 14:12:43 +0200 Subject: [PATCH 37/58] fix(targetchange,targetproblem): folow method call signature for fields plugin --- inc/targetchange.class.php | 2 +- inc/targetproblem.class.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/targetchange.class.php b/inc/targetchange.class.php index 06ad671f2..001a083e7 100644 --- a/inc/targetchange.class.php +++ b/inc/targetchange.class.php @@ -702,7 +702,7 @@ public function save(PluginFormcreatorFormAnswer $formanswer): ?CommonDBTM { $data = $this->prepareUploadedFiles($data, $formanswer); - $this->appendFieldsData($formanswer, $data); + $data = $this->appendFieldsData($data, $formanswer); // Cleanup actors array $data = $this->cleanActors($data); diff --git a/inc/targetproblem.class.php b/inc/targetproblem.class.php index 42d372757..61cc0707f 100644 --- a/inc/targetproblem.class.php +++ b/inc/targetproblem.class.php @@ -222,7 +222,7 @@ public function save(PluginFormcreatorFormAnswer $formanswer): ?CommonDBTM { $data = $this->prepareUploadedFiles($data, $formanswer); - $this->appendFieldsData($formanswer, $data); + $data = $this->appendFieldsData($data, $formanswer); // Cleanup actors array $data = $this->cleanActors($data); From 9272cda32000eac43a8b932ad8761a34701c3502 Mon Sep 17 00:00:00 2001 From: Adrien Clairembault <42734840+AdrienClairembault@users.noreply.github.com> Date: Wed, 21 Jun 2023 16:20:46 +0200 Subject: [PATCH 38/58] fix: resize dashboard to match GLPI's core (#3306) --- inc/common.class.php | 2 +- install/upgrade_to_2.13.7.php | 37 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/inc/common.class.php b/inc/common.class.php index 8efd52e69..af5bc2d93 100644 --- a/inc/common.class.php +++ b/inc/common.class.php @@ -871,7 +871,7 @@ public static function showMiniDashboard(): void { if (PluginFormcreatorEntityconfig::getUsedConfig('is_dashboard_visible', Session::getActiveEntity()) == PluginFormcreatorEntityconfig::CONFIG_DASHBOARD_VISIBLE) { if (version_compare(GLPI_VERSION, '10.0.3') > 0) { - $dashboard = new Glpi\Dashboard\Grid('plugin_formcreator_issue_counters', 33, 1, 'mini_core'); + $dashboard = new Glpi\Dashboard\Grid('plugin_formcreator_issue_counters', 33, 2, 'mini_core'); } else { $dashboard = new Glpi\Dashboard\Grid('plugin_formcreator_issue_counters', 33, 0, 'mini_core'); } diff --git a/install/upgrade_to_2.13.7.php b/install/upgrade_to_2.13.7.php index c1b99d387..bd2f9ce84 100644 --- a/install/upgrade_to_2.13.7.php +++ b/install/upgrade_to_2.13.7.php @@ -29,6 +29,8 @@ * --------------------------------------------------------------------- */ +use Glpi\Dashboard\Dashboard; +use Glpi\Dashboard\Item; use Glpi\Toolbox\Sanitizer; class PluginFormcreatorUpgradeTo2_13_7 { @@ -45,6 +47,7 @@ public function isResyncIssuesRequired() { public function upgrade(Migration $migration) { $this->migration = $migration; $this->fixEncodingInQuestions(); + $this->resizeWidgets(); } /** @@ -83,4 +86,38 @@ public function fixEncodingInQuestions() { ); } } + + /** + * Resize widgets of the `plugin_formcreator_issue_counters` dashboard to match + * the mini_tickets core dashboard style + * + * @return void + */ + public function resizeWidgets() { + // Get container + $dashboard = new Dashboard(); + $found = $dashboard->getFromDB("plugin_formcreator_issue_counters"); + + if (!$found) { + // Unable to fetch dashboard + return; + }; + + $di = new Item(); + $cards = $di->find(['dashboards_dashboards_id' => $dashboard->fields['id']]); + $x = 0; + + foreach ($cards as $card) { + $di = new Item(); + $di->update([ + 'id' => $card['id'], + 'width' => 4, + 'height' => 2, + 'x' => $x, + 'y' => 0, + ]); + + $x +=4; + } + } } From f6f01d7d93bc35c1a7914c1c42cab62bc8aaa329 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 21 Jun 2023 15:20:20 +0200 Subject: [PATCH 39/58] fix(issue): php warnings when anonymisation enabled --- inc/issue.class.php | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/inc/issue.class.php b/inc/issue.class.php index ee5187700..4b5d2e9ad 100644 --- a/inc/issue.class.php +++ b/inc/issue.class.php @@ -493,13 +493,25 @@ public function rawSearchOptions() { $hide_technician = false; $hide_technician_group = false; if (!Session::isCron()) { - $user = new User(); - if (empty($user->getAnonymizedName(Session::getActiveEntity()))) { - $hide_technician = true; - } - $group = new Group(); - if (empty($group->getAnonymizedName(Session::getActiveEntity()))) { - $hide_technician_group = true; + $anonymisation = Entity::getUsedConfig( + 'anonymize_support_agents', + Session::getActiveEntity() + ); + switch ($anonymisation) { + case Entity::ANONYMIZE_USE_GENERIC: + case Entity::ANONYMIZE_USE_NICKNAME: + $hide_technician = true; + $hide_technician_group = true; + break; + + case Entity::ANONYMIZE_USE_GENERIC_USER: + case Entity::ANONYMIZE_USE_NICKNAME_USER: + $hide_technician = true; + break; + + case Entity::ANONYMIZE_USE_GENERIC_GROUP: + $hide_technician_group = true; + break; } } From 52a9fc2b9c3cfaff5c6f5f2400672bfc4f8b8e45 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 21 Jun 2023 19:53:05 +0200 Subject: [PATCH 40/58] fix(fieldsfield): restore mandatory field as read only --- inc/question.class.php | 2 +- templates/field/fieldsfield.html.twig | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/inc/question.class.php b/inc/question.class.php index 18edf3bde..87d223e57 100644 --- a/inc/question.class.php +++ b/inc/question.class.php @@ -52,7 +52,7 @@ class PluginFormcreatorQuestion extends CommonDBChild implements static public $items_id = 'plugin_formcreator_sections_id'; /** @var PluginFormcreatorFieldInterface|null $field a field describing the question denpending on its field type */ - private ?PluginFormcreatorFieldInterface $field = null; + public ?PluginFormcreatorFieldInterface $field = null; private $skipChecks = false; diff --git a/templates/field/fieldsfield.html.twig b/templates/field/fieldsfield.html.twig index 9a7984cbe..e333cba0a 100644 --- a/templates/field/fieldsfield.html.twig +++ b/templates/field/fieldsfield.html.twig @@ -70,4 +70,20 @@ input_class: 'col-xxl-8', }) }} {% endif %} + + {{ fields.nullField({ + label_class: 'col-xxl-4', + input_class: 'col-xxl-8', + }) }} + + {{ fields.dropdownYesNo( + 'required', + item.field.getField().fields['mandatory'], + __('Required', 'formcreator'), { + label_class: 'col-xxl-4', + input_class: 'col-xxl-8', + disabled: true, + } + ) }} + {% endblock %} From 42dd84ea12511c177cd8f1f426ae5666bef26511 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Fri, 23 Jun 2023 10:27:30 +0200 Subject: [PATCH 41/58] refactor: use constant --- setup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.php b/setup.php index 85d4ffc20..2c88fc2be 100644 --- a/setup.php +++ b/setup.php @@ -337,7 +337,7 @@ function plugin_formcreator_hook(): void { Session::getCurrentInterface() == 'helpdesk') { // Add specific JavaScript - $PLUGIN_HOOKS['add_javascript']['formcreator'][] = 'js/scripts.js'; + $PLUGIN_HOOKS[Hooks::ADD_JAVASCRIPT]['formcreator'][] = 'js/scripts.js'; } if (isset($_SESSION['glpiactiveentities_string'])) { From eb0acb6543b34e71a704b5b851e344d411414a92 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Fri, 23 Jun 2023 14:09:41 +0200 Subject: [PATCH 42/58] fix(formanswer): redirect to login if session expired --- front/formanswer.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/front/formanswer.php b/front/formanswer.php index 60279beba..ce2f6e723 100644 --- a/front/formanswer.php +++ b/front/formanswer.php @@ -36,6 +36,8 @@ Html::displayNotFoundError(); } +Session::checkLoginUser(); + if (!PluginFormcreatorFormAnswer::canView()) { Html::displayRightError(); } From 144fc49df28d9e57ab4bf80824bfd72485ede45f Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Fri, 23 Jun 2023 14:10:32 +0200 Subject: [PATCH 43/58] refactor(question): useless instanciation --- inc/question.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/inc/question.class.php b/inc/question.class.php index 87d223e57..602c0c1fa 100644 --- a/inc/question.class.php +++ b/inc/question.class.php @@ -352,7 +352,6 @@ private function checkBeforeSave($input) : array { return []; } // - field type is compatible with accessibility of the form - $form = PluginFormcreatorCommon::getForm(); $section = PluginFormcreatorSection::getById($input[PluginFormcreatorSection::getForeignKeyField()]); $form = PluginFormcreatorForm::getByItem($section); if ($form->isPublicAccess() && !$this->field->isPublicFormCompatible()) { From bd25e7d17dfb5942cab4a86624163532944c48af Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Fri, 23 Jun 2023 14:11:51 +0200 Subject: [PATCH 44/58] fix(dropdownfield): handle specific case with Entity itemtype --- inc/field/dropdownfield.class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/inc/field/dropdownfield.class.php b/inc/field/dropdownfield.class.php index 17193ffb4..d6dc4251d 100644 --- a/inc/field/dropdownfield.class.php +++ b/inc/field/dropdownfield.class.php @@ -304,14 +304,15 @@ public function buildParams($rand = null) { // Set specific root if defined (CommonTreeDropdown) $baseLevel = 0; if (isset($decodedValues['show_tree_root']) - && (int) $decodedValues['show_tree_root'] > 0 + && ((int) $decodedValues['show_tree_root'] > 0 + || $itemtype == Entity::class && (int) $decodedValues['show_tree_root'] > -1) ) { $sons = (new DBUtils)->getSonsOf( $itemtype::getTable(), $decodedValues['show_tree_root'] ); $decodedValues['selectable_tree_root'] = $decodedValues['selectable_tree_root'] ?? '1'; - if (!isset($decodedValues['selectable_tree_root']) || $decodedValues['selectable_tree_root'] == '0') { + if ($decodedValues['selectable_tree_root'] == '0') { unset($sons[$decodedValues['show_tree_root']]); } From 918e72da14114d7e95c33a467fec254829f7709a Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Fri, 23 Jun 2023 15:27:28 +0200 Subject: [PATCH 45/58] refactor(formanswer): remove useless canonical class name --- ajax/formanswer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ajax/formanswer.php b/ajax/formanswer.php index b48ff297f..680f400a9 100644 --- a/ajax/formanswer.php +++ b/ajax/formanswer.php @@ -55,7 +55,7 @@ // Save form $backup_debug = $_SESSION['glpi_use_mode']; -$_SESSION['glpi_use_mode'] = \Session::NORMAL_MODE; +$_SESSION['glpi_use_mode'] = Session::NORMAL_MODE; $formAnswer = PluginFormcreatorCommon::getFormAnswer(); if ($formAnswer->add($_POST) === false) { http_response_code(400); From a07dddded58b6d85adc57dff4f26b7c2661e025f Mon Sep 17 00:00:00 2001 From: WebGregGit <68922721+WebGregGit@users.noreply.github.com> Date: Thu, 29 Jun 2023 11:12:01 +0200 Subject: [PATCH 46/58] Update pl_PL.po Correcting the typo --- locales/pl_PL.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/pl_PL.po b/locales/pl_PL.po index a412205db..689799f41 100644 --- a/locales/pl_PL.po +++ b/locales/pl_PL.po @@ -1515,7 +1515,7 @@ msgstr "Brak formularzy oczekujących na zatwierdzenie" #: inc/form.class.php:1035 msgid "All my forms (validator)" -msgstr "Moje wszystkie formilarze (zatwierdzający)" +msgstr "Moje wszystkie formularze (zatwierdzający)" #: inc/form.class.php:1095 inc/form.class.php:1229 #: inc/abstracttarget.class.php:162 inc/abstractitiltarget.class.php:1573 From c4277d8c9bbe1edde77d1b682cb05facc6a0fb9c Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 4 Jul 2023 08:23:46 +0200 Subject: [PATCH 47/58] fix(section): rename section impacts display of inner questions --- js/scripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/scripts.js b/js/scripts.js index 0cf0cf744..7c39d3b34 100644 --- a/js/scripts.js +++ b/js/scripts.js @@ -1043,7 +1043,7 @@ var plugin_formcreator = new function() { displayAjaxMessageAfterRedirect(); }).done(function (data) { var section = $('.plugin_formcreator_form_design[data-itemtype="PluginFormcreatorForm"] [data-itemtype="PluginFormcreatorSection"][data-id="' + sectionId + '"]'); - section.find('[data-field="name"]').replaceWith(data['name']); + section.find(' > [data-field="name"]').replaceWith(data['name']); that.resetTabs(); }).complete(function () { var myModal = form.closest('div.modal'); From 7bbb9b81bed9de4f66481b425ee7846163598b20 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Tue, 4 Jul 2023 08:25:40 +0200 Subject: [PATCH 48/58] fix(section): cannot rename section twice --- inc/section.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/section.class.php b/inc/section.class.php index a5e4ca4c5..1bea5ebb3 100644 --- a/inc/section.class.php +++ b/inc/section.class.php @@ -552,7 +552,7 @@ public function getDesignLabel(): string { ]); $formId = $this->fields[PluginFormcreatorForm::getForeignKeyField()]; $onclick = 'plugin_formcreator.showSectionForm(' . $formId . ', ' . $sectionId . ');'; - $html = ''; + $html = ''; $html .= "$nb"; $html .= ''; $html .= empty($this->fields['name']) ? '(' . $sectionId . ')' : $this->fields['name']; From 22597832a09eb005fd34866f14c7fd95c5703f20 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Thu, 6 Jul 2023 10:59:36 +0200 Subject: [PATCH 49/58] fix(question,section): duplicate a question or section must duplicate inner conditions --- inc/question.class.php | 15 +++++++++++++++ inc/section.class.php | 14 ++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/inc/question.class.php b/inc/question.class.php index 602c0c1fa..48b498c51 100644 --- a/inc/question.class.php +++ b/inc/question.class.php @@ -772,6 +772,21 @@ public function duplicate(array $options = []) { $export[$key] = $value; } } + + // Before importing the question, we need to give to the linker the questions + // used in the conditions of the question being duplicated + $conditions = (new PluginFormcreatorCondition())->find([ + 'itemtype' => self::getType(), + 'items_id' => $this->getID() + ]); + foreach ($conditions as $row) { + $question = PluginFormcreatorQuestion::getById($row['plugin_formcreator_questions_id']); + if ($question === null || $question === false) { + continue; + } + $linker->addObject($row['plugin_formcreator_questions_id'], $question); + } + $newQuestionId = static::import($linker, $export, $this->fields[$sectionFk]); if ($newQuestionId === false) { diff --git a/inc/section.class.php b/inc/section.class.php index 1bea5ebb3..5f877aa0a 100644 --- a/inc/section.class.php +++ b/inc/section.class.php @@ -239,6 +239,20 @@ public function duplicate(array $options = []) { ) + 1; $newSectionId = static::import($linker, $export, $this->fields[$formFk]); + // Before importing the section, we need to give to the linker the questions + // used in the conditions of the section being duplicated + $conditions = (new PluginFormcreatorCondition())->find([ + 'itemtype' => self::getType(), + 'items_id' => $this->getID() + ]); + foreach ($conditions as $row) { + $question = PluginFormcreatorQuestion::getById($row['plugin_formcreator_questions_id']); + if ($question === null || $question === false) { + continue; + } + $linker->addObject($row['plugin_formcreator_questions_id'], $question); + } + if ($newSectionId === false) { return false; } From 03e6281ee30665b907287018bd29bbe89c0e9903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Cailly?= Date: Mon, 26 Jun 2023 10:05:53 +0200 Subject: [PATCH 50/58] fix: Adding READ right for display reservations menu tab --- inc/common.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/common.class.php b/inc/common.class.php index af5bc2d93..8174bf630 100644 --- a/inc/common.class.php +++ b/inc/common.class.php @@ -806,7 +806,7 @@ public static function hookRedefineMenu($menus) { $newMenu['faq'] = $menus['faq']; $newMenu['faq']['default'] = Plugin::getWebDir('formcreator', false) . '/front/knowbaseitem.php'; } - if (Session::haveRight("reservation", ReservationItem::RESERVEANITEM)) { + if (Session::haveRightsOr("reservation", [READ, ReservationItem::RESERVEANITEM])) { if (isset($menus['reservation'])) { $newMenu['reservation'] = $menus['reservation']; } From 8845b88815f9dfa7ae0ec282b381d9a3d276a112 Mon Sep 17 00:00:00 2001 From: stonebuzz Date: Tue, 11 Jul 2023 14:41:45 +0200 Subject: [PATCH 51/58] fix(TargetChange): use RichText instead of plaintext --- inc/targetchange.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/targetchange.class.php b/inc/targetchange.class.php index 001a083e7..c18797f3c 100644 --- a/inc/targetchange.class.php +++ b/inc/targetchange.class.php @@ -664,11 +664,11 @@ public function save(PluginFormcreatorFormAnswer $formanswer): ?CommonDBTM { $data[$changeField] = $this->prepareTemplate( Sanitizer::unsanitize(__($this->fields[$changeField], $domain)) ?? '', $formanswer, - $changeField == 'content' // only content supports rich text + true // all *content supports rich text ); $data[$changeField] = $data[$changeField] ?? ''; - $data[$changeField] = $formanswer->parseTags($data[$changeField], $this, $changeField == 'content'); + $data[$changeField] = $formanswer->parseTags($data[$changeField], $this, true); // all *content supports rich text } $data['_users_id_recipient'] = $formanswer->fields['requester_id']; From 54543cb360e4cc6a32d53e9acb269aa180e4b20c Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Wed, 19 Jul 2023 11:36:49 +0200 Subject: [PATCH 52/58] fix(dropdownfield): missing entity restriction setting --- inc/field/dropdownfield.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/field/dropdownfield.class.php b/inc/field/dropdownfield.class.php index d6dc4251d..a4ce6a0a8 100644 --- a/inc/field/dropdownfield.class.php +++ b/inc/field/dropdownfield.class.php @@ -41,6 +41,7 @@ use DBUtils; use Document; use Dropdown; +use CommonDBTM; use CommonITILActor; use CommonITILObject; use CommonTreeDropdown; From c5499ad4520f46c8a2b170e277b16c0b662cf094 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Mon, 31 Jul 2023 15:39:01 +0200 Subject: [PATCH 53/58] fix: show FAQ without tabs for self-service --- js/scripts.js | 2 +- setup.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/scripts.js b/js/scripts.js index 7c39d3b34..1ef28519e 100644 --- a/js/scripts.js +++ b/js/scripts.js @@ -396,7 +396,7 @@ function buildTiles(list) { // Build a HTML tile var url = formcreatorRootDoc + '/front/formdisplay.php?id=' + item.id; if (item.type != 'form') { - url = rootDoc + '/front/knowbaseitem.form.php?id=' + item.id; + url = rootDoc + '/front/helpdesk.faq.php?id=' + item.id; } var tiles_design = ""; diff --git a/setup.php b/setup.php index 2c88fc2be..0ebeba6a8 100644 --- a/setup.php +++ b/setup.php @@ -515,7 +515,7 @@ function plugin_formcreator_redirect() { $pages = [ 'front/reservationitem.php' => FORMCREATOR_ROOTDOC . '/front/reservationitem.php', - 'front/helpdesk.faq.php' => FORMCREATOR_ROOTDOC . '/front/wizard.php', + // 'front/helpdesk.faq.php' => FORMCREATOR_ROOTDOC . '/front/wizard.php', 'front/ticket.php' => FORMCREATOR_ROOTDOC . '/front/issue.php', ]; foreach ($pages as $srcPage => $dstPage) { From 5f2604aa58cb8c698014e0aef77075405ec56539 Mon Sep 17 00:00:00 2001 From: AdrienClairembault Date: Tue, 1 Aug 2023 11:15:47 +0200 Subject: [PATCH 54/58] Fix default document category --- inc/targetticket.class.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/inc/targetticket.class.php b/inc/targetticket.class.php index a20f6f32c..8620abaec 100644 --- a/inc/targetticket.class.php +++ b/inc/targetticket.class.php @@ -803,6 +803,8 @@ protected function getTargetTemplate(array $data): int { * @return Ticket|null Generated ticket if success, null otherwise */ public function save(PluginFormcreatorFormAnswer $formanswer): ?CommonDBTM { + global $CFG_GLPI; + $ticket = new Ticket(); $form = $formanswer->getForm(); $data = $this->getDefaultData($formanswer); @@ -904,6 +906,22 @@ public function save(PluginFormcreatorFormAnswer $formanswer): ?CommonDBTM { return null; } + // Set default document category + $document_category = $CFG_GLPI['documentcategories_id_forticket'] ?? 0; + if ($document_category) { + foreach (array_keys($this->attachedDocuments) as $documents_id) { + $document = Document::getById($documents_id); + if (!$document) { + continue; + } + + $document->update([ + 'id' => $document->fields['id'], + 'documentcategories_id' => $document_category, + ]); + } + } + $this->saveTags($formanswer, $ticketID); // Add link between Ticket and FormAnswer From 6201d61da1e29dca80ebeebc1d75fbc041606fcb Mon Sep 17 00:00:00 2001 From: Rom1-B Date: Mon, 21 Aug 2023 15:48:20 +0200 Subject: [PATCH 55/58] fix(tag): tag was always deleted --- inc/targetchange.class.php | 4 ++-- inc/targetproblem.class.php | 4 ++-- inc/targetticket.class.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/inc/targetchange.class.php b/inc/targetchange.class.php index c18797f3c..1f8facab4 100644 --- a/inc/targetchange.class.php +++ b/inc/targetchange.class.php @@ -712,8 +712,6 @@ public function save(PluginFormcreatorFormAnswer $formanswer): ?CommonDBTM { return null; } - $this->saveTags($formanswer, $changeID); - // Add link between Change and FormAnswer $itemlink = $this->getItem_Item(); $itemlink->add([ @@ -722,6 +720,8 @@ public function save(PluginFormcreatorFormAnswer $formanswer): ?CommonDBTM { 'changes_id' => $changeID, ]); + $this->saveTags($formanswer, $changeID); + return $change; } diff --git a/inc/targetproblem.class.php b/inc/targetproblem.class.php index 61cc0707f..3e911a9e3 100644 --- a/inc/targetproblem.class.php +++ b/inc/targetproblem.class.php @@ -232,8 +232,6 @@ public function save(PluginFormcreatorFormAnswer $formanswer): ?CommonDBTM { return null; } - $this->saveTags($formanswer, $problemID); - // Add link between Problem and FormAnswer $itemlink = $this->getItem_Item(); $itemlink->add([ @@ -242,6 +240,8 @@ public function save(PluginFormcreatorFormAnswer $formanswer): ?CommonDBTM { 'problems_id' => $problemID, ]); + $this->saveTags($formanswer, $problemID); + return $problem; } diff --git a/inc/targetticket.class.php b/inc/targetticket.class.php index 8620abaec..fd2d92b35 100644 --- a/inc/targetticket.class.php +++ b/inc/targetticket.class.php @@ -922,8 +922,6 @@ public function save(PluginFormcreatorFormAnswer $formanswer): ?CommonDBTM { } } - $this->saveTags($formanswer, $ticketID); - // Add link between Ticket and FormAnswer $itemlink = $this->getItem_Item(); $itemlink->add([ @@ -932,6 +930,8 @@ public function save(PluginFormcreatorFormAnswer $formanswer): ?CommonDBTM { 'tickets_id' => $ticketID, ]); + $this->saveTags($formanswer, $ticketID); + // Attach validation message as first ticket followup if validation is required and // if is set in ticket target configuration if ($form->validationRequired() && $this->fields['validation_followup']) { From 4bd2c3e65f417afcd97ec503011c70fb16523935 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Mon, 21 Aug 2023 10:36:28 +0200 Subject: [PATCH 56/58] build(2.13.7): release 2.13.7 --- CHANGELOG.md | 41 +++++++++++++++++++++++++++++++++++++++++ plugin.xml | 5 +++++ setup.php | 2 +- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcedef755..f3c59eeda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,44 @@ + +## [2.13.7](https://github.com/pluginsGLPI/formcreator/compare/2.13.6..2.13.7) (2023-07-19) + + +### Bug Fixes + +* Adding READ right for display reservations menu tab ([03e6281e](https://github.com/pluginsGLPI/formcreator/commit/03e6281e)) +* bad lcoale in en_US ([db9986f1](https://github.com/pluginsGLPI/formcreator/commit/db9986f1)) +* resize dashboard to match GLPI's core (#3306) ([9272cda3](https://github.com/pluginsGLPI/formcreator/commit/9272cda3)) +* show FAQ without tabs for self-service ([c5499ad4](https://github.com/pluginsGLPI/formcreator/commit/c5499ad4)) +* **TargetChange:** use RichText instead of plaintext ([8845b888](https://github.com/pluginsGLPI/formcreator/commit/8845b888)) +* **checkboxesfield,radiosfield,selectfield:** add missing error messages ([66585193](https://github.com/pluginsGLPI/formcreator/commit/66585193)) +* **datefield, datetimefield:** comparison against empty string ([be4831c7](https://github.com/pluginsGLPI/formcreator/commit/be4831c7)) +* **dropdownfield:** SQL error for GLPI objects / tickets and some specific rights ([2539e366](https://github.com/pluginsGLPI/formcreator/commit/2539e366)) +* **dropdownfield:** handle specific case with Entity itemtype ([bd25e7d1](https://github.com/pluginsGLPI/formcreator/commit/bd25e7d1)) +* **dropdownfield:** missing entity restriction setting ([54543cb3](https://github.com/pluginsGLPI/formcreator/commit/54543cb3)) +* **dropdownfield:** prevent language switching and log error ([49f8fc07](https://github.com/pluginsGLPI/formcreator/commit/49f8fc07)) +* **fieldsfield:** restore mandatory field as read only ([52a9fc2b](https://github.com/pluginsGLPI/formcreator/commit/52a9fc2b)) +* **form,category:** obey show count on tabs parameter ([f4ebf9e5](https://github.com/pluginsGLPI/formcreator/commit/f4ebf9e5)) +* **form_language:** obey show counter in tab setting ([9dfc3b8d](https://github.com/pluginsGLPI/formcreator/commit/9dfc3b8d)) +* **formanswer:** php warning ([ce078990](https://github.com/pluginsGLPI/formcreator/commit/ce078990)) +* **formanswer:** prevent silent rejection of answers ([d630302d](https://github.com/pluginsGLPI/formcreator/commit/d630302d)) +* **formanswer:** redirect to login if session expired ([eb0acb65](https://github.com/pluginsGLPI/formcreator/commit/eb0acb65)) +* **glpiselectfield:** fix namespace (#3287) ([613e0fad](https://github.com/pluginsGLPI/formcreator/commit/613e0fad)) +* **install:** missing row in sql query, causing PHP warning ([0c47776a](https://github.com/pluginsGLPI/formcreator/commit/0c47776a)) +* **issue:** php warnings when anonymisation enabled ([f6f01d7d](https://github.com/pluginsGLPI/formcreator/commit/f6f01d7d)) +* **issue:** prevent fatal error in tooltip ([3419affc](https://github.com/pluginsGLPI/formcreator/commit/3419affc)) +* **question,section:** duplicate a question or section must duplicate inner conditions ([22597832](https://github.com/pluginsGLPI/formcreator/commit/22597832)) +* **section:** cannot rename section twice ([7bbb9b81](https://github.com/pluginsGLPI/formcreator/commit/7bbb9b81)) +* **section:** condition rule loss after duplicate / import ([883a1227](https://github.com/pluginsGLPI/formcreator/commit/883a1227)) +* **section:** duplicate form may lead to bad question id in condition ([a6f9c41c](https://github.com/pluginsGLPI/formcreator/commit/a6f9c41c)) +* **section:** rename section impacts display of inner questions ([c4277d8c](https://github.com/pluginsGLPI/formcreator/commit/c4277d8c)) +* **selectfield,multiselectfield:** fix possible encoding problem ([8aaec8ac](https://github.com/pluginsGLPI/formcreator/commit/8aaec8ac)) +* **tag:** tag was always deleted ([6201d61d](https://github.com/pluginsGLPI/formcreator/commit/6201d61d)) +* **targetchange,targetproblem:** folow method call signature for fields plugin ([016696ab](https://github.com/pluginsGLPI/formcreator/commit/016696ab)) +* **textfield:** Unescaped HTML when displaying a form answer ([6ce71f95](https://github.com/pluginsGLPI/formcreator/commit/6ce71f95)) +* **textfield:** exception while displaying counters ([0a857d7f](https://github.com/pluginsGLPI/formcreator/commit/0a857d7f)) +* **textfield:** target ticket title need html encoding ([1b71d652](https://github.com/pluginsGLPI/formcreator/commit/1b71d652)) + + + ## [2.13.6](https://github.com/pluginsGLPI/formcreator/compare/2.13.5..2.13.6) (2023-05-26) diff --git a/plugin.xml b/plugin.xml index 54f0c5822..dc7eeaa09 100644 --- a/plugin.xml +++ b/plugin.xml @@ -58,6 +58,11 @@ Features Teclib' + + 2.13.7 + ~10.0 + https://github.com/pluginsGLPI/formcreator/releases/download/2.13.7/glpi-formcreator-2.13.7.tar.bz2 + 2.13.6 ~10.0 diff --git a/setup.php b/setup.php index 0ebeba6a8..865d211b5 100644 --- a/setup.php +++ b/setup.php @@ -37,7 +37,7 @@ // Schema version of this version (major.minor only) define('PLUGIN_FORMCREATOR_SCHEMA_VERSION', '2.13'); // is or is not an official release of the plugin -define('PLUGIN_FORMCREATOR_IS_OFFICIAL_RELEASE', false); +define('PLUGIN_FORMCREATOR_IS_OFFICIAL_RELEASE', true); // Minimal GLPI version, inclusive define ('PLUGIN_FORMCREATOR_GLPI_MIN_VERSION', '10.0'); From 8729238ce6aead4fd5e1e3f76a941da714b6bbeb Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Mon, 21 Aug 2023 10:37:26 +0200 Subject: [PATCH 57/58] docs: bump version in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5925b3fc5..6e0588487 100644 --- a/package.json +++ b/package.json @@ -13,5 +13,5 @@ "tag": true } }, - "version": "2.13.6" + "version": "2.13.7" } From a3f16ace7b51a4f7b6fd99781bddfb8561a3dec1 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Mon, 21 Aug 2023 10:37:27 +0200 Subject: [PATCH 58/58] docs(locales): update translations --- locales/pl_PL.mo | Bin 30341 -> 30341 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/locales/pl_PL.mo b/locales/pl_PL.mo index cc5f87348e06e8dff3c3b65f5958f93f6daccc98..98570633aa1a78c2eceace86cb895333ceb65303 100644 GIT binary patch delta 18 ZcmZpD%h>vsaf6EQvsaf6C4W9DX6-vmtnJ0%7n