Skip to content

Commit

Permalink
Fix completename translated value
Browse files Browse the repository at this point in the history
  • Loading branch information
cedric-anne authored and anthonymontebrun committed Jul 11, 2024
1 parent 82651cd commit bbf9314
Show file tree
Hide file tree
Showing 4 changed files with 285 additions and 65 deletions.
140 changes: 75 additions & 65 deletions src/DropdownTranslation.php
Original file line number Diff line number Diff line change
Expand Up @@ -279,84 +279,91 @@ public function generateCompletename($input, $add = true)
{
/** @var \DBmysql $DB */
global $DB;
// Force completename translated : used for the first translation
$_SESSION['glpi_dropdowntranslations'][$input['itemtype']]['completename'] = 'completename';

//If there's already a completename for this language, get it's ID, otherwise 0
if (!is_a($input['itemtype'], CommonTreeDropdown::class, true)) {
return; // `completename` is used only for tree dropdowns
}
$itemtype = $input['itemtype'];

//If there's already a completename for this language, get it's ID, otherwise 0
$completenames_id = self::getTranslationID(
$input['items_id'],
$input['itemtype'],
$itemtype,
'completename',
$input['language']
);
$item = new $input['itemtype']();
//Completename is used only for tree dropdowns !
if (
$item instanceof CommonTreeDropdown
&& isset($input['language'])
) {
$item->getFromDB($input['items_id']);
$foreignKey = $item->getForeignKeyField();

//Regenerate completename : look for item's ancestors
$completename = "";

//Get ancestors as an array
$item = new $itemtype();
$item->getFromDB($input['items_id']);
$foreignKey = $item->getForeignKeyField();

if ($item->fields[$foreignKey] != 0) {
$completename = self::getTranslatedValue(
$item->fields[$foreignKey],
$input['itemtype'],
'completename',
$input['language']
);
}
$completename_parts = [];
$completename = "";

if ($completename != '') {
$completename .= " > ";
}
$completename .= self::getTranslatedValue(
$item->getID(),
$input['itemtype'],
'name',
if ($item->fields[$foreignKey] != 0) {
// Get translated complename of parent item
$tranlated_parent_completename = self::getTranslatedValue(
$item->fields[$foreignKey],
$itemtype,
'completename',
$input['language']
);
if ($tranlated_parent_completename !== '') {
$completename_parts[] = $tranlated_parent_completename;
} elseif ($parent = $itemtype::getById($item->fields[$foreignKey])) {
// Fallback to untranslated completename of parent item
$completename_parts[] = $parent->fields['completename'];
}
}

//Add or update completename for this language
$translation = new self();
$tmp = [];
$tmp['items_id'] = $input['items_id'];
$tmp['itemtype'] = $input['itemtype'];
$tmp['field'] = 'completename';
$tmp['value'] = addslashes($completename);
$tmp['language'] = $input['language'];
$tmp['_no_completename'] = true;
if ($completenames_id) {
$tmp['id'] = $completenames_id;
if ($completename === $item->fields['completename']) {
$translation->delete(['id' => $completenames_id]);
} else {
$translation->update($tmp);
}
// Append translated name of item
$tranlated_name = self::getTranslatedValue(
$item->getID(),
$itemtype,
'name',
$input['language']
);
if ($tranlated_name !== '') {
$completename_parts[] = $tranlated_name;
} else {
$completename_parts[] = $item->fields['name'];
}

$completename = implode(' > ', $completename_parts);

// Add or update completename for this language
$translation = new self();
$tmp = [];
$tmp['items_id'] = $input['items_id'];
$tmp['itemtype'] = $input['itemtype'];
$tmp['field'] = 'completename';
$tmp['value'] = addslashes($completename);
$tmp['language'] = $input['language'];
$tmp['_no_completename'] = true;
if ($completenames_id) {
$tmp['id'] = $completenames_id;
if ($completename === $item->fields['completename']) {
$translation->delete(['id' => $completenames_id]);
} else {
if ($completename != $item->fields['completename']) {
$translation->add($tmp);
}
$translation->update($tmp);
}
} else {
if ($completename != $item->fields['completename']) {
$translation->add($tmp);
}
}

$iterator = $DB->request([
'SELECT' => ['id'],
'FROM' => $item->getTable(),
'WHERE' => [
$foreignKey => $item->getID()
]
]);
$iterator = $DB->request([
'SELECT' => ['id'],
'FROM' => $item->getTable(),
'WHERE' => [
$foreignKey => $item->getID()
]
]);

foreach ($iterator as $tmp) {
$input2 = $input;
$input2['items_id'] = $tmp['id'];
$this->generateCompletename($input2, $add);
}
foreach ($iterator as $tmp) {
$input2 = $input;
$input2['items_id'] = $tmp['id'];
$this->generateCompletename($input2, $add);
}
}

Expand Down Expand Up @@ -674,12 +681,15 @@ public static function getTranslatedValue($ID, $itemtype, $field = 'name', $lang
$language = $_SESSION['glpilanguage'];
}

$translated_fields = $language === $_SESSION['glpilanguage'] && isset($_SESSION['glpi_dropdowntranslations'])
? $_SESSION['glpi_dropdowntranslations']
: DropdownTranslation::getAvailableTranslations($language);

//If dropdown translation is globally off, or if this itemtype cannot be translated,
//then original value should be returned
$item = new $itemtype();
if (
!$ID
|| !Session::haveTranslations($itemtype, $field)
|| !isset($translated_fields[$itemtype][$field])
) {
return $value;
}
Expand Down
7 changes: 7 additions & 0 deletions tests/functional/Dropdown.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@ public function testGetDropdownName()

// test of return with translations
$CFG_GLPI['translate_dropdowns'] = 1;
// Force generation of completename that was not done on dataset bootstrap
// because `translate_dropdowns` is false by default.
(new \DropdownTranslation())->generateCompletename([
'itemtype' => \TaskCategory::class,
'items_id' => getItemByTypeName(\TaskCategory::class, '_cat_1', true),
'language' => 'fr_FR'
]);
$_SESSION["glpilanguage"] = \Session::loadLanguage('fr_FR');
$_SESSION['glpi_dropdowntranslations'] = \DropdownTranslation::getAvailableTranslations($_SESSION["glpilanguage"]);
$expected = ['name' => 'FR - _cat_1' . $encoded_sep . 'FR - _subcat_1',
Expand Down
196 changes: 196 additions & 0 deletions tests/functional/DropdownTranslation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
<?php

/**
* ---------------------------------------------------------------------
*
* GLPI - Gestionnaire Libre de Parc Informatique
*
* http://glpi-project.org
*
* @copyright 2015-2023 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;

use DbTestCase;
use ITILCategory;
use QueryExpression;

class DropdownTranslation extends DbTestCase
{
protected function completenameGenerationProvider(): iterable
{
$this->login();

$category = $this->createItem(
ITILCategory::class,
[
'name' => 'Root category'
]
);
$sub_category = $this->createItem(
ITILCategory::class,
[
'name' => 'Sub category',
'itilcategories_id' => $category->getID(),
]
);
$sub_sub_category = $this->createItem(
ITILCategory::class,
[
'name' => 'Sub sub category',
'itilcategories_id' => $sub_category->getID(),
]
);

// Default value is alway returned when there is no translation
foreach ([$category->getID(), $sub_category->getID(), $sub_sub_category->getID()] as $category_id) {
yield [
'translations' => [
],
'category_id' => $category_id,
'language' => 'fr_FR',
'default_value' => 'Valeur par défaut',
'result' => 'Valeur par défaut',
];
}

yield [
'translations' => [
[
'itemtype' => ITILCategory::class,
'items_id' => $category->getID(),
'language' => 'fr_FR',
'field' => 'name',
'value' => 'Catégorie racine',
]
],
'category_id' => $category->getID(),
'language' => 'fr_FR',
'default_value' => 'Valeur par défaut',
'result' => 'Catégorie racine',
];

yield [
'translations' => [
[
'itemtype' => ITILCategory::class,
'items_id' => $category->getID(),
'language' => 'fr_FR',
'field' => 'name',
'value' => 'Catégorie racine',
]
],
'category_id' => $sub_category->getID(),
'language' => 'fr_FR',
'default_value' => 'Valeur par défaut',
'result' => 'Catégorie racine > Sub category',
];

yield [
'translations' => [
[
'itemtype' => ITILCategory::class,
'items_id' => $sub_category->getID(),
'language' => 'fr_FR',
'field' => 'name',
'value' => 'Sous catégorie',
]
],
'category_id' => $sub_category->getID(),
'language' => 'fr_FR',
'default_value' => 'Valeur par défaut',
'result' => 'Root category > Sous catégorie',
];

yield [
'translations' => [
[
'itemtype' => ITILCategory::class,
'items_id' => $category->getID(),
'language' => 'fr_FR',
'field' => 'name',
'value' => 'Catégorie racine',
],
[
'itemtype' => ITILCategory::class,
'items_id' => $sub_category->getID(),
'language' => 'fr_FR',
'field' => 'name',
'value' => 'Sous catégorie',
]
],
'category_id' => $sub_category->getID(),
'language' => 'fr_FR',
'default_value' => 'Valeur par défaut',
'result' => 'Catégorie racine > Sous catégorie',
];

yield [
'translations' => [
[
'itemtype' => ITILCategory::class,
'items_id' => $sub_category->getID(),
'language' => 'fr_FR',
'field' => 'name',
'value' => 'Sous catégorie',
]
],
'category_id' => $sub_sub_category->getID(),
'language' => 'fr_FR',
'default_value' => 'Valeur par défaut',
'result' => 'Root category > Sous catégorie > Sub sub category',
];
}

/**
* @dataProvider completenameGenerationProvider
*/
public function testgetTranslatedCompletename(
array $translations,
int $category_id,
string $language,
string $default_value,
string $result
): void {
global $CFG_GLPI, $DB;
$CFG_GLPI['translate_dropdowns'] = 1;

// Delete existing translations to prevent conflicts with tested data
$DB->delete(\DropdownTranslation::getTable(), [new QueryExpression("true")]);

$this->createItems(\DropdownTranslation::class, $translations);

foreach (['en_GB', 'fr_FR', 'es_ES'] as $session_language) {
// Current session language should not affect result
$_SESSION['glpilanguage'] = $session_language;
$_SESSION['glpi_dropdowntranslations'] = \DropdownTranslation::getAvailableTranslations($session_language);

$this->string(\DropdownTranslation::getTranslatedValue($category_id, ITILCategory::class, 'completename', $language, $default_value))
->isEqualTo($result);
}
}
}
7 changes: 7 additions & 0 deletions tests/functional/NotificationTargetTicket.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,13 @@ public function testgetDataForObject()

// test of the getDataForObject for default language fr_FR
$CFG_GLPI['translate_dropdowns'] = 1;
// Force generation of completename that was not done on dataset bootstrap
// because `translate_dropdowns` is false by default.
(new \DropdownTranslation())->generateCompletename([
'itemtype' => \TaskCategory::class,
'items_id' => getItemByTypeName(\TaskCategory::class, '_cat_1', true),
'language' => 'fr_FR'
]);
$_SESSION["glpilanguage"] = \Session::loadLanguage('fr_FR');
$_SESSION['glpi_dropdowntranslations'] = \DropdownTranslation::getAvailableTranslations($_SESSION["glpilanguage"]);

Expand Down

0 comments on commit bbf9314

Please sign in to comment.