Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Fixed

- Avoid a per-tag database lookup when rendering the tag column in item lists

## [2.14.6] - 2026-08-04

### Fixed
Expand Down
14 changes: 13 additions & 1 deletion hook.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ function plugin_tag_getAddSearchOptionsNew($itemtype)
'searchtype' => ['equals','notequals','contains'],
'massiveaction' => false,
'forcegroupby' => true,
// Fetch the color alongside the name in the same grouped query,
// avoiding a getFromDB() call per tag per row in plugin_tag_giveItem().
'additionalfields' => ['color'],
'joinparams' => [
'beforejoin' => [
'table' => 'glpi_plugin_tag_tagitems',
Expand Down Expand Up @@ -133,6 +136,7 @@ function plugin_tag_getAddSearchOptionsNew($itemtype)
'massiveaction' => false,
'forcegroupby' => true,
'usehaving' => true,
'additionalfields' => ['color'],
'joinparams' => [
'condition' => "AND 1=1", // to force distinct complex id than the previous option
'beforejoin' => [
Expand Down Expand Up @@ -163,7 +167,15 @@ function plugin_tag_giveItem($type, $field, $data, $num, $linkfield = "")
$separator = '';
foreach ($data[$num] as $tag) {
if (isset($tag['id']) && isset($tag['name'])) {
$out .= PluginTagTag::getSingleTag($tag['id'], $separator);
$color = $tag['color'] ?: '#DDDDDD';
$textcolor = idealTextColor($color);
$out .= sprintf(
"<span class='select2-search-choice tag_choice' style='padding-left:5px;background-color: %s; color: %s'>%s%s</span>",
htmlentities((string) $color, ENT_QUOTES, "UTF-8"),
$textcolor,
$separator,
htmlentities((string) $tag['name'], ENT_QUOTES, "UTF-8"),
);
//For export (CSV, PDF) of GLPI core
$separator = '<span style="display:none">, </span>';
}
Expand Down
29 changes: 29 additions & 0 deletions tests/Units/TagTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,35 @@ public function testAddHavingEscapesValue(): void
);
}

public function testGiveItemRendersColorFromSearchDataWithoutDbLookup(): void
{
// Tag ids intentionally do not exist in DB: if plugin_tag_giveItem()
// ever falls back to a getFromDB() call per tag, this fails because
// the lookup returns nothing and the fallback color/empty name show up instead.
$data = [
0 => [
'count' => 2,
0 => [
'id' => 999998,
'name' => 'First tag',
'color' => '#123456',
],
1 => [
'id' => 999999,
'name' => 'Second tag',
'color' => '#abcdef',
],
],
];

$out = plugin_tag_giveItem('Ticket', PluginTagTag::S_OPTION, $data, 0);

$this->assertStringContainsString('#123456', $out);
$this->assertStringContainsString('First tag', $out);
$this->assertStringContainsString('#abcdef', $out);
$this->assertStringContainsString('Second tag', $out);
}

public function testUpdateAcceptsScalarTypeMenu(): void
{
$tag = $this->createItem(
Expand Down