<?php
/*-------------------------------------------------------+
| PHPFusion Content Management System
| Copyright (C) PHP Fusion Inc
| https://phpfusion.com/
+--------------------------------------------------------+
| Filename: form_select.php
| Author: Frederick MC Chan (Chan)
| Co-Author: Takács Ákos (Rimelek)
+--------------------------------------------------------+
| This program is released as free software under the
| Affero GPL license. You can redistribute it and/or
| modify it under the terms of this license which you
| can read by viewing the included agpl.txt or online
| at www.gnu.org/licenses/agpl.html. Removal of this
| copyright header is strictly prohibited without
| written permission from the original author(s).
+--------------------------------------------------------*/
/**
* Select2 dynamics plugin version 3.5 (stable)
*
* Note on Tags Support
* $options['tags'] = default $input_value must not be multidimensional array but only as $value = array(TRUE,'2','3');
* For tagging - set both tags and multiple to TRUE
* http://select2.github.io/select2/
*
* @param $input_name
* @param string $label
* @param $input_value
* @param array $options
*
* Setting up a select chain
*
* There will be 2 select box, Parent Select and Child Select
* Parent Select has options value of: array(1 => 'Parent A', 2 => 'Parent B')
* Parent Child has options value of: array(3 => 'Child A', 4 => 'Child B');
* The way that these two select chain to each other is via $options['chain_index'] with a value of:
* array(3 => 1, 4 => 1); ***
* The above array is the 'id of child A' => 'id of parent of A'
* key - current option value (i.e. +60)
* value - parent value that this option value is chained against (i.e. Malaysia)
*
* Implementation
* 1. Do nothing for Parent Select
* 2. In Child Select add:
* $options['chainable'] - set to true
* $options['chain_to_id'] - unique input_id of the Parent Select
* $options['chain_index'] - the chain array (see ***)
*
* Example code
* form_select('parent', 'Parent Sample', $parent_callback_value, ['options'=>$parent_opts]);
* form_select('child', 'Child Sample', $child_callback_value, ['options' => $child_opts, 'chainable'=>TRUE, 'chain_to_id'=>'parent', 'chain_index'=>$chain_index_opts]);
*
* @return string
*
* @package dynamics/select2
*/
function form_select($input_name, $label, $input_value, $options = []) {
$locale = fusion_get_locale();
$title = $label ? stripinput($label) : ucfirst(strtolower(str_replace("_", " ", $input_name)));
$default_options = [
'options' => [],
'required' => FALSE,
'regex' => '',
'input_id' => $input_name,
'placeholder' => $locale['choose'],
'deactivate' => FALSE,
'safemode' => FALSE,
'allowclear' => FALSE,
'multiple' => FALSE,
'width' => '',
'inner_width' => '250px',
'keyflip' => FALSE,
'tags' => FALSE,
'jsonmode' => FALSE,
'chainable' => FALSE, // Set to True to Enable Chaining
'chain_to_id' => '', // Set which select it has to be chained to.
'db' => '', // Specify which DB to map
'id_col' => '', // Chain Primary Key Column Name
'cat_col' => '', // Chain Category Column Name
'title_col' => '', // Chain Title Column Name
'custom_query' => '', // SQL query replacements
'value_filter' => ['col' => '', 'value' => NULL], // Specify if building opts has to specifically match these conditions
'optgroup' => FALSE, // Enable the option group output - if db, id_col, cat_col, and title_col is specified.
'option_pattern' => "—",
'display_search_count' => "5",
'max_select' => FALSE,
'error_text' => $locale['error_input_default'],
'class' => '',
'inline' => FALSE,
'tip' => '',
'ext_tip' => '',
'delimiter' => ',',
'callback_check' => '',
'stacked' => '',
'onchange' => '',
'select2_disabled' => FALSE, // if select2_disabled is set to true, then we will not use the select2 plugin
'parent_value' => $locale['root'],
'add_parent_opts' => FALSE,
'disable_opts' => '',
'hide_disabled' => FALSE,
'no_root' => FALSE,
'show_current' => FALSE,
'db_cache' => TRUE,
'data' => []
];
$options += $default_options;
$input_value = clean_input_value($input_value);
$disable_opts = '';
if ($options['disable_opts']) {
$disable_opts = is_array($options['disable_opts']) ? $options['disable_opts'] : explode(',', $options['disable_opts']);
}
$list = [];
static $select_db = [];
// New DB Caching Function.
if ($options['db'] && $options['id_col'] && $options['title_col']) {
// Cache result
$cache = !$options['custom_query'];
if (empty($select_db[$options['db']]) || (!$cache or $options['db_cache'] === FALSE)) {
if (!empty($options['cat_col'])) {
$select_db[$options['db']] = dbquery_tree_full($options['db'], $options['id_col'], $options['cat_col'], "ORDER BY ".$options['cat_col']." ASC, ".$options['id_col']." ASC, ".$options['title_col']." ASC", ($options['custom_query'] ?: ""));
} else {
// if there is a custom query
if ($options['custom_query']) {
$select_result = dbquery($options['custom_query']);
} else {
$select_result = dbquery("SELECT * FROM ".$options['db']." ORDER BY ".$options['id_col']." ASC, ".$options['title_col']." ASC");
}
// then make into hierarchy
if (dbrows($select_result)) {
while ($data = dbarray($select_result)) {
$list[0][$data[$options['id_col']]] = $data;
}
$select_db[$options['db']] = $list;
}
}
/*
* Build opt functions
*/
if (!function_exists('get_form_select_opts')) {
// @todo: implement all options settings inherited from dbquery_select_hierarchy
function get_form_select_opts($data, $options, $id = 0, $level = 0) {
$list = [];
//array('text' => 'Parent Text', 'children' => array(1 => 'Child A' , 2 => 'Child B'));
if (!empty($data[$id])) {
foreach ($data[$id] as $key => $value) {
// Displays defined pattern
$pattern = "";
if ($options['option_pattern']) {
$pattern = str_repeat($options['option_pattern'], $level)." ";
}
// Build List
if (!empty($options['value_filter']['col']) && (!empty($options['value_filter']['value']) || $options['value_filter']['value'] !== NULL)) {
if (isset($value[$options['value_filter']['col']]) && $value[$options['value_filter']['col']] == $options['value_filter']['value']) {
$list[$key] = $pattern.$value[$options['title_col']];
}
} else {
$list[$key] = $pattern.$value[$options['title_col']];
}
// Build Child
if (isset($data[$key])) {
$child = get_form_select_opts($data, $options, $key, $level + 1);
if ($options['optgroup']) {
$list[$key] = [
'text' => $list[$key],
'children' => $child,
];
} else {
$list = (!empty($list)) ? $list + $child : $child;
}
}
}
} else {
// the list does not start with a root
foreach (array_keys($data) as $id) {
foreach ($data[$id] as $key => $value) {
// Displays defined pattern
$pattern = "";
if ($options['option_pattern']) {
$pattern = str_repeat($options['option_pattern'], $level)." ";
}
// Build List
if (!empty($options['value_filter']['col']) && (!empty($options['value_filter']['value']) || $options['value_filter']['value'] !== NULL)) {
if (isset($value[$options['value_filter']['col']]) && $value[$options['value_filter']['col']] == $options['value_filter']['value']) {
$list[$key] = $pattern.html_entity_decode($value[$options['title_col']]);
}
} else {
$list[$key] = $pattern.html_entity_decode($value[$options['title_col']]);
}
// Build Child
if (isset($data[$key])) {
$child = get_form_select_opts($data, $options, $key, $level + 1);
if ($options['optgroup']) {
$list[$key] = [
'text' => $list[$key],
'children' => $child,
];
} else {
$list = (!empty($list)) ? $list + $child : $child;
}
}
}
}
}
return (array)$list;
}
}
/**
* Build Chainable Reference
* array key current id
* value parent id
*/
if (!function_exists('get_form_select_chain_index')) {
function get_form_select_chain_index($data, $options) {
$list = [];
if (!empty($data)) {
$data = flatten_array($data);
foreach ($data as $value) {
$list[$value[$options['id_col']]] = $value[$options['cat_col']];
}
}
return $list;
}
}
}
// Automatic build chain index.
if ($options['chainable'] && $options['chain_to_id'] && empty($options['chain_index'])) {
$options['chain_index'] = get_form_select_chain_index($select_db[$options['db']], $options);
}
if (!empty($select_db[$options['db']])) {
// Build options and override declared options
$options['options'] = get_form_select_opts($select_db[$options['db']], $options);
} else {
$options['options'] = ['0' => $locale['no_opts']];
$options['deactivate'] = 1;
}
} else if (empty($options['options'])) {
$options['options'] = ['0' => $locale['no_opts']];
$options['deactivate'] = 1;
}
// Build a chain index and initialize the JS chain plugin
// $options['chainable'] - true
// $options['chain_to_id'] - parent id
// $options['chain_index'] - a list of array of current id and the parent id as value (see get_form_select_chain_index function how it's done)
if ($options['chainable'] && $options['chain_to_id'] && !empty($options['chain_index'])) {
fusion_load_script(DYNAMICS."assets/chainselect/jquery.chained.js");
add_to_jquery("$('#".$options['input_id']."').chained('#".$options['chain_to_id']."');");
}
// Optgroup with Hierarchy
if (!function_exists('form_select_build_optgroup')) {
function form_select_build_optgroup($array, $input_value, $options) {
$html = '';
$disable_opts = '';
if ($options['disable_opts']) {
$disable_opts = is_array($options['disable_opts']) ? $options['disable_opts'] : explode(',', $options['disable_opts']);
}
foreach ($array as $arr => $value) {
// where options is more than one value, pass to data attributes.
$data_attributes = '';
if (count($value) > 1) {
$data_options = [];
foreach ($value as $datakey => $dataval) {
$data_options[] = "data-$datakey='$dataval'";
}
$data_attributes = " ".implode(' ', $data_options)." ";
}
$select = "";
$chain = (isset($options['chain_index'][$arr]) ? " class='".$options['chain_index'][$arr]."' " : "");
$text_value = isset($value['text']) ? $value['text'] : $value;
// if you have data attributes, you must have text key
if (!empty($text_value) && !is_array($text_value)) {
if ($options['keyflip']) { // flip mode = store array values
if ($input_value !== '') {
$select = ($input_value == $text_value) ? " selected" : "";
}
$disabled = $disable_opts && in_array($arr, $disable_opts);
$hide = $disabled && $options['hide_disabled'];
$item = (!$hide ? "<option".$data_attributes."value='$text_value'".$chain.$select.($disabled ? 'disabled' : '').">".html_entity_decode($text_value)." ".($options['show_current'] && $input_value == $text_value ? '(Current Item)' : '')."</option>\n" : "");
} else {
if ($input_value !== '') {
$input_value = stripinput($input_value); // not sure if it can turn false to zero not null.
$select = (isset($input_value) && $input_value == $arr) ? ' selected' : '';
}
$disabled = $disable_opts && in_array($arr, $disable_opts);
$hide = $disabled && $options['hide_disabled'];
$item = (!$hide ? "<option".$data_attributes."value='$arr'".$chain.$select.($disabled ? 'disabled' : '').">".html_entity_decode($text_value)." ".($options['show_current'] && $input_value == $text_value ? '(Current Item)' : '')."</option>\n" : "");
//$item = "<option value='$arr'".$chain.$select.">$text_value</option>\n";
}
if (isset($value['children'])) {
$html .= "<optgroup label='".$value['text']."'>\n";
$html .= $item;
$html .= form_select_build_optgroup($value['children'], $input_value, $options);
$html .= "</optgroup>\n";
} else {
$html .= $item;
}
}
}
return $html;
}
}
if (!$options['width']) {
$options['width'] = $default_options['width'];
}
if ($options['multiple']) {
if ($input_value !== NULL) {
$input_value = explode($options['delimiter'], $input_value);
} else {
$input_value = [];
}
}
// always trim id
$options['input_id'] = trim($options['input_id'], "[]");
$allowclear = ($options['placeholder'] && $options['multiple'] || $options['allowclear']) ? "allowClear:true," : '';
$error_class = "";
if (\Defender::inputHasError($input_name)) {
$error_class = " has-error ";
if (!empty($options['error_text'])) {
$new_error_text = \Defender::getErrorText($input_name);
if (!empty($new_error_text)) {
$options['error_text'] = $new_error_text;
}
addnotice("danger", $options['error_text']);
}
}
$html = "<div id='".$options['input_id']."-field' class='form-group ".($options['inline'] && $label ? 'row' : '').$error_class.' '.$options['class']."' ".($options['width'] && !$label ? "style='width: ".$options['width']."'" : '').">\n";
$html .= ($label) ? "<label class='control-label ".($options['inline'] ? "col-xs-12 col-sm-12 col-md-3 col-lg-3" : '')."' for='".$options['input_id']."'>".$label.($options['required'] == TRUE ? "<span class='required'> *</span>" : '')."
".($options['tip'] ? "<i class='pointer fa fa-question-circle' title='".$options['tip']."'></i>" : '')."
</label>\n" : '';
$html .= $options['inline'] && $label ? "<div class='col-xs-12 col-sm-9 col-md-9 col-lg-9'>\n" : "";
if ($options['jsonmode'] || $options['tags']) {
// json mode.
$html .= "<div id='".$options['input_id']."-spinner' style='display:none;'>\n<img src='".fusion_get_settings('siteurl')."images/loader.svg'>\n</div>\n";
$html .= "<input ".($options['required'] ? "class='req'" : '')." type='hidden' name='$input_name' id='".$options['input_id']."' style='width: ".($options['width'] ? $options['inner_width'] : $default_options['width'])."'/>\n";
} else {
// normal mode
$html .= "<select ".($options['select2_disabled'] == TRUE ? " class='form-control' " : "")." name='$input_name' id='".$options['input_id']."' style='width: ".(!empty($options['inner_width']) ? $options['inner_width'] : $default_options['inner_width'])."'".($options['deactivate'] ? " disabled" : "").($options['onchange'] ? ' onchange="'.$options['onchange'].'"' : '').($options['multiple'] ? " multiple" : "").">\n";
$html .= ($options['allowclear']) ? "<option value=''></option>\n" : '';
// add parent value
if ($options['no_root'] == FALSE && !empty($options['cat_col']) || $options['add_parent_opts'] === TRUE) { // api options to remove root from selector. used in items creation.
$this_select = '';
if ($input_value !== NULL) {
if ($input_value !== '') {
$this_select = 'selected';
}
}
$html .= "<option value='0' ".$this_select." >".$options['parent_value']."</option>\n";
}
/**
* Supported Formatting
* ---------------------
* Have an array that looks like this in 'options' key
* array('text' => 'Parent Text', 'children' => array(1 => 'Child A' , 2 => 'Child B'));
* or
* array(1 => 'Option A', 2 => 'Option B');
*/
if (is_array($options['options'])) {
// Test if this is an optgroup
$test_array = $options['options'];
foreach ($test_array as $v) {
if (isset($v['text'])) {
$options['optgroup'] = TRUE;
break;
}
}
if ($options['optgroup']) {
$html .= form_select_build_optgroup($options['options'], $input_value, $options);
} else {
foreach ($options['options'] as $arr => $v) { // outputs: key, value, class - in order
$select = '';
$chain = '';
// Chain method always bind to option's array key
if (isset($options['chain_index'][$arr])) {
$chain = " class='".$options['chain_index'][$arr]."' ";
}
// do a disable for filter_opts item.
if ($options['keyflip']) { // flip mode = store array values
if ($input_value !== '') {
$select = ($input_value == $v) ? " selected" : "";
}
$disabled = $disable_opts && in_array($arr, $disable_opts);
$hide = $disabled && $options['hide_disabled'];
$html .= (!$hide ? "<option value='$v'".$chain.$select.($disabled ? 'disabled' : '').">".html_entity_decode($v)." ".($options['show_current'] && $input_value == $v ? '(Current Item)' : '')."</option>\n" : "");
} else {
if ($input_value !== '') {
//$input_value = stripinput($input_value); // not sure if can turn FALSE to zero not null.
$select = (isset($input_value) && $input_value == $arr) ? ' selected' : '';
}
$disabled = $disable_opts && in_array($arr, $disable_opts);
$hide = $disabled && $options['hide_disabled'];
$html .= (!$hide ? "<option value='$arr'".$chain.$select.($disabled ? 'disabled' : '').">".html_entity_decode($v)." ".($options['show_current'] && $input_value == $v ? '(Current Item)' : '')."</option>\n" : "");
}
}
}
}
$html .= "</select>\n";
}
$html .= $options['stacked'];
$html .= $options['ext_tip'] ? "<br/>\n<div class='m-t-10 tip'><i>".$options['ext_tip']."</i></div>" : "";
$html .= \Defender::inputHasError($input_name) && !$options['inline'] ? "<br/>" : "";
$html .= \Defender::inputHasError($input_name) ? "<div id='".$options['input_id']."-help' class='label label-danger p-5 display-inline-block'>".$options['error_text']."</div>" : "";
$html .= $options['inline'] && $label ? "</div>\n" : '';
$html .= "</div>\n";
if ($options['required']) {
$html .= "<input class='req' id='dummy-".$options['input_id']."' type='hidden'>\n"; // for jscheck
}
// Generate Defender Tag
$input_name = ($options['multiple']) ? str_replace("[]", "", $input_name) : $input_name;
\Defender::add_field_session([
'input_name' => clean_input_name($input_name),
'title' => clean_input_name($title),
'id' => $options['input_id'],
'type' => 'dropdown',
'regex' => $options['regex'],
'required' => $options['required'],
'safemode' => $options['safemode'],
'error_text' => $options['error_text'],
'callback_check' => $options['callback_check'],
'delimiter' => $options['delimiter'],
]);
// Initialize Select2
if ($options['select2_disabled'] === FALSE) {
// Select 2 Multiple requires hidden DOM.
if ($options['jsonmode'] === FALSE) {
// not json mode (normal)
$max_js = '';
if ($options['multiple'] && $options['max_select']) {
$max_js = "maximumSelectionSize : ".$options['max_select'].",";
}
$tag_js = '';
if ($options['tags']) {
$tag_value = json_encode(array_values($options['options']));
// The format yield must be : `tags:["red", "green", "blue", "orange", "white", "black", "purple", "cyan", "teal"]`
$tag_js = ($tag_value) ? "tags: ".html_entity_decode($tag_value)."" : "tags: []";
}
if ($options['required']) {
add_to_jquery("
if ($('#".$options['input_id']."').select2('val')) { $('dummy-".$options['input_id']."').val($('#".$options['input_id']."').select2('val'));} else { $('dummy-".$options['input_id']."').val('');}
$('#".$options['input_id']."').select2({
".($options['placeholder'] ? "placeholder: '".$options['placeholder']."'," : '')."
minimumResultsForSearch: ".$options['display_search_count'].",
".$max_js."
".$allowclear."
".$tag_js."
}).bind('change', function(e) { $('#dummy-".$options['input_id']."').val($(this).val()); });
");
} else {
add_to_jquery("
$('#".$options['input_id']."').select2({
".($options['placeholder'] ? "placeholder: '".$options['placeholder']."'," : '')."
minimumResultsForSearch: ".$options['display_search_count'].",
".$max_js."
".$allowclear."
".$tag_js."
});
");
}
} else {
// json mode
add_to_jquery("
var this_data = [{id:0, text: '".$options['placeholder']."'}];
$('#".$options['input_id']."').select2({
placeholder: '".$options['placeholder']."',
data: this_data
});
");
}
// For Multiple Callback JS
if (is_array($input_value) && $options['multiple']) { // stores as value;
$vals = '';
foreach ($input_value as $arr => $val) {
$val = html_entity_decode($val);
$vals .= ($arr == count($input_value) - 1) ? "'$val'" : "'$val',";
}
add_to_jquery("$('#".$options['input_id']."').select2('val', [$vals]);");
}
}
load_select2_script();
return $html;
}
/**
* Selector for registered user
*
* @param $input_name
* @param string $label
* @param bool $input_value - user id
* @param array $options
*
* @return string
*/
function form_user_select($input_name, $label = "", $input_value = FALSE, array $options = []) {
$locale = fusion_get_locale();
$title = $label ? stripinput($label) : ucfirst(strtolower(str_replace("_", " ", $input_name)));
$input_value = clean_input_value($input_value);
$default_options = [
'required' => FALSE,
'regex' => '',
'input_id' => $input_name,
'placeholder' => $locale['sel_user'],
'deactivate' => FALSE,
'safemode' => FALSE,
'allowclear' => FALSE,
'multiple' => FALSE,
'inner_width' => '250px',
'width' => '',
'keyflip' => FALSE,
'tags' => FALSE,
'jsonmode' => FALSE,
'chainable' => FALSE,
'max_select' => 1,
'error_text' => '',
'class' => '',
'stacked' => '',
'inline' => FALSE,
'tip' => '',
'ext_tip' => '',
'delimiter' => ',',
'callback_check' => '',
'file' => '',
'allow_self' => FALSE,
'callback_function' => '',
'image_path' => IMAGES."avatars/",
];
$options += $default_options;
$options['input_id'] = trim($options['input_id'], "[]");
$allowclear = ($options['placeholder'] && $options['multiple'] || $options['allowclear']) ? "allowClear:true," : '';
$length = "minimumInputLength: 1,";
$error_class = "";
if (Defender::inputHasError($input_name)) {
$error_class = "has-error ";
$new_error_text = Defender::getErrorText($input_name);
if (!empty($new_error_text)) {
$options['error_text'] = $new_error_text;
}
addnotice("danger", $options['error_text']);
}
$html = "<div id='".$options['input_id']."-field' class='form-group ".($options['inline'] && $label ? 'row ' : '').$error_class.$options['class']."' style='width:".$options['width']."'>\n";
$html .= ($label) ? "<label class='control-label ".($options['inline'] ? 'col-xs-12 col-sm-12 col-md-3 col-lg-3' : '')."' for='".$options['input_id']."'>".$label.($options['required'] == TRUE ? "<span class='required'> *</span>" : '')." ".($options['tip'] ? "<i class='pointer fa fa-question-circle' title=".$options['tip']."></i>" : '')."</label>\n" : '';
$html .= $options['inline'] && $label ? "<div class='col-xs-12 col-sm-9 col-md-9 col-lg-9'>\n" : "";
$html .= "<input ".($options['required'] ? "class='req'" : '')." type='hidden' name='$input_name' id='".$options['input_id']."' data-placeholder='".$options['placeholder']."' style='width:".$options['inner_width']."'".($options['deactivate'] ? ' disabled' : '')."/>\n";
if ($options['deactivate']) {
$html .= form_hidden($input_name, '', $input_value, ["input_id" => $options['input_id']]);
}
$html .= $options['stacked'];
$html .= $options['ext_tip'] ? "<br/>\n<div class='m-t-10 tip'><i>".$options['ext_tip']."</i></div>" : "";
$html .= \Defender::inputHasError($input_name) && !$options['inline'] ? "<br/>" : "";
$html .= \Defender::inputHasError($input_name) ? "<div id='".$options['input_id']."-help' class='label label-danger p-5 display-inline-block'>".$options['error_text']."</div>" : "";
$html .= $options['inline'] && $label ? "</div>\n" : '';
$html .= "</div>\n";
$root_prefix = fusion_get_settings("site_seo") == 1 ? fusion_get_settings('siteurl')."includes/" : INCLUDES;
$root_img = fusion_get_settings("site_seo") == 1 && !defined('ADMIN_PANEL') ? fusion_get_settings('siteurl') : '';
$path = !empty($options['file']) ? $options['file'] : $root_prefix."dynamics/assets/users/users.json.php".($options['allow_self'] ? "?allow_self=true" : "");
if (!empty($input_value)) {
// json mode.
$encoded = $options['callback_function'] && is_callable($options['callback_function']) ? $options['callback_function']($input_value) : user_search($input_value, $options['delimiter']);
} else {
$encoded = json_encode([]);
}
Defender::getInstance()->add_field_session([
'input_name' => clean_input_name($input_name),
'title' => $title,
'id' => $options['input_id'],
'type' => 'dropdown',
'required' => $options['required'],
'safemode' => $options['safemode'],
'error_text' => $options['error_text']
]);
add_to_jquery("
function avatar(item) {
if(!item.id) {return item.text;}
var avatar = item.avatar;
var level = item.level;
return '<table><tr><td style=\"\"><img style=\"height:35px;\" class=\"img-rounded\" src=\"".$root_img.$options['image_path']."' + avatar + '\"/></td><td style=\"padding-left:10px; padding-right:10px;line-height:1.2;\"><div><strong>' + item.text + '</strong></div>' + level + '</div></td></tr></table>';
}
$('#".$options['input_id']."').select2({
$length
multiple: true,
".($options['max_select'] !== FALSE ? "maximumSelectionSize: ".$options['max_select']."," : '')."
placeholder: '".$options['placeholder']."',
ajax: {
url: '$path',
dataType: 'json',
data: function (term, page) {
return {q: term};
},
results: function (data, page) {
//console.log(page);
return {results: data};
}
},
formatSelection: avatar,
escapeMarkup: function(m) { return m; },
formatResult: avatar,
".$allowclear."
})".(!empty($encoded) ? ".select2('data', $encoded );" : '')."
");
load_select2_script();
return $html;
}
/* Returns Json Encoded Object used in form_select_user */
function user_search($users, $delimiter) {
$user_opts = [];
$users = explode($delimiter, $users);
if (!empty($users)) {
foreach ($users as $user) {
$result = dbquery("SELECT user_id, user_name, user_avatar, user_level FROM ".DB_USERS." WHERE user_status=:status AND user_id=:id", [':status' => 0, ':id' => $user]);
if (dbrows($result) > 0) {
while ($udata = dbarray($result)) {
$user_avatar = !empty($udata['user_avatar']) ? $udata['user_avatar'] : "no-avatar.jpg";
$user_name = $udata['user_name'];
$user_level = getuserlevel($udata['user_level']);
$user_opts[] = [
'id' => $udata['user_id'],
'text' => $user_name,
'avatar' => $user_avatar,
"level" => $user_level
];
}
}
}
}
return json_encode($user_opts);
}
/**
* Select2 hierarchy
* Returns a full hierarchy nested dropdown.
*
* @param $input_name
* @param string $label
* @param string $input_value
* @param array $options
* @param $db - your db
* @param $name_col - the option text to show
* @param $id_col - unique id
* @param $cat_col - parent id
* ## The rest of the Params are used by the function itself -- no need to handle ##
* @param bool $self_id - not required
* @param bool $id - not required
* @param bool $level - not required
* @param bool $index - not required
* @param bool $data - not required
*
* @return string
*/
function form_select_tree($input_name, $label, $input_value, array $options, $db, $name_col, $id_col, $cat_col, $self_id = FALSE, $id = FALSE, $level = FALSE, $index = [], $data = FALSE) {
$html = '';
$locale = fusion_get_locale();
$title = $label ? stripinput($label) : ucfirst(strtolower(str_replace("_", " ", $input_name)));
$default_options = [
'required' => FALSE,
'regex' => '',
'input_id' => $input_name,
'placeholder' => $locale['choose'],
'deactivate' => FALSE,
'safemode' => FALSE,
'allowclear' => FALSE,
'multiple' => FALSE,
'width' => '',
'inner_width' => '250px',
'keyflip' => FALSE,
'tags' => FALSE,
'jsonmode' => FALSE,
'chainable' => FALSE,
'max_select' => FALSE,
'error_text' => $locale['error_input_default'],
'class' => '',
'inline' => FALSE,
'tip' => '',
'delimiter' => ',',
'callback_check' => '',
'file' => '',
'parent_value' => $locale['root'],
'add_parent_opts' => FALSE,
'disable_opts' => '',
'hide_disabled' => FALSE,
'no_root' => FALSE,
'show_current' => FALSE,
'query' => '',
'full_query' => '',
];
$options += $default_options;
$options['input_id'] = trim($options['input_id'], "[]");
if ($options['multiple']) {
if ($input_value) {
$input_value = explode('|', $input_value);
} else {
$input_value = [];
}
}
if (!$options['width']) {
$options['width'] = $default_options['width'];
}
$allowclear = ($options['placeholder'] && $options['multiple'] || $options['allowclear']) ? "allowClear:true" : '';
$disable_opts = '';
if ($options['disable_opts']) {
$disable_opts = is_array($options['disable_opts']) ? $options['disable_opts'] : explode(',', $options['disable_opts']);
}
/* Child patern */
$opt_pattern = str_repeat("—", $level);
if (!$level) {
$level = 0;
if (!isset($index[$id])) {
$index[$id] = ['0' => $locale['no_opts']];
}
$error_class = '';
if (\Defender::inputHasError($input_name)) {
$error_class = "has-error ";
if (!empty($options['error_text'])) {
$new_error_text = \Defender::getErrorText($input_name);
if (!empty($new_error_text)) {
$options['error_text'] = $new_error_text;
}
addnotice("danger", $options['error_text']);
}
}
$html = "<div id='".$options['input_id']."-field' class='form-group ".($options['inline'] && $label ? 'row ' : '').$error_class.$options['class']."' ".($options['inline'] && $options['width'] && !$label ? "style='width: ".$options['width']."'" : '').">\n";
$html .= ($label) ? "<label class='control-label ".($options['inline'] ? 'col-xs-12 col-sm-12 col-md-3 col-lg-3' : '')."' for='".$options['input_id']."'>".$label.($options['required'] == TRUE ? "<span class='required'> *</span>" : '')." ".($options['tip'] ? "<i class='pointer fa fa-question-circle' title=".$options['tip']."></i>" : '')."</label>\n" : '';
$html .= $options['inline'] && $label ? "<div class='col-xs-12 col-sm-9 col-md-9 col-lg-9'>\n" : "";
}
if ($level == 0) {
add_to_jquery("
$('#".$options['input_id']."').select2({
placeholder: '".$options['placeholder']."',
$allowclear
});
");
if (is_array($input_value) && $options['multiple']) { // stores as value;
$vals = '';
foreach ($input_value as $arr => $val) {
$vals .= ($arr == count($input_value) - 1) ? "'$val'" : "'$val',";
}
add_to_jquery("$('#".$options['input_id']."').select2('val', [$vals]);");
}
$html .= "<select name='$input_name' id='".$options['input_id']."' style='width: ".(!empty($options['inner_width']) ? $options['inner_width'] : $default_options['inner_width'])."'".($options['deactivate'] ? " disabled" : "").($options['multiple'] ? " multiple" : "").">";
$html .= $options['allowclear'] ? "<option value=''></option>\n" : '';
if ($options['no_root'] == FALSE) { // api options to remove root from selector. used in items creation.
$this_select = '';
if ($input_value !== NULL) {
if ($input_value !== '') {
$this_select = 'selected';
}
}
$html .= ($options['add_parent_opts'] == TRUE) ? "<option value='0' ".$this_select.">$opt_pattern ".$locale['parent']."</option>\n" : "<option value='0' ".$this_select." >$opt_pattern ".$options['parent_value']."</option>\n";
}
$index = dbquery_tree($db, $id_col, $cat_col, $options['query'], $options['full_query']);
if (!empty($index)) {
$data = dropdown_select($db, $id_col, $name_col, $cat_col, implode(',', flatten_array($index)), $options['query'], $options['full_query']);
}
}
if (!$id) {
$id = 0;
}
if (isset($index[$id]) && !empty($data)) {
foreach ($index[$id] as $value) {
// value is the array
//$hide = $disable_branch && $value == $self_id ? 1 : 0;
$name = $data[$value][$name_col];
//print_p($data[$value]);
$name = PHPFusion\QuantumFields::parseLabel($name);
$select = ($input_value !== "" && ($input_value == $value)) ? 'selected' : '';
$disabled = $disable_opts && in_array($value, $disable_opts);
$hide = $disabled && $options['hide_disabled'];
// do a disable for filter_opts item.
$html .= (!$hide) ? "<option value='$value' ".$select." ".($disable_opts && in_array($value, $disable_opts) ? 'disabled' : '')." >$opt_pattern $name ".($options['show_current'] && $self_id == $value ? '(Current Item)' : '')."</option>\n" : '';
if (isset($index[$value]) && (!$hide)) {
$html .= form_select_tree($input_name, $label, $input_value, $options, $db, $name_col, $id_col, $cat_col, $self_id, $value, $level + TRUE, $index, $data);
}
}
}
if (!$level) {
$html .= "</select>\n";
$html .= (($options['required'] == 1 && \Defender::inputHasError($input_name)) || \Defender::inputHasError($input_name)) ? "<div id='".$options['input_id']."-help' class='label label-danger p-5 display-inline-block'>".$options['error_text']."</div>" : "";
$html .= $options['inline'] && $label ? "</div>\n" : '';
$html .= "</div>\n";
if ($options['required']) {
$html .= "<input class='req' id='dummy-".$options['input_id']."' type='hidden'>\n"; // for jscheck
}
$input_name = ($options['multiple']) ? str_replace("[]", "", $input_name) : $input_name;
\Defender::add_field_session(
[
'input_name' => $input_name,
'title' => trim($title, '[]'),
'id' => $options['input_id'],
'type' => 'dropdown',
'regex' => $options['regex'],
'required' => $options['required'],
'safemode' => $options['safemode'],
'error_text' => $options['error_text'],
'callback_check' => $options['callback_check'],
'delimiter' => $options['delimiter'],
]
);
}
load_select2_script();
return $html;
}
/*
* Optimized performance by adding a self param to implode to fetch only certain rows
*/
function dropdown_select($db, $id_col, $name_col, $cat_col, $index_values, $filter = '', $query_replace = '') {
$data = [];
$query = "SELECT $id_col, $name_col, $cat_col FROM ".$db." ".($filter ? $filter." AND " : 'WHERE')." $id_col IN ($index_values) ORDER BY $name_col ASC";
if (!empty($query_replace)) {
$query = $query_replace;
}
$result = dbquery($query);
while ($row = dbarray($result)) {
$id = $row[$id_col];
$data[$id] = $row;
}
return $data;
}