diff --git a/CHANGELOG.md b/CHANGELOG.md index cdcf090..177d77c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Avoid a per-tag database lookup when rendering the tag column in item lists +- Fix tag associate item ## [2.14.6] - 2026-08-04 diff --git a/ajax/add_item_to_tag.php b/ajax/add_item_to_tag.php new file mode 100644 index 0000000..1ab6624 --- /dev/null +++ b/ajax/add_item_to_tag.php @@ -0,0 +1,70 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2014-2026 by Teclib'. + * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/pluginsGLPI/tag + * ------------------------------------------------------------------------- + */ + +use Glpi\Exception\Http\BadRequestHttpException; +use Glpi\Exception\Http\AccessDeniedHttpException; + +Session::checkLoginUser(); + +if (!isset($_POST['plugin_tag_tags_id'], $_POST['itemtype'], $_POST['items_id'])) { + throw new BadRequestHttpException(__s('Missing parameters', 'tag')); +} + +$tag = new PluginTagTag(); +if (!$tag->getFromDB($_POST['plugin_tag_tags_id']) || !$tag->can($tag->getID(), UPDATE)) { + throw new AccessDeniedHttpException(__s('You do not have permission to update this tag', 'tag')); +} + +$itemtype = $_POST['itemtype']; +if (!is_a($itemtype, CommonDBTM::class, true) || !PluginTagTag::canItemtype($itemtype)) { + throw new BadRequestHttpException(__s('Invalid item type', 'tag')); +} + +$item = new $itemtype(); +if (!$item->getFromDB($_POST['items_id']) || !$item->canUpdateItem()) { + throw new AccessDeniedHttpException(__s('You do not have permission to update this item', 'tag')); +} + +$tag_item = new PluginTagTagItem(); +$found = $tag_item->find([ + 'plugin_tag_tags_id' => $tag->getID(), + 'items_id' => $item->getID(), + 'itemtype' => $itemtype, +]); + +if (count($found) === 0) { + $tag_item->add([ + 'plugin_tag_tags_id' => $tag->getID(), + 'items_id' => $item->getID(), + 'itemtype' => $itemtype, + ]); +} + +Html::back(); diff --git a/inc/tagitem.class.php b/inc/tagitem.class.php index f06709c..56ae802 100644 --- a/inc/tagitem.class.php +++ b/inc/tagitem.class.php @@ -197,7 +197,7 @@ public static function showForTag(PluginTagTag $tag) if ($canedit) { echo "
"; echo "
"; + action='" . plugin_tag_geturl() . "/ajax/add_item_to_tag.php'>"; echo ""; echo ""; diff --git a/tests/TagTestCase.php b/tests/TagTestCase.php index d5a5ae5..d48b261 100644 --- a/tests/TagTestCase.php +++ b/tests/TagTestCase.php @@ -46,7 +46,7 @@ protected function logOut() $_SESSION['glpi_currenttime'] = $ctime; } - public function loginAs(array $credentials): int + public function loginAs(array $credentials, int $rights = CREATE | UPDATE | PURGE): int { global $DB; @@ -59,7 +59,7 @@ public function loginAs(array $credentials): int $DB->update( 'glpi_profilerights', [ - 'rights' => CREATE | UPDATE | PURGE, + 'rights' => $rights, ], [ 'profiles_id' => $user_profile, @@ -72,14 +72,14 @@ public function loginAs(array $credentials): int return $user->getID(); } - public function createTag(string $tagName): int + public function createTag(string $tagName, array $typeMenu = ['Ticket']): int { $tag = new PluginTagTag(); $tag->add( [ 'name' => $tagName, 'is_active' => 1, - 'type_menu' => ['Ticket'], + 'type_menu' => $typeMenu, ], ); $this->assertGreaterThan(0, $tag->getID()); diff --git a/tests/Units/TagItemTest.php b/tests/Units/TagItemTest.php index 1c00b69..2f8b203 100644 --- a/tests/Units/TagItemTest.php +++ b/tests/Units/TagItemTest.php @@ -30,17 +30,20 @@ namespace GlpiPlugin\Tag\Tests\Units; +use Computer; use GlpiPlugin\Tag\Tests\TagTestCase; +use PluginTagTagItem; use Ticket; final class TagItemTest extends TagTestCase { + private const TECH_USER = ['login' => 'tech', 'pass' => 'tech']; + public function testTagsFromTicket(): void { $tagID1 = $this->createTag('TicketTag1'); $tagID2 = $this->createTag('TicketTag2'); - $ticket = new Ticket(); $ticket->add([ 'name' => 'Ticket add Tag', @@ -56,4 +59,23 @@ public function testTagsFromTicket(): void $this->isItemTagged($ticket, $tagID2); } + public function testTagAssociationCreatesLink(): void + { + $this->loginAs(self::TECH_USER); + + $tag = $this->createTag('MyTag', ['Computer']); + $computer = $this->createItem(Computer::class, [ + 'name' => 'Computer to tag', + 'entities_id' => 0, + ]); + + $tagItem = new PluginTagTagItem(); + $tagItem->add([ + 'plugin_tag_tags_id' => $tag, + 'itemtype' => Computer::class, + 'items_id' => $computer->getID(), + ]); + + $this->isItemTagged($computer, $tag); + } }
" . __s('Add an item') . "