Skip to content

Commit

Permalink
Forms: add tag manager class; insert tag content into the generated t…
Browse files Browse the repository at this point in the history
…ickets
  • Loading branch information
AdrienClairembault committed May 16, 2024
1 parent 81e5472 commit 78b30d9
Show file tree
Hide file tree
Showing 11 changed files with 289 additions and 27 deletions.
15 changes: 3 additions & 12 deletions ajax/form/form_tags.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,14 @@
*/

use Glpi\Form\Form;
use Glpi\Form\Tag\FormTagsManager;

include('../../inc/includes.php');

// The user must be able to respond to forms.
Session::checkRight(Form::$rightname, UPDATE);

// Get tags
$tags = [
[
'label' => 'Exemple tag 1',
],
[
'label' => 'Exemple tag 2',
],
[
'label' => 'Exemple tag 3',
],
];
$tag_manager = new FormTagsManager();
header('Content-Type: application/json');
echo json_encode($tags);
echo json_encode($tag_manager->getTags());
15 changes: 3 additions & 12 deletions js/RichText/FormTags.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,26 +81,17 @@ GLPI.RichText.FormTags = class
const data = await $.get(url);

return data.map((tag) => ({
// The `tag` variable is a json encoded instance of Glpi\Form\Tag\Tag
type: 'autocompleteitem',
value: JSON.stringify(tag),
value: tag.html,
text: tag.label,
}));
}

#insertTag(autocompleteApi, range, value) {
this.#editor.selection.setRng(range);
this.#editor.insertContent(this.#generateTagHtml(value));
this.#editor.insertContent(value + " ");

autocompleteApi.hide();
}

#generateTagHtml(value) {
const tag = JSON.parse(value);
return `
<span
contenteditable="false"
data-form-tag="true"
>${tag.label}</span>&nbsp;
`;
}
};
4 changes: 3 additions & 1 deletion src/Form/Destination/CommonITILField/ContentField.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

use Glpi\Application\View\TemplateRenderer;
use Glpi\Form\Destination\ConfigFieldInterface;
use Glpi\Form\Tag\FormTagsManager;
use Override;

class ContentField implements ConfigFieldInterface
Expand Down Expand Up @@ -91,7 +92,8 @@ public function applyConfiguratedValue(array $input, ?array $config): array
return $input;
}

$input['content'] = $config['value'];
$tag_manager = new FormTagsManager();
$input['content'] = $tag_manager->insertTagsContent($config['value']);

return $input;
}
Expand Down
72 changes: 72 additions & 0 deletions src/Form/Tag/FormTagsManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

/**
* ---------------------------------------------------------------------
*
* GLPI - Gestionnaire Libre de Parc Informatique
*
* http://glpi-project.org
*
* @copyright 2015-2024 Teclib' and contributors.
* @copyright 2003-2014 by the INDEPNET Development Team.
* @licence https://www.gnu.org/licenses/gpl-3.0.html
*
* ---------------------------------------------------------------------
*
* LICENSE
*
* This file is part of GLPI.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* ---------------------------------------------------------------------
*/

namespace Glpi\Form\Tag;

final class FormTagsManager
{
public function getTags(): array
{
return [
new Tag(label: "Exemple tag 1", value: "exemple-tag-1"),
new Tag(label: "Exemple tag 2", value: "exemple-tag-2"),
new Tag(label: "Exemple tag 3", value: "exemple-tag-3"),
];
}

public function insertTagsContent(string $content): string
{
return preg_replace_callback(
'/<span.*?data-form-tag="true".*?>.*?<\/span>/',
function ($match) {
$tag = $match[0];

// Extract value.
preg_match('/data-form-tag-value="([^"]+)"/', $tag, $value_match);
if (empty($value_match)) {
return "";
}

// For now, we return the raw value.
// In futures improvements, the value will be an id and we will
// need to call some kind of object here to transform the id into
// the right string value (for exemple, transforming a question
// id into its name).
return $value_match[1];
},
$content
);
}
}
66 changes: 66 additions & 0 deletions src/Form/Tag/Tag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

/**
* ---------------------------------------------------------------------
*
* GLPI - Gestionnaire Libre de Parc Informatique
*
* http://glpi-project.org
*
* @copyright 2015-2024 Teclib' and contributors.
* @copyright 2003-2014 by the INDEPNET Development Team.
* @licence https://www.gnu.org/licenses/gpl-3.0.html
*
* ---------------------------------------------------------------------
*
* LICENSE
*
* This file is part of GLPI.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* ---------------------------------------------------------------------
*/

namespace Glpi\Form\Tag;

/**
* Simple data structure that will be json_encoded and sent to the
* GLPI.RichText.FormTags component.
*/
final readonly class Tag
{
public string $label;
public string $html;

public function __construct(
string $label,
string $value,
) {
$this->label = $label;

// Build HTML representation of the tag.
$properties = [
"contenteditable" => "false",
"data-form-tag" => "true",
"data-form-tag-value" => $value,
];
$properties = implode(" ", array_map(
fn($key, $value) => sprintf('%s="%s"', htmlspecialchars($key), htmlspecialchars($value)),
array_keys($properties),
array_values($properties),
));
$this->html = sprintf('<span %s>%s</span>', $properties, htmlspecialchars($label));
}
}
1 change: 1 addition & 0 deletions src/RichText/RichText.php
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ private static function getHtmlSanitizer(): HtmlSanitizer
'data-user-mention',
'data-user-id',
'data-form-tag',
'data-form-tag-value',
];
foreach ($rich_text_completion_attributes as $attribute) {
$config = $config->allowAttribute($attribute, 'span');
Expand Down
2 changes: 2 additions & 0 deletions tests/cypress/e2e/form_tags.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ describe('Form tags', () => {
.findByText("Exemple tag 3")
.should('have.attr', 'contenteditable', 'false')
.should('have.attr', 'data-form-tag', 'true')
.should('have.attr', 'data-form-tag-value', 'exemple-tag-3')
;

// Save form
Expand All @@ -86,6 +87,7 @@ describe('Form tags', () => {
.findByText("Exemple tag 3")
.should('have.attr', 'contenteditable', 'false')
.should('have.attr', 'data-form-tag', 'true')
.should('have.attr', 'data-form-tag-value', 'exemple-tag-3')
;
});
});
12 changes: 10 additions & 2 deletions tests/units/Glpi/Form/Destination/FormDestinationTicket.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
namespace tests\units\Glpi\Form\Destination;

use Glpi\Form\AnswersHandler\AnswersHandler;
use Glpi\Form\Form;
use Glpi\Form\QuestionType\QuestionTypeShortText;
use Glpi\Form\Tag\Tag;
use Glpi\Tests\Form\Destination\AbstractFormDestinationType;
use Glpi\Tests\FormBuilder;
use Glpi\Tests\FormTesterTrait;
Expand All @@ -61,6 +63,10 @@ public function testCreateDestinations(): void
$answers_handler = AnswersHandler::getInstance();

// Create a form with a single FormDestinationTicket destination
$tag = new Tag(
label: "Exemple tag 3",
value: "exemple-tag-3"
);
$form = $this->createForm(
(new FormBuilder("Test form 1"))
->addQuestion("Name", QuestionTypeShortText::class)
Expand All @@ -69,7 +75,7 @@ public function testCreateDestinations(): void
'test',
[
'title' => ['value' => 'Ticket title'],
'content' => ['value' => 'Ticket content'],
'content' => ['value' => "Ticket content: $tag->html"],
]
)
);
Expand All @@ -87,7 +93,9 @@ public function testCreateDestinations(): void

// Check fields
$ticket = current($tickets);
$this->string($ticket['content'])->isEqualTo('Ticket content');
$this->string($ticket['content'])
->isEqualTo('Ticket content: exemple-tag-3')
;

// Make sure link with the form answers was created too
$ticket = array_pop($tickets);
Expand Down
69 changes: 69 additions & 0 deletions tests/units/Glpi/Form/Tag/FormTagsManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

/**
* ---------------------------------------------------------------------
*
* GLPI - Gestionnaire Libre de Parc Informatique
*
* http://glpi-project.org
*
* @copyright 2015-2024 Teclib' and contributors.
* @copyright 2003-2014 by the INDEPNET Development Team.
* @licence https://www.gnu.org/licenses/gpl-3.0.html
*
* ---------------------------------------------------------------------
*
* LICENSE
*
* This file is part of GLPI.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* ---------------------------------------------------------------------
*/

namespace tests\units\Glpi\Form\Tag;

use GLPITestCase;
use Glpi\Form\Tag\Tag;

final class FormTagsManager extends GLPITestCase
{
public function testGetTags()
{
$tag_manager = new \Glpi\Form\Tag\FormTagsManager();
$tags = $tag_manager->getTags();
$this->array($tags)->isNotEmpty();

foreach ($tags as $tag) {
$this->object($tag)->isInstanceOf(Tag::class);
}
}

public function testInsertTagsContent()
{
$tag_manager = new \Glpi\Form\Tag\FormTagsManager();
$tag_1 = new Tag(label: "Exemple tag 1", value: "exemple-tag-1");
$tag_2 = new Tag(label: "Exemple tag 2", value: "exemple-tag-2");
$tag_3 = new Tag(label: "Exemple tag 3", value: "exemple-tag-3");

$content_with_tag =
"My content: $tag_1->html, $tag_2->html and $tag_3->html"
;
$computed_content = $tag_manager->insertTagsContent($content_with_tag);
$this->string($computed_content)->isEqualTo(
'My content: exemple-tag-1, exemple-tag-2 and exemple-tag-3'
);
}
}
Loading

0 comments on commit 78b30d9

Please sign in to comment.