Skip to content

Commit 7e3c6e7

Browse files
committed
fix(actorsfield): compatibility with GLPI 9.5.3
a security fix added in GLPI broke the field Signed-off-by: Thierry Bugier <tbugier@teclib.com>
1 parent 4c96836 commit 7e3c6e7

File tree

3 files changed

+226
-8
lines changed

3 files changed

+226
-8
lines changed

inc/common.class.php

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,4 +296,185 @@ public static function canValidate() : bool {
296296
return Session::haveRight('ticketvalidation', TicketValidation::VALIDATEINCIDENT)
297297
|| Session::haveRight('ticketvalidation', TicketValidation::VALIDATEREQUEST);
298298
}
299+
300+
/*
301+
* Create Ajax dropdown to clean JS
302+
* Code copied and modified from Html::jsAjaxDropdown to allow
303+
* item creation in dropdown
304+
*
305+
* @param $name
306+
* @param $field_id string id of the dom element
307+
* @param $url string URL to get datas
308+
* @param $params array of parameters
309+
* must contains :
310+
* if single select
311+
* - 'value' : default value selected
312+
* - 'valuename' : default name of selected value
313+
* if multiple select
314+
* - 'values' : default values selected
315+
* - 'valuesnames' : default names of selected values
316+
*
317+
* @since 0.85.
318+
*
319+
* @return String
320+
**/
321+
public static function jsAjaxDropdown($name, $field_id, $url, $params = []) {
322+
global $CFG_GLPI;
323+
324+
if (!isset($params['value'])) {
325+
$value = 0;
326+
} else {
327+
$value = $params['value'];
328+
}
329+
if (!isset($params['value'])) {
330+
$valuename = Dropdown::EMPTY_VALUE;
331+
} else {
332+
$valuename = $params['valuename'];
333+
}
334+
$on_change = '';
335+
if (isset($params["on_change"])) {
336+
$on_change = $params["on_change"];
337+
unset($params["on_change"]);
338+
}
339+
$width = '80%';
340+
if (isset($params["width"])) {
341+
$width = $params["width"];
342+
unset($params["width"]);
343+
}
344+
345+
$placeholder = isset($params['placeholder']) ? $params['placeholder'] : '';
346+
$allowclear = "false";
347+
if (strlen($placeholder) > 0 && !$params['display_emptychoice']) {
348+
$allowclear = "true";
349+
}
350+
351+
unset($params['placeholder']);
352+
unset($params['value']);
353+
unset($params['valuename']);
354+
355+
$options = [
356+
'id' => $field_id,
357+
'selected' => $value
358+
];
359+
if (!empty($params['specific_tags'])) {
360+
foreach ($params['specific_tags'] as $tag => $val) {
361+
if (is_array($val)) {
362+
$val = implode(' ', $val);
363+
}
364+
$options[$tag] = $val;
365+
}
366+
}
367+
368+
// manage multiple select (with multiple values)
369+
if (isset($params['values']) && count($params['values'])) {
370+
$values = array_combine($params['values'], $params['valuesnames']);
371+
$options['multiple'] = 'multiple';
372+
$options['selected'] = $params['values'];
373+
} else {
374+
$values = [];
375+
376+
// simple select (multiple = no)
377+
if ((isset($params['display_emptychoice']) && $params['display_emptychoice'])
378+
|| isset($params['toadd'][$value])
379+
|| $value > 0) {
380+
$values = ["$value" => $valuename];
381+
}
382+
}
383+
384+
// display select tag
385+
$output = Html::select($name, $values, $options);
386+
387+
$js = "
388+
var params_$field_id = {";
389+
foreach ($params as $key => $val) {
390+
// Specific boolean case
391+
if (is_bool($val)) {
392+
$js .= "$key: ".($val?1:0).",\n";
393+
} else {
394+
$js .= "$key: ".json_encode($val).",\n";
395+
}
396+
}
397+
$js.= "};
398+
399+
$('#$field_id').select2({
400+
width: '$width',
401+
placeholder: '$placeholder',
402+
allowClear: $allowclear,
403+
minimumInputLength: 0,
404+
quietMillis: 100,
405+
dropdownAutoWidth: true,
406+
minimumResultsForSearch: ".$CFG_GLPI['ajax_limit_count'].",
407+
tokenSeparators: [',', ';'],
408+
tags: true,
409+
ajax: {
410+
url: '$url',
411+
dataType: 'json',
412+
type: 'POST',
413+
data: function (params) {
414+
query = params;
415+
return $.extend({}, params_$field_id, {
416+
searchText: params.term,
417+
page_limit: ".$CFG_GLPI['dropdown_max'].", // page size
418+
page: params.page || 1, // page number
419+
});
420+
},
421+
processResults: function (data, params) {
422+
params.page = params.page || 1;
423+
var more = (data.count >= ".$CFG_GLPI['dropdown_max'].");
424+
425+
return {
426+
results: data.results,
427+
pagination: {
428+
more: more
429+
}
430+
};
431+
}
432+
},
433+
templateResult: templateResult,
434+
templateSelection: templateSelection
435+
})
436+
.bind('setValue', function(e, value) {
437+
$.ajax('$url', {
438+
data: $.extend({}, params_$field_id, {
439+
_one_id: value,
440+
}),
441+
dataType: 'json',
442+
type: 'POST',
443+
}).done(function(data) {
444+
445+
var iterate_options = function(options, value) {
446+
var to_return = false;
447+
$.each(options, function(index, option) {
448+
if (option.hasOwnProperty('id')
449+
&& option.id == value) {
450+
to_return = option;
451+
return false; // act as break;
452+
}
453+
454+
if (option.hasOwnProperty('children')) {
455+
to_return = iterate_options(option.children, value);
456+
}
457+
});
458+
459+
return to_return;
460+
};
461+
462+
var option = iterate_options(data.results, value);
463+
if (option !== false) {
464+
var newOption = new Option(option.text, option.id, true, true);
465+
$('#$field_id').append(newOption).trigger('change');
466+
}
467+
});
468+
});
469+
";
470+
if (!empty($on_change)) {
471+
$js .= " $('#$field_id').on('change', function(e) {".
472+
stripslashes($on_change)."});";
473+
}
474+
475+
$js .= " $('label[for=$field_id]').on('click', function(){ $('#$field_id').select2('open'); });";
476+
477+
$output .= Html::scriptBlock('$(function() {' . $js . '});');
478+
return $output;
479+
}
299480
}

inc/field/actorfield.class.php

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ public static function getName(): string {
9595
}
9696

9797
public function getRenderedHtml($canEdit = true) : string {
98+
global $CFG_GLPI;
99+
98100
$html = '';
99101
if (!$canEdit) {
100102
if (empty($this->value)) {
@@ -130,14 +132,38 @@ public function getRenderedHtml($canEdit = true) : string {
130132
$domId = $fieldName . '_' . $rand;
131133

132134
// Value needs to be non empty to allow execition of select2's initSelection
133-
$html .= '<select multiple
134-
name="' . $fieldName . '[]"
135-
id="' . $domId . '"
136-
value=""></select>';
137-
$html .= Html::scriptBlock("$(function() {
138-
pluginFormcreatorInitializeActor('$fieldName', '$rand', '$initialValue');
139-
});");
135+
if (version_compare(GLPI_VERSION, '9.5') < 0) {
136+
$html .= '<select multiple
137+
name="' . $fieldName . '[]"
138+
id="' . $domId . '"
139+
value=""></select>';
140+
$html .= Html::scriptBlock("$(function() {
141+
pluginFormcreatorInitializeActor('$fieldName', '$rand', '$initialValue');
142+
});");
143+
} else {
144+
$params = [
145+
'specific_tags' => [
146+
'multiple' => 'multiple',
147+
],
148+
'entity_restrict' => -1,
149+
'itemtype' => User::getType(),
150+
'values' => array_keys($value),
151+
'valuesnames' => array_values($value),
152+
];
153+
if (version_compare(GLPI_VERSION, '9.5.3') >= 0) {
154+
$params['_idor_token'] = Session::getNewIDORToken(User::getType());
155+
}
156+
$html .= \PluginFormcreatorCommon::jsAjaxDropdown(
157+
$fieldName . '[]',
158+
$domId,
159+
$CFG_GLPI['root_doc']."/ajax/getDropdownUsers.php",
160+
$params
161+
);
162+
$html .= Html::scriptBlock("$(function() {
163+
pluginFormcreatorInitializeActor2('$fieldName', '$rand');
164+
});");
140165

166+
}
141167
return $html;
142168
}
143169

js/scripts.js.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1289,7 +1289,7 @@ function pluginFormcreatorInitializeField(fieldName, rand) {
12891289
}
12901290

12911291
/**
1292-
* Initialize an actor field
1292+
* Initialize an actor field (< GLPI 9.5.3)
12931293
*/
12941294
function pluginFormcreatorInitializeActor(fieldName, rand, initialValue) {
12951295
var field = $('[name="' + fieldName + '[]"]');
@@ -1351,6 +1351,17 @@ function pluginFormcreatorInitializeActor(fieldName, rand, initialValue) {
13511351
});
13521352
}
13531353

1354+
/**
1355+
* Initialize an actor field (>= GLPI 9.5.3)
1356+
*/
1357+
function pluginFormcreatorInitializeActor2(fieldName, rand) {
1358+
var field = $('select[name="' + fieldName + '[]"]');
1359+
field.on("change", function(e) {
1360+
formcreatorShowFields($(field[0].form));
1361+
});
1362+
}
1363+
1364+
13541365
/**
13551366
* Initialize a checkboxes field
13561367
*/

0 commit comments

Comments
 (0)