PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / trunk
VikAppointments Services Booking Calendar vtrunk
trunk 1.2.17 1.2.18 1.2.19
vikappointments / libraries / adapter / html / classes / select.php
vikappointments / libraries / adapter / html / classes Last commit date
access.php 2 years ago behavior.php 5 months ago bootstrap.php 5 months ago contentlanguage.php 2 years ago date.php 1 month ago form.php 2 years ago formbehavior.php 5 months ago grid.php 2 years ago jquery.php 2 years ago list.php 2 years ago number.php 2 years ago select.php 2 years ago user.php 2 years ago
select.php
500 lines
1 <?php
2 /**
3 * @package VikWP - Libraries
4 * @subpackage adapter.html
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2023 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 JLoader::import('adapter.utilities.array');
15
16 /**
17 * Utility class for creating HTML select lists.
18 *
19 * @since 10.1.16
20 */
21 abstract class JHtmlSelect
22 {
23 /**
24 * Default values for options. Organized by option group.
25 *
26 * @var array
27 */
28 protected static $optionDefaults = array(
29 'option' => array(
30 'option.attr' => null,
31 'option.disable' => 'disable',
32 'option.id' => null,
33 'option.key' => 'value',
34 'option.key.toHtml' => true,
35 'option.label' => null,
36 'option.label.toHtml' => true,
37 'option.text' => 'text',
38 'option.text.toHtml' => true,
39 'option.class' => 'class',
40 'option.onclick' => 'onclick',
41 ),
42 );
43
44 /**
45 * Generates a grouped HTML selection list from nested arrays.
46 *
47 * @param array $data An array of groups, each of which is an array of options.
48 * @param string $name The value of the HTML name attribute
49 * @param array $options Options, an array of key/value pairs. Valid options are:
50 * Format options.
51 * Selection options. See {@see JHtmlSelect::options()}.
52 * group.id: The property in each group to use as the group id
53 * attribute. Defaults to none.
54 * group.label: The property in each group to use as the group
55 * label. Defaults to "text". If set to null, the data array index key is
56 * used.
57 * group.items: The property in each group to use as the array of
58 * items in the group. Defaults to "items". If set to null, group.id and
59 * group. label are forced to null and the data element is assumed to be a
60 * list of selections.
61 * id: Value to use as the select element id attribute. Defaults to
62 * the same as the name.
63 * list.attr: Attributes for the select element. Can be a string or
64 * an array of key/value pairs. Defaults to none.
65 * list.select: either the value of one selected option or an array
66 * of selected options. Default: none.
67 * list.translate: Boolean. If set, text and labels are translated via
68 * JText::translate().
69 *
70 * @return string HTML for the select list
71 *
72 * @throws RuntimeException If a group has contents that cannot be processed.
73 */
74 public static function groupedlist($data, $name, $options = array())
75 {
76 // Set default options and overwrite with anything passed in
77 $options = array_merge(
78 JHtml::$formatOptions,
79 array('format.depth' => 0, 'group.items' => 'items', 'group.label' => 'text', 'group.label.toHtml' => true, 'id' => false),
80 $options
81 );
82
83 // Apply option rules
84 if ($options['group.items'] === null)
85 {
86 $options['group.label'] = null;
87 }
88
89 $attribs = '';
90
91 if (isset($options['list.attr']))
92 {
93 if (is_array($options['list.attr']))
94 {
95 $attribs = ArrayHelper::toString($options['list.attr']);
96 }
97 else
98 {
99 $attribs = $options['list.attr'];
100 }
101
102 if ($attribs !== '')
103 {
104 $attribs = ' ' . $attribs;
105 }
106 }
107
108 $id = $options['id'] !== false ? $options['id'] : $name;
109 $id = str_replace(array('[', ']', ' '), '', $id);
110
111 // Disable groups in the options.
112 $options['groups'] = false;
113
114 $baseIndent = str_repeat($options['format.indent'], $options['format.depth']++);
115 $html = $baseIndent . '<select' . ($id !== '' ? ' id="' . $id . '"' : '') . ' name="' . $name . '"' . $attribs . '>' . $options['format.eol'];
116 $groupIndent = str_repeat($options['format.indent'], $options['format.depth']++);
117
118 foreach ($data as $dataKey => $group)
119 {
120 $label = $dataKey;
121 $id = '';
122 $noGroup = is_int($dataKey);
123
124 if ($options['group.items'] == null)
125 {
126 // Sub-list is an associative array
127 $subList = $group;
128 }
129 elseif (is_array($group))
130 {
131 // Sub-list is in an element of an array.
132 $subList = $group[$options['group.items']];
133
134 if (isset($group[$options['group.label']]))
135 {
136 $label = $group[$options['group.label']];
137 $noGroup = false;
138 }
139
140 if (isset($options['group.id']) && isset($group[$options['group.id']]))
141 {
142 $id = $group[$options['group.id']];
143 $noGroup = false;
144 }
145 }
146 elseif (is_object($group))
147 {
148 // Sub-list is in a property of an object
149 $subList = $group->{$options['group.items']};
150
151 if (isset($group->{$options['group.label']}))
152 {
153 $label = $group->{$options['group.label']};
154 $noGroup = false;
155 }
156
157 if (isset($options['group.id']) && isset($group->{$options['group.id']}))
158 {
159 $id = $group->{$options['group.id']};
160 $noGroup = false;
161 }
162 }
163 else
164 {
165 throw new RuntimeException('Invalid group contents.', 1);
166 }
167
168 if ($noGroup)
169 {
170 $html .= static::options($subList, $options);
171 }
172 else
173 {
174 $html .= $groupIndent . '<optgroup' . (empty($id) ? '' : ' id="' . $id . '"') . ' label="'
175 . ($options['group.label.toHtml'] ? htmlspecialchars($label, ENT_COMPAT, 'UTF-8') : $label) . '">' . $options['format.eol']
176 . static::options($subList, $options) . $groupIndent . '</optgroup>' . $options['format.eol'];
177 }
178 }
179
180 $html .= $baseIndent . '</select>' . $options['format.eol'];
181
182 return $html;
183 }
184
185 /**
186 * Create an object that represents an option in an option list.
187 *
188 * @param string $value The value of the option
189 * @param string $text The text for the option
190 * @param mixed $optKey If a string, the returned object property name for
191 * the value. If an array, options. Valid options are:
192 * attr: String|array. Additional attributes for this option.
193 * Defaults to none.
194 * disable: Boolean. If set, this option is disabled.
195 * label: String. The value for the option label.
196 * option.attr: The property in each option array to use for
197 * additional selection attributes. Defaults to none.
198 * option.disable: The property that will hold the disabled state.
199 * Defaults to "disable".
200 * option.key: The property that will hold the selection value.
201 * Defaults to "value".
202 * option.label: The property in each option array to use as the
203 * selection label attribute. If a "label" option is provided, defaults to
204 * "label", if no label is given, defaults to null (none).
205 * option.text: The property that will hold the the displayed text.
206 * Defaults to "text". If set to null, the option array is assumed to be a
207 * list of displayable scalars.
208 * @param string $optText The property that will hold the the displayed text. This
209 * parameter is ignored if an options array is passed.
210 * @param boolean $disable Not used.
211 *
212 * @return stdClass
213 */
214 public static function option($value, $text = '', $optKey = 'value', $optText = 'text', $disable = false)
215 {
216 $options = array(
217 'attr' => null,
218 'disable' => false,
219 'option.attr' => null,
220 'option.disable' => 'disable',
221 'option.key' => 'value',
222 'option.label' => null,
223 'option.text' => 'text',
224 );
225
226 if (is_array($optKey))
227 {
228 // Merge in caller's options
229 $options = array_merge($options, $optKey);
230 }
231 else
232 {
233 // Get options from the parameters
234 $options['option.key'] = $optKey;
235 $options['option.text'] = $optText;
236 $options['disable'] = $disable;
237 }
238
239 $obj = new stdClass;
240 $obj->{$options['option.key']} = $value;
241 $obj->{$options['option.text']} = trim($text) ? $text : $value;
242
243 /*
244 * If a label is provided, save it. If no label is provided and there is
245 * a label name, initialise to an empty string.
246 */
247 $hasProperty = $options['option.label'] !== null;
248
249 if (isset($options['label']))
250 {
251 $labelProperty = $hasProperty ? $options['option.label'] : 'label';
252 $obj->$labelProperty = $options['label'];
253 }
254 elseif ($hasProperty)
255 {
256 $obj->{$options['option.label']} = '';
257 }
258
259 // Set attributes only if there is a property and a value
260 if ($options['attr'] !== null)
261 {
262 $obj->{$options['option.attr']} = $options['attr'];
263 }
264
265 // Set disable only if it has a property and a value
266 if ($options['disable'] !== null)
267 {
268 $obj->{$options['option.disable']} = $options['disable'];
269 }
270
271 return $obj;
272 }
273
274 /**
275 * Generates the option tags for an HTML select list (with no select tag
276 * surrounding the options).
277 *
278 * @param array $arr An array of objects, arrays, or values.
279 * @param mixed $optKey If a string, this is the name of the object variable for
280 * the option value. If null, the index of the array of objects is used. If
281 * an array, this is a set of options, as key/value pairs. Valid options are:
282 * -Format options.
283 * -groups: Boolean. If set, looks for keys with the value
284 * "&lt;optgroup>" and synthesizes groups from them. Deprecated. Defaults
285 * true for backwards compatibility.
286 * -list.select: either the value of one selected option or an array
287 * of selected options. Default: none.
288 * -list.translate: Boolean. If set, text and labels are translated via
289 * JText::translate(). Default is false.
290 * -option.id: The property in each option array to use as the
291 * selection id attribute. Defaults to none.
292 * -option.key: The property in each option array to use as the
293 * selection value. Defaults to "value". If set to null, the index of the
294 * option array is used.
295 * -option.label: The property in each option array to use as the
296 * selection label attribute. Defaults to null (none).
297 * -option.text: The property in each option array to use as the
298 * displayed text. Defaults to "text". If set to null, the option array is
299 * assumed to be a list of displayable scalars.
300 * -option.attr: The property in each option array to use for
301 * additional selection attributes. Defaults to none.
302 * -option.disable: The property that will hold the disabled state.
303 * Defaults to "disable".
304 * -option.key: The property that will hold the selection value.
305 * Defaults to "value".
306 * -option.text: The property that will hold the the displayed text.
307 * Defaults to "text". If set to null, the option array is assumed to be a
308 * list of displayable scalars.
309 * @param string $optText The name of the object variable for the option text.
310 * @param mixed $selected The key that is selected (accepts an array or a string)
311 * @param boolean $translate Translate the option values.
312 *
313 * @return string HTML for the select list.
314 */
315 public static function options($arr, $optKey = 'value', $optText = 'text', $selected = null, $translate = false)
316 {
317 $options = array_merge(
318 JHtml::$formatOptions,
319 static::$optionDefaults['option'],
320 array('format.depth' => 0, 'groups' => true, 'list.select' => null, 'list.translate' => false)
321 );
322
323 if (is_array($optKey))
324 {
325 // Set default options and overwrite with anything passed in
326 $options = array_merge($options, $optKey);
327 }
328 else
329 {
330 // Get options from the parameters
331 $options['option.key'] = $optKey;
332 $options['option.text'] = $optText;
333 $options['list.select'] = $selected;
334 $options['list.translate'] = $translate;
335 }
336
337 $html = '';
338 $baseIndent = str_repeat($options['format.indent'], $options['format.depth']);
339
340 foreach ($arr as $elementKey => &$element)
341 {
342 $attr = '';
343 $extra = '';
344 $label = '';
345 $id = '';
346
347 if (is_array($element))
348 {
349 $key = $options['option.key'] === null ? $elementKey : $element[$options['option.key']];
350 $text = $element[$options['option.text']];
351
352 if (isset($element[$options['option.attr']]))
353 {
354 $attr = $element[$options['option.attr']];
355 }
356
357 if (isset($element[$options['option.id']]))
358 {
359 $id = $element[$options['option.id']];
360 }
361
362 if (isset($element[$options['option.label']]))
363 {
364 $label = $element[$options['option.label']];
365 }
366
367 if (isset($element[$options['option.disable']]) && $element[$options['option.disable']])
368 {
369 $extra .= ' disabled="disabled"';
370 }
371 }
372 elseif (is_object($element))
373 {
374 $key = $options['option.key'] === null ? $elementKey : $element->{$options['option.key']};
375 $text = $element->{$options['option.text']};
376
377 if (isset($element->{$options['option.attr']}))
378 {
379 $attr = $element->{$options['option.attr']};
380 }
381
382 if (isset($element->{$options['option.id']}))
383 {
384 $id = $element->{$options['option.id']};
385 }
386
387 if (isset($element->{$options['option.label']}))
388 {
389 $label = $element->{$options['option.label']};
390 }
391
392 if (isset($element->{$options['option.disable']}) && $element->{$options['option.disable']})
393 {
394 $extra .= ' disabled="disabled"';
395 }
396
397 if (isset($element->{$options['option.class']}) && $element->{$options['option.class']})
398 {
399 $extra .= ' class="' . $element->{$options['option.class']} . '"';
400 }
401
402 if (isset($element->{$options['option.onclick']}) && $element->{$options['option.onclick']})
403 {
404 $extra .= ' onclick="' . $element->{$options['option.onclick']} . '"';
405 }
406 }
407 else
408 {
409 // This is a simple associative array
410 $key = $elementKey;
411 $text = $element;
412 }
413
414 /*
415 * The use of options that contain optgroup HTML elements was
416 * somewhat hacked for J1.5. J1.6 introduces the grouplist() method
417 * to handle this better. The old solution is retained through the
418 * "groups" option, which defaults true in J1.6, but should be
419 * deprecated at some point in the future.
420 */
421
422 $key = (string) $key;
423
424 if ($key === '<OPTGROUP>' && $options['groups'])
425 {
426 $html .= $baseIndent . '<optgroup label="' . ($options['list.translate'] ? JText::translate($text) : $text) . '">' . $options['format.eol'];
427 $baseIndent = str_repeat($options['format.indent'], ++$options['format.depth']);
428 }
429 elseif ($key === '</OPTGROUP>' && $options['groups'])
430 {
431 $baseIndent = str_repeat($options['format.indent'], --$options['format.depth']);
432 $html .= $baseIndent . '</optgroup>' . $options['format.eol'];
433 }
434 else
435 {
436 // If no string after hyphen - take hyphen out
437 $splitText = explode(' - ', $text, 2);
438 $text = $splitText[0];
439
440 if (isset($splitText[1]) && $splitText[1] !== '' && !preg_match('/^[\s]+$/', $splitText[1]))
441 {
442 $text .= ' - ' . $splitText[1];
443 }
444
445 if (!empty($label) && $options['list.translate'])
446 {
447 $label = JText::translate($label);
448 }
449
450 if ($options['option.label.toHtml'])
451 {
452 $label = htmlentities($label);
453 }
454
455 if (is_array($attr))
456 {
457 $attr = ArrayHelper::toString($attr);
458 }
459 else
460 {
461 $attr = trim($attr);
462 }
463
464 $extra = ($id ? ' id="' . $id . '"' : '') . ($label ? ' label="' . $label . '"' : '') . ($attr ? ' ' . $attr : '') . $extra;
465
466 if (is_array($options['list.select']))
467 {
468 foreach ($options['list.select'] as $val)
469 {
470 $key2 = is_object($val) ? $val->{$options['option.key']} : $val;
471
472 if ($key == $key2)
473 {
474 $extra .= ' selected="selected"';
475 break;
476 }
477 }
478 }
479 elseif ((string) $key === (string) $options['list.select'])
480 {
481 $extra .= ' selected="selected"';
482 }
483
484 if ($options['list.translate'])
485 {
486 $text = JText::translate($text);
487 }
488
489 // Generate the option, encoding as required
490 $html .= $baseIndent . '<option value="' . ($options['option.key.toHtml'] ? htmlspecialchars($key, ENT_COMPAT, 'UTF-8') : $key) . '"'
491 . $extra . '>';
492 $html .= $options['option.text.toHtml'] ? htmlentities(html_entity_decode($text, ENT_COMPAT, 'UTF-8'), ENT_COMPAT, 'UTF-8') : $text;
493 $html .= '</option>' . $options['format.eol'];
494 }
495 }
496
497 return $html;
498 }
499 }
500