';
+ . __s('Regenerate container files', 'fields') . " "
+ . __s('Export to YAML', 'fields') . ' ';
}
public function getForbiddenStandardMassiveAction()
@@ -82,7 +82,7 @@ public static function installBaseData(Migration $migration, $version)
$table = self::getTable();
if (!$DB->tableExists($table)) {
- $migration->displayMessage(sprintf(__('Installing %s'), $table));
+ $migration->displayMessage(sprintf(__s('Installing %s'), $table));
$query = "CREATE TABLE IF NOT EXISTS `{$table}` (
`id` INT {$default_key_sign} NOT NULL auto_increment,
@@ -269,7 +269,7 @@ public static function installUserData(Migration $migration, $version)
}
// Regenerate container classes to ensure they can be used
- $migration->displayMessage(__('Regenerate containers files', 'fields'));
+ $migration->displayMessage(__s('Regenerate containers files', 'fields'));
$obj = new self();
$containers = $obj->find();
foreach ($containers as $container) {
@@ -290,7 +290,7 @@ public static function installUserData(Migration $migration, $version)
);
if ($bad_named_containers->count() > 0) {
- $migration->displayMessage(__('Fix container names', 'fields'));
+ $migration->displayMessage(__s('Fix container names', 'fields'));
$toolbox = new PluginFieldsToolbox();
@@ -438,7 +438,7 @@ public static function installUserData(Migration $migration, $version)
$migration->executeMigration();
// Regenerate files and install missing tables
- $migration->displayMessage(__('Updating generated containers files', 'fields'));
+ $migration->displayMessage(__s('Updating generated containers files', 'fields'));
$obj = new self();
$containers = $obj->find();
@@ -630,7 +630,7 @@ public function prepareInputForAdd($input)
{
if (empty($input['itemtypes'])) {
Session::AddMessageAfterRedirect(
- __(
+ __s(
'You cannot add block without associated element type',
'fields',
),
@@ -652,7 +652,7 @@ public function prepareInputForAdd($input)
foreach (array_column($found, 'itemtypes') as $founditemtypes) {
foreach (PluginFieldsToolbox::decodeJSONItemtypes($founditemtypes) as $founditemtype) {
if (in_array($founditemtype, $input['itemtypes'])) {
- Session::AddMessageAfterRedirect(__("You cannot add several blocks with type 'Insertion in the form' on same object", 'fields'), false, ERROR);
+ Session::AddMessageAfterRedirect(__s("You cannot add several blocks with type 'Insertion in the form' on same object", 'fields'), false, ERROR);
return false;
}
@@ -668,7 +668,7 @@ public function prepareInputForAdd($input)
foreach (array_column($found, 'itemtypes') as $founditemtypes) {
foreach (PluginFieldsToolbox::decodeJSONItemtypes($founditemtypes) as $founditemtype) {
if (in_array($founditemtype, $input['itemtypes'])) {
- Session::AddMessageAfterRedirect(__("You cannot add several blocks with type 'Insertion in the form of a specific tab' on same object tab", 'fields'), false, ERROR);
+ Session::AddMessageAfterRedirect(__s("You cannot add several blocks with type 'Insertion in the form of a specific tab' on same object tab", 'fields'), false, ERROR);
return false;
}
@@ -679,7 +679,7 @@ public function prepareInputForAdd($input)
$accepted_itemtypes = array_keys(array_merge(...array_values(self::getItemtypes(true))));
foreach ($input['itemtypes'] as $itemtype) {
if (!in_array($itemtype, $accepted_itemtypes)) {
- Session::AddMessageAfterRedirect(__("At least one selected object cannot be linked with type 'Insertion in the form of a specific tab'.", 'fields'), false, ERROR);
+ Session::AddMessageAfterRedirect(__s("At least one selected object cannot be linked with type 'Insertion in the form of a specific tab'.", 'fields'), false, ERROR);
return false;
}
@@ -693,7 +693,7 @@ public function prepareInputForAdd($input)
$tmp = getTableForItemType(self::getClassname($itemtype, $input['name']));
if (strlen($tmp) > 64) {
Session::AddMessageAfterRedirect(
- __('Container name is too long for database (digits in name are replaced by characters, try to remove them)', 'fields'),
+ __s('Container name is too long for database (digits in name are replaced by characters, try to remove them)', 'fields'),
false,
ERROR,
);
@@ -708,7 +708,7 @@ public function prepareInputForAdd($input)
foreach (array_column($found, 'itemtypes') as $founditemtypes) {
foreach (PluginFieldsToolbox::decodeJSONItemtypes($founditemtypes) as $founditemtype) {
if (in_array($founditemtype, $input['itemtypes'])) {
- Session::AddMessageAfterRedirect(__('You cannot add several blocs with identical name on same object', 'fields'), false, ERROR);
+ Session::AddMessageAfterRedirect(__s('You cannot add several blocs with identical name on same object', 'fields'), false, ERROR);
return false;
}
@@ -952,7 +952,7 @@ public function showForm($ID, $options = [])
$rand = mt_rand();
echo '
';
- echo "
" . __('Label') . ' :
';
+ echo "
" . __s('Label') . ' :
';
echo "
";
echo Html::input(
'label',
@@ -966,7 +966,7 @@ public function showForm($ID, $options = [])
echo '
';
echo '
';
- echo '
' . __('Type') . ' :
';
+ echo '
' . __s('Type') . ' :
';
echo '
';
if ($ID > 0) {
$types = self::getTypes();
@@ -994,7 +994,7 @@ public function showForm($ID, $options = [])
}
echo '
';
- echo '
' . __('Associated item type') . ' :
';
+ echo '
' . __s('Associated item type') . ' :
';
echo '
';
if ($ID > 0) {
$types = PluginFieldsToolbox::decodeJSONItemtypes($this->fields['itemtypes']);
@@ -1039,7 +1039,7 @@ public function showForm($ID, $options = [])
echo sprintf("
", $display);
echo "
";
- echo '
' . __('Tab', 'fields') . ' :
';
+ echo '
' . __s('Tab', 'fields') . ' :
';
echo '
';
echo sprintf(" ", $rand);
if ($ID > 0 && !empty($this->fields['subtype'])) {
@@ -1056,7 +1056,7 @@ public function showForm($ID, $options = [])
echo '
';
@@ -1198,9 +1198,9 @@ public static function getItemtypes($is_domtab)
public static function getTypes()
{
return [
- 'tab' => __('Add tab', 'fields'),
- 'dom' => __('Insertion in the form (before save button)', 'fields'),
- 'domtab' => __('Insertion in the form of a specific tab (before save button)', 'fields'),
+ 'tab' => __s('Add tab', 'fields'),
+ 'dom' => __s('Insertion in the form (before save button)', 'fields'),
+ 'domtab' => __s('Insertion in the form of a specific tab (before save button)', 'fields'),
];
}
@@ -1734,17 +1734,17 @@ public static function validateValues($data, $itemtype, $massiveaction)
}
if ($empty_errors !== []) {
- Session::AddMessageAfterRedirect(__('Some mandatory fields are empty', 'fields')
+ Session::AddMessageAfterRedirect(__s('Some mandatory fields are empty', 'fields')
. ' : ' . implode(', ', $empty_errors), false, ERROR);
}
if ($number_errors !== []) {
- Session::AddMessageAfterRedirect(__('Some numeric fields contains non numeric values', 'fields')
+ Session::AddMessageAfterRedirect(__s('Some numeric fields contains non numeric values', 'fields')
. ' : ' . implode(', ', $number_errors), false, ERROR);
}
if ($url_errors !== []) {
- Session::AddMessageAfterRedirect(__('Some URL fields contains invalid links', 'fields')
+ Session::AddMessageAfterRedirect(__s('Some URL fields contains invalid links', 'fields')
. ' : ' . implode(', ', $url_errors), false, ERROR);
}
@@ -2349,11 +2349,11 @@ private static function getSubtypes($item)
switch ($item::getType()) {
case Entity::getType():
$tabs = [
- 'Entity$2' => __('Address'),
- 'Entity$3' => __('Advanced information'),
- 'Entity$4' => __('Notifications'),
- 'Entity$5' => __('Assistance'),
- 'Entity$6' => __('Assets'),
+ 'Entity$2' => __s('Address'),
+ 'Entity$3' => __s('Advanced information'),
+ 'Entity$4' => __s('Notifications'),
+ 'Entity$5' => __s('Assistance'),
+ 'Entity$6' => __s('Assets'),
];
break;
default:
@@ -2390,10 +2390,15 @@ public static function getClassname(string $itemtype, string $container_name, st
*
* @param string $itemtype Name of associated itemtype
* @param string $container_name Name of container
+ *
+ * @psalm-taint-escape file (only `[A-Za-z0-9_]` characters are kept, forcing path safeness)
*/
protected static function getSystemName(string $itemtype, string $container_name): string
{
- return strtolower(str_replace('\\', '', $itemtype) . preg_replace('/s$/', '', $container_name));
+ // Only keep characters valid in a PHP class name, as the result is used to build filenames.
+ $itemtype = preg_replace('/[^A-Za-z0-9_]/', '', $itemtype);
+
+ return strtolower($itemtype . preg_replace('/s$/', '', $container_name));
}
public static function getIcon()
diff --git a/inc/containerdisplaycondition.class.php b/inc/containerdisplaycondition.class.php
index 8c87b234..5e7ae5ec 100644
--- a/inc/containerdisplaycondition.class.php
+++ b/inc/containerdisplaycondition.class.php
@@ -70,7 +70,7 @@ public static function installBaseData(Migration $migration, $version)
$table = self::getTable();
if (!$DB->tableExists($table)) {
- $migration->displayMessage(sprintf(__('Installing %s'), $table));
+ $migration->displayMessage(sprintf(__s('Installing %s'), $table));
$query = "CREATE TABLE IF NOT EXISTS `{$table}` (
`id` INT {$default_key_sign} NOT NULL auto_increment,
`plugin_fields_containers_id` INT {$default_key_sign} NOT NULL DEFAULT '0',
@@ -132,13 +132,13 @@ public static function getConditionName($condition)
echo '>';
break;
case self::SHOW_CONDITION_REGEX:
- echo __('regular expression matches', 'fields');
+ echo __s('regular expression matches', 'fields');
break;
case self::SHOW_CONDITION_UNDER:
- echo __('under', 'fields');
+ echo __s('under', 'fields');
break;
case self::SHOW_CONDITION_NOT_UNDER:
- echo __('not under', 'fields');
+ echo __s('not under', 'fields');
break;
}
}
@@ -359,7 +359,7 @@ public static function getRawValue($searchoption_id, $itemtype, $value)
$raw_value = $value;
}
- echo $raw_value;
+ echo htmlescape($raw_value);
}
public static function removeBlackListedOption($array, $itemtype_class)
@@ -508,7 +508,7 @@ public function prepareInputForAdd($input)
// itemtype, search_option, condition, value must all be set
if (!isset($input['itemtype'], $input['search_option'], $input['condition'])) {
Session::addMessageAfterRedirect(
- __('You must specify an item type, search option and condition.', 'fields'),
+ __s('You must specify an item type, search option and condition.', 'fields'),
true,
ERROR,
);
@@ -524,7 +524,7 @@ public function prepareInputForUpdate($input)
// itemtype, search_option, condition, value must all be set
if (!isset($input['itemtype'], $input['search_option'], $input['condition'])) {
Session::addMessageAfterRedirect(
- __('You must specify an item type, search option and condition.', 'fields'),
+ __s('You must specify an item type, search option and condition.', 'fields'),
true,
ERROR,
);
diff --git a/inc/dropdown.class.php b/inc/dropdown.class.php
index 3ec0d2eb..f0319424 100644
--- a/inc/dropdown.class.php
+++ b/inc/dropdown.class.php
@@ -76,7 +76,7 @@ public static function installUserData(Migration $migration, $version)
$migration->executeMigration();
// Regenerate files and install missing tables
- $migration->displayMessage(__('Updating generated dropdown files', 'fields'));
+ $migration->displayMessage(__s('Updating generated dropdown files', 'fields'));
$obj = new PluginFieldsField();
$fields = $obj->find(['type' => 'dropdown']);
diff --git a/inc/field.class.php b/inc/field.class.php
index ce9b3e24..d4ae045c 100644
--- a/inc/field.class.php
+++ b/inc/field.class.php
@@ -74,7 +74,7 @@ public static function installBaseData(Migration $migration, $version)
$table = self::getTable();
if (!$DB->tableExists($table)) {
- $migration->displayMessage(sprintf(__('Installing %s'), $table));
+ $migration->displayMessage(sprintf(__s('Installing %s'), $table));
$query = "CREATE TABLE IF NOT EXISTS `{$table}` (
`id` INT {$default_key_sign} NOT NULL auto_increment,
@@ -293,7 +293,7 @@ public function prepareInputForAdd($input)
//reject adding when field name is too long for mysql
if (strlen($input['name']) > 64) {
Session::AddMessageAfterRedirect(
- __('Field name is too long for database (digits in name are replaced by characters, try to remove them)', 'fields'),
+ __s('Field name is too long for database (digits in name are replaced by characters, try to remove them)', 'fields'),
false,
ERROR,
);
@@ -312,7 +312,7 @@ public function prepareInputForAdd($input)
//reject adding for same dropdown on same block
if (!empty($found)) {
- Session::AddMessageAfterRedirect(__("You cannot add same field 'dropdown' on same block", 'fields'), false, ERROR);
+ Session::AddMessageAfterRedirect(__s("You cannot add same field 'dropdown' on same block", 'fields'), false, ERROR);
return false;
}
@@ -320,7 +320,7 @@ public function prepareInputForAdd($input)
//reject adding when dropdown name is too long for mysql table name
if (strlen(getTableForItemType(PluginFieldsDropdown::getClassname($input['name']))) > 64) {
Session::AddMessageAfterRedirect(
- __('Field name is too long for database (digits in name are replaced by characters, try to remove them)', 'fields'),
+ __s('Field name is too long for database (digits in name are replaced by characters, try to remove them)', 'fields'),
false,
ERROR,
);
@@ -662,11 +662,11 @@ public function showSummary($container)
echo "
";
echo Html::input('label', [
'value' => $this->fields['label'],
diff --git a/inc/profile.class.php b/inc/profile.class.php
index 6cd97e32..a8252a74 100644
--- a/inc/profile.class.php
+++ b/inc/profile.class.php
@@ -62,7 +62,7 @@ public static function installBaseData(Migration $migration, $version)
$table = self::getTable();
if (!$DB->tableExists($table)) {
- $migration->displayMessage(sprintf(__('Installing %s'), $table));
+ $migration->displayMessage(sprintf(__s('Installing %s'), $table));
$query = "CREATE TABLE IF NOT EXISTS `{$table}` (
`id` INT {$default_key_sign} NOT NULL auto_increment,
@@ -113,7 +113,7 @@ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $
echo "
";
echo "
";
- echo "
" . _n('Profile', 'Profiles', 2) . '
';
+ echo "
" . _sn('Profile', 'Profiles', 2) . '
';
foreach ($found_profiles as $profile_item) {
//get right for current profile
$found = $fields_profile->find([
@@ -136,7 +136,7 @@ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $
echo '
';
echo "
";
- echo "";
+ echo "";
echo "";
echo '
';
echo '
';
diff --git a/inc/statusoverride.class.php b/inc/statusoverride.class.php
index e60eda37..127caf0d 100644
--- a/inc/statusoverride.class.php
+++ b/inc/statusoverride.class.php
@@ -58,7 +58,7 @@ public static function installBaseData(Migration $migration, $version)
$table = self::getTable();
if (!$DB->tableExists($table)) {
- $migration->displayMessage(sprintf(__('Installing %s'), $table));
+ $migration->displayMessage(sprintf(__s('Installing %s'), $table));
$query = "CREATE TABLE IF NOT EXISTS `{$table}` (
`id` INT {$default_key_sign} NOT NULL auto_increment,
diff --git a/inc/toolbox.class.php b/inc/toolbox.class.php
index f1922a6c..99a29105 100644
--- a/inc/toolbox.class.php
+++ b/inc/toolbox.class.php
@@ -119,7 +119,7 @@ public function fixFieldsNames(Migration $migration, $condition)
return;
}
- $migration->displayMessage(__('Fix fields names', 'fields'));
+ $migration->displayMessage(__s('Fix fields names', 'fields'));
foreach ($bad_named_fields as $field) {
$old_name = $field['name'];
diff --git a/psalm.xml b/psalm.xml
new file mode 100644
index 00000000..8704f172
--- /dev/null
+++ b/psalm.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/Units/ContainerItemUpdateTest.php b/tests/Units/ContainerItemUpdateTest.php
index 587a13be..85a3b85f 100644
--- a/tests/Units/ContainerItemUpdateTest.php
+++ b/tests/Units/ContainerItemUpdateTest.php
@@ -788,7 +788,7 @@ public function testOnlyOneDomContainerAllowedPerItemtype(): void
$this->assertFalse((bool) $result, 'Creating a second DOM container for the same itemtype must be rejected.');
// message should be checked manually
- $this->hasSessionMessages(ERROR, ["You cannot add several blocks with type 'Insertion in the form' on same object"]);
+ $this->hasSessionMessages(ERROR, [__s("You cannot add several blocks with type 'Insertion in the form' on same object")]);
}
// -----------------------------------------------------------------------