Пример #1
0
/**
 * Generates form elements. The main use for print_search() and print_form(), see examples of this functions.
 *
 * Options tree:
 * textarea -\
 *     (string)id, (string)name, (bool)readonly, (bool)disabled, (string)width, (string)class,
 *     (int)rows, (int)cols,
 *     (string)value, (bool,string)placeholder, (bool)ajax, (array)ajax_vars
 * text, input, password -\
 *     (string)id, (string)name, (bool)readonly, (bool)disabled, (string)width, (string)class,
 *     (string)value, (bool,string)placeholder, (bool)ajax, (array)ajax_vars,
 *     (bool)show_password
 * hidden -\
 *     (string)id, (string)value
 * select, multiselect -\
 *     (string)id, (string)name, (bool)readonly, (bool)disabled, (string)onchange, (string)width,
 *     (string)title, (int)size, (bool)right, (bool)live-search, (bool)encode, (bool)subtext
 *     (string)value, (array)values, (string)icon,
 *     values items can be arrays, ie:
 *         value => array('name' => string, 'group' => string, 'icon' => string, 'class' => string, 'style' => string)
 * datetime -\
 *     (string)id, (string)name, (bool)readonly, (bool)disabled,
 *     (string|FALSE)from, (string|FALSE)to, (bool)presets, (string)min, (string)max
 *     (string)value (use it for single input)
 * checkbox, switch -\
 *     (string)id, (string)name, (bool)readonly, (bool)disabled, (string)onchange,
 *     (bool)revert, (int)width, (string)size, (string)off-color, (string)on-color, (string)off-text, (string)on-text
 *     (string)value, (string)placeholder, (string)title
 * submit -\
 *     (string)id, (string)name, (bool)readonly, (bool)disabled,
 *     (string)class, (bool)right, (string)tooltip,
 *     (string)value, (string)form_id, (string)icon
 * html, raw -\
 *     (string)id,
 *     (string)html
 * newline -\
 *     (string)id,
 *     (bool)hr
 *
 * @param array $item Options for current form element
 * @param string $type Type of form element, also can passed as $item['type']
 * @return string Generated form element
 */
function generate_form_element($item, $type = '')
{
    $value_isset = isset($item['value']);
    if (!$value_isset) {
        $item['value'] = '';
    }
    if (!isset($item['type'])) {
        $item['type'] = $type;
    }
    $string = '';
    $element_tooltip = '';
    switch ($item['type']) {
        case 'hidden':
            if (!$item['readonly'] && !$item['disabled']) {
                $string .= '    <input type="' . $item['type'] . '" name="' . $item['id'] . '" id="' . $item['id'] . '" value="' . $item['value'] . '" />' . PHP_EOL;
            }
            break;
        case 'password':
        case 'textarea':
        case 'text':
        case 'input':
            if ($item['type'] != 'textarea') {
                $item_begin = '    <input type="' . $item['type'] . '" ';
                // password specific options
                if ($item['type'] == 'password') {
                    // disable autocomplete for passwords
                    $item_begin .= ' autocomplete="off" ';
                    // mask password field for disabled/readonly by bullet
                    if (strlen($item['value']) && ($item['disabled'] || $item['readonly'])) {
                        if (!($item['show_password'] && $_SESSION['userlevel'] > 7)) {
                            $item['value'] = '&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;';
                        }
                    }
                    // add icon for show/hide password
                    if ($item['show_password']) {
                        $item_begin .= ' data-toggle="password" ';
                        register_html_resource('js', 'bootstrap-show-password.min.js');
                        $GLOBALS['cache_html']['javascript'][] = "\$('[data-toggle=\"password\"]').password();";
                    }
                }
                $item_end = ' value="' . $item['value'] . '" />';
                $item_class = 'input';
            } else {
                $item_begin = '    <textarea ';
                // textarea specific options
                if (is_numeric($item['rows'])) {
                    $item_begin .= 'rows="' . $item['rows'] . '" ';
                }
                if (is_numeric($item['cols'])) {
                    $item_begin .= 'cols="' . $item['cols'] . '" ';
                }
                $item_end = '>' . $item['value'] . '</textarea>';
                $item_class = 'form-control';
            }
            if ($item['disabled']) {
                $item_end = ' disabled="1"' . $item_end;
            } else {
                if ($item['readonly']) {
                    $item_end = ' readonly="1"' . $item_end;
                }
            }
            if (isset($item['placeholder']) && $item['placeholder'] !== FALSE) {
                if ($item['placeholder'] === TRUE) {
                    $item['placeholder'] = $item['name'];
                }
                $string .= PHP_EOL;
                $string .= $item_begin . 'placeholder="' . $item['placeholder'] . '" ';
                $item['placeholder'] = TRUE;
                // Set to true for check at end
            } else {
                $string .= '  <div class="input-prepend">' . PHP_EOL;
                if (!$item['name']) {
                    $item['name'] = '<i class="icon-list"></i>';
                }
                $string .= '    <span class="add-on">' . $item['name'] . '</span>' . PHP_EOL;
                $string .= $item_begin;
            }
            if ($item['class']) {
                $item_class .= ' ' . $item['class'];
            }
            $string .= isset($item['width']) ? 'style="width:' . $item['width'] . '" ' : '';
            $string .= 'name="' . $item['id'] . '" id="' . $item['id'] . '" class="' . $item_class;
            if ($item['ajax'] === TRUE && is_array($item['ajax_vars'])) {
                $ajax_vars = array();
                if (!isset($item['ajax_vars']['field'])) {
                    // If query field not specified use item id as field
                    $item['ajax_vars']['field'] = $item['id'];
                }
                foreach ($item['ajax_vars'] as $k => $v) {
                    $ajax_vars[] = urlencode($k) . '=' . var_encode($v);
                }
                $string .= ' ajax-typeahead" autocomplete="off" data-link="/ajax/input.php?' . implode('&amp;', $ajax_vars);
                // Register scripts/css
                register_html_resource('js', 'typeahead.bundle.min.js');
                register_html_resource('css', 'typeaheadjs.css');
                // Ajax autocomplete for input
                // <input type='text' class='ajax-typeahead' data-link='your-json-link' />
                $item_id = $item['id'];
                $script = <<<SCRIPT
  var element_{$item_id} = \$('#{$item_id}.ajax-typeahead');
  var entries_{$item_id} = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    remote: {
      url: element_{$item_id}.data('link') + '&query=%QUERY',
      wildcard: '%QUERY',
      filter: function(json) {
        return json.options;
      }
    }
  });
  element_{$item_id}.typeahead({
      hint: false,
      highlight: true,
      minLength: 1
    },
    {
      name: 'options',
      limit: 16,
      source: entries_{$item_id}
    }
  );
SCRIPT;
                register_html_resource('script', $script);
            }
            $string .= '" ' . $item_end . PHP_EOL;
            $string .= $item['placeholder'] ? PHP_EOL : '  </div>' . PHP_EOL;
            // End 'text' & 'input'
            break;
        case 'switch':
            // switch specific options
            if ($item['revert']) {
                $item_switch = ' data-toggle="switch-revert"';
            } else {
                $item_switch = ' data-toggle="switch"';
            }
            if ($item['size']) {
                $item_switch .= ' data-size="' . $item['size'] . '"';
            }
            if ($item['on-color']) {
                $item_switch .= ' data-on-color="' . $item['on-color'] . '"';
            }
            if ($item['off-color']) {
                $item_switch .= ' data-off-color="' . $item['off-color'] . '"';
            }
            if ($item['on-text']) {
                $item_switch .= ' data-on-text="' . $item['on-text'] . '"';
            }
            if ($item['off-text']) {
                $item_switch .= ' data-off-text="' . $item['off-text'] . '"';
            }
            if (is_numeric($item['width']) && $item['width'] > 10) {
                $item_switch .= ' data-handle-width="' . intval($item['width'] / 2) . '"';
            }
        case 'checkbox':
            $string = '    <input type="checkbox" ';
            $string .= ' name="' . $item['id'] . '" id="' . $item['id'] . '" ' . $item_switch;
            if ($item['title']) {
                $string .= ' data-rel="tooltip" data-tooltip="' . escape_html($item['title']) . '"';
            }
            if ($item['value'] == '1' || $item['value'] === 'on' || $item['value'] === 'yes' || $item['value'] === TRUE) {
                $string .= ' checked';
            }
            if ($item['disabled']) {
                $string .= ' disabled="1"';
            } else {
                if ($item['readonly']) {
                    $string .= ' readonly="1" onclick="return false"';
                } else {
                    if ($item['onchange']) {
                        $string .= ' onchange="' . $item['onchange'] . '"';
                    }
                }
            }
            $string .= ' value="1" />';
            if (is_string($item['placeholder'])) {
                // add placeholder text at right of the element
                $string .= '      <span class="help-inline" style="margin-top: 4px;">' . $item['placeholder'] . '</span>' . PHP_EOL;
            }
            // End 'switch' & 'checkbox'
            break;
        case 'datetime':
            register_html_resource('js', 'bootstrap-datetimepicker.min.js');
            // Enable DateTime JS
            $id_from = $item['id'] . '_from';
            $id_to = $item['id'] . '_to';
            if ($value_isset && !$item['from'] && !$item['to']) {
                // Single datetime input
                $item['from'] = $item['value'];
                $item['to'] = FALSE;
                $item['presets'] = FALSE;
                $id_from = $item['id'];
                $name_from = $item['name'];
            } else {
                $name_from = 'From';
            }
            // Presets
            if ($item['from'] === FALSE || $item['to'] === FALSE) {
                $item['presets'] = FALSE;
            }
            if (is_numeric($item['from'])) {
                $item['from'] = strftime("%F %T", $item['from']);
            }
            if (is_numeric($item['to'])) {
                $item['to'] = strftime("%F %T", $item['to']);
            }
            if ($item['presets']) {
                $presets = array('sixhours' => 'Last 6 hours', 'today' => 'Today', 'yesterday' => 'Yesterday', 'tweek' => 'This week', 'lweek' => 'Last week', 'tmonth' => 'This month', 'lmonth' => 'Last month', 'tquarter' => 'This quarter', 'lquarter' => 'Last quarter', 'tyear' => 'This year', 'lyear' => 'Last year');
                // Recursive call
                $preset_item = array('id' => $item['id'] . '_preset', 'type' => 'select', 'name' => 'Date presets', 'width' => '110px', 'values' => $presets);
                $string .= generate_form_element($preset_item) . PHP_EOL;
            }
            // Date/Time input fields
            if ($item['from'] !== FALSE) {
                $string .= '  <div id="' . $id_from . '_div" class="input-prepend" style="margin-bottom: 0;">' . PHP_EOL;
                $string .= '    <span class="add-on btn"><i data-time-icon="icon-time" data-date-icon="icon-calendar"></i> ' . $name_from . '</span>' . PHP_EOL;
                //$string .= '    <input type="text" class="input-medium" data-format="yyyy-MM-dd hh:mm:ss" ';
                $string .= '    <input type="text" data-format="yyyy-MM-dd hh:mm:ss" ';
                $string .= isset($item['width']) ? 'style="width:' . escape_html($item['width']) . '" ' : 'style="width: 130px;" ';
                if ($item['disabled']) {
                    $string .= 'disabled="1" ';
                } else {
                    if ($item['readonly']) {
                        $item['disabled'] = TRUE;
                        // for js
                        $string .= 'readonly="1" ';
                    }
                }
                $string .= 'name="' . $id_from . '" id="' . $id_from . '" value="' . escape_html($item['from']) . '"/>' . PHP_EOL;
                $string .= '  </div>' . PHP_EOL;
            }
            if ($item['to'] !== FALSE) {
                $string .= '  <div id="' . $id_to . '_div" class="input-prepend" style="margin-bottom: 0;">' . PHP_EOL;
                $string .= '    <span class="add-on btn"><i data-time-icon="icon-time" data-date-icon="icon-calendar"></i> To</span>' . PHP_EOL;
                //$string .= '    <input type="text" class="input-medium" data-format="yyyy-MM-dd hh:mm:ss" ';
                $string .= '    <input type="text" data-format="yyyy-MM-dd hh:mm:ss" ';
                $string .= isset($item['width']) ? 'style="width:' . escape_html($item['width']) . '" ' : 'style="width: 140px;" ';
                $string .= 'name="' . $id_to . '" id="' . $id_to . '" value="' . escape_html($item['to']) . '"/>' . PHP_EOL;
                $string .= '  </div>' . PHP_EOL;
            }
            // JS SCRIPT
            $min = '-Infinity';
            $max = 'Infinity';
            $pattern = '/^(\\d{4})-(\\d{2})-(\\d{2}) ([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/';
            if (!empty($item['min'])) {
                if (preg_match($pattern, $item['min'], $matches)) {
                    $matches[2] = $matches[2] - 1;
                    array_shift($matches);
                    $min = 'new Date(' . implode(',', $matches) . ')';
                } else {
                    if ($item['min'] == 'now' || $item['min'] == 'current') {
                        $min = 'new Date()';
                    }
                }
            }
            if (!empty($item['max'])) {
                if (preg_match($pattern, $item['max'], $matches)) {
                    $matches[2] = $matches[2] - 1;
                    array_shift($matches);
                    $max = 'new Date(' . implode(',', $matches) . ')';
                } else {
                    if ($item['max'] == 'now' || $item['max'] == 'current') {
                        $max = 'new Date()';
                    }
                }
            }
            $script = '
      var startDate = ' . $min . ';
      var endDate   = ' . $max . ';
      $(document).ready(function() {
        $(\'[id=' . $id_from . '_div]\').datetimepicker({
          //pickSeconds: false,
          weekStart: 1,
          startDate: startDate,
          endDate: endDate
        });';
            if ($item['disabled']) {
                $script .= '
        $(\'[id=' . $id_from . '_div]\').datetimepicker(\'disable\');';
            }
            if ($item['to'] !== FALSE) {
                $script .= '
        $(\'[id=' . $id_to . '_div]\').datetimepicker({
          //pickSeconds: false,
          weekStart: 1,
          startDate: startDate,
          endDate: endDate
        });';
            }
            $script .= '
      });' . PHP_EOL;
            if ($item['presets']) {
                $script .= '
      $(\'select[id=' . $item['id'] . '_preset]\').change(function() {
        var input_from = $(\'input#' . $id_from . '\');
        var input_to   = $(\'input#' . $id_to . '\');
        switch ($(this).val()) {' . PHP_EOL;
                foreach ($presets as $k => $v) {
                    $preset = datetime_preset($k);
                    $script .= "          case '{$k}':\n";
                    $script .= "            input_from.val('" . $preset['from'] . "');\n";
                    $script .= "            input_to.val('" . $preset['to'] . "');\n";
                    $script .= "            break;\n";
                }
                $script .= '
          default:
            input_from.val("");
            input_to.val("");
            break;
        }
      });';
            }
            register_html_resource('script', $script);
            // End 'datetime'
            break;
        case 'tags':
            // Tags mostly same as multiselect, but used separate options and Bootstrap Tags Input JS
            register_html_resource('js', 'bootstrap-tagsinput.min.js');
            // Enable Tags Input JS
            //register_html_resource('js',  'bootstrap-tagsinput.js');      // Enable Tags Input JS
            register_html_resource('css', 'bootstrap-tagsinput.css');
            // Enable Tags Input CSS
            // defaults
            $delimiter = empty($item['delimiter']) ? ',' : $item['delimiter'];
            $script_begin = '';
            $script_options = array('trimValue' => 'true', 'tagClass' => 'function(item) {return "label label-default";}');
            //register_html_resource('script', '$("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput({trimValue: true, tagClass: function(item) {return "label label-default";} });');
            $string .= '    <select multiple data-toggle="tagsinput" name="' . $item['id'] . '[]" ' . $title;
            $string .= 'id="' . $item['id'] . '" ';
            if ($item['title']) {
                $string .= 'title="' . $item['title'] . '" ';
            } else {
                if (isset($item['name'])) {
                    $string .= 'title="' . $item['name'] . '" ';
                }
            }
            if (isset($item['placeholder']) && $item['placeholder'] !== FALSE) {
                if ($item['placeholder'] === TRUE) {
                    $item['placeholder'] = $item['name'];
                }
                //$string .= PHP_EOL;
                $string .= ' placeholder="' . $item['placeholder'] . '"';
                //$item['placeholder'] = TRUE; // Set to true for check at end
            }
            if ($item['disabled']) {
                $string .= ' disabled="1"';
            } else {
                if ($item['readonly']) {
                    $string .= ' disabled="1" readonly="1"';
                    // Bootstrap Tags Input not support readonly attribute, currently use disable
                }
            }
            if ($item['onchange']) {
                $string .= ' onchange="' . $item['onchange'] . '"';
            }
            $string .= '>' . PHP_EOL . '      ';
            // end <select>
            // Process values
            if (!is_array($item['value'])) {
                //$item['value'] = explode($delimiter, $item['value']);
                $item['value'] = array($item['value']);
            }
            //$item['value'] = array('test', 'hello');
            $suggest = array();
            foreach ($item['value'] as $entry) {
                $value = (string) $entry;
                if ($value == '[there is no data]' || $value === '') {
                    continue;
                }
                $suggest[] = $value;
                $string .= '<option value="' . $value . '"';
                $string .= '>' . escape_html($value) . '</option> ';
            }
            $string .= PHP_EOL . '    </select>' . PHP_EOL;
            // Generate typeahead from values
            $suggest = array_merge($suggest, (array) $item['values']);
            if (count($suggest)) {
                $option = '[{ hint: false, highlight: true, minLength: 1 },
                    { name: "suggest", limit: 16, source: suggest_' . $item['id'] . ' }]';
                $script_begin .= 'var suggest_' . $item['id'] . ' = new Bloodhound({ matchAnyQueryToken: true, queryTokenizer: Bloodhound.tokenizers.nonword, datumTokenizer: Bloodhound.tokenizers.nonword,
        local: [';
                $values = array();
                foreach (array_unique($suggest) as $k => $entry) {
                    if (is_array($entry)) {
                        $value = (string) $k;
                    } else {
                        $value = (string) $entry;
                    }
                    $values[] = "'" . str_replace("'", "\\'", $value) . "'";
                }
                $script_begin .= implode(',', $values);
                $script_begin .= ']});' . PHP_EOL;
                $script_options['typeaheadjs'] = $option;
                // Register scripts/css
                //register_html_resource('js', 'typeahead.bundle.js');
                register_html_resource('js', 'typeahead.bundle.min.js');
                register_html_resource('css', 'typeaheadjs.css');
            }
            if (count($script_options)) {
                $script = $script_begin;
                $script .= "\$('#" . $item['id'] . "').tagsinput({" . PHP_EOL;
                foreach ($script_options as $key => &$option) {
                    $option = '  ' . $key . ': ' . $option;
                }
                $script .= implode(',' . PHP_EOL, $script_options) . PHP_EOL;
                $script .= "});";
                register_html_resource('script', $script);
            }
            // End 'tags'
            break;
        case 'multiselect':
            unset($item['icon']);
            // For now not used icons in multiselect
        // For now not used icons in multiselect
        case 'select':
            $count_values = count($item['values']);
            if (empty($item['values'])) {
                $item['values'] = array(0 => '[there is no data]');
                $item['subtext'] = FALSE;
            }
            if ($item['type'] == 'multiselect') {
                $string .= '    <select multiple name="' . $item['id'] . '[]" ' . $title;
                // Enable Select/Deselect all (if select values count more than 4)
                if ($count_values > 4) {
                    $string .= ' data-actions-box="true" ';
                }
            } else {
                $string .= '    <select name="' . $item['id'] . '" ';
            }
            $string .= 'id="' . $item['id'] . '" ';
            if ($item['title']) {
                $string .= 'title="' . $item['title'] . '" ';
            } else {
                if (isset($item['name'])) {
                    $string .= 'title="' . $item['name'] . '" ';
                }
            }
            $data_width = $item['width'] ? ' data-width="' . $item['width'] . '"' : ' data-width="auto"';
            $data_size = is_numeric($item['size']) ? ' data-size="' . $item['size'] . '"' : ' data-size="15"';
            $string .= 'class="selectpicker show-tick';
            if ($item['right']) {
                $string .= ' pull-right';
            }
            $string .= '" data-selected-text-format="count>2"';
            if ($item['data-style']) {
                $string .= ' data-style="' . $item['data-style'] . '"';
            }
            // Enable Live search in values list (if select values count more than 12)
            if ($count_values > 12 && $item['live-search'] !== FALSE) {
                $string .= ' data-live-search="true"';
            }
            if ($item['disabled']) {
                $string .= ' disabled="1"';
            } else {
                if ($item['readonly']) {
                    $string .= ' disabled="1" readonly="1"';
                    // Bootstrap select not support readonly attribute, currently use disable
                }
            }
            if ($item['onchange']) {
                $string .= ' onchange="' . $item['onchange'] . '"';
            }
            $string .= $data_width . $data_size . '>' . PHP_EOL . '      ';
            // end <select>
            if (!is_array($item['value'])) {
                $item['value'] = array($item['value']);
            }
            // Prepare values for optgroups
            $values = array();
            $optgroup = array();
            foreach ($item['values'] as $k => $entry) {
                $k = (string) $k;
                $value = $item['encode'] ? var_encode($k) : $k;
                // Use base64+serialize encoding
                // Default group is '' (empty string), for allow to use 0 as group name!
                $group = '';
                if (!is_array($entry)) {
                    $entry = array('name' => $entry);
                } else {
                    if (isset($entry['group'])) {
                        $group = $entry['group'];
                    }
                }
                if ($item['subtext'] && !isset($entry['subtext'])) {
                    $entry['subtext'] = $k;
                }
                // Icons and empty name fix
                if ($item['icon'] && $item['value'] === array('')) {
                    // Only one main icon
                    $entry['icon'] = $item['icon'];
                    // Set value icon as global icon
                    unset($item['icon']);
                }
                if (in_array($k, $item['value'])) {
                    if (!($k === '' && $entry['name'] === '')) {
                        if ($item['icon']) {
                            $entry['icon'] = $item['icon'];
                            // Set value icon as global icon
                        }
                        // Element selected
                        $entry['selected'] = TRUE;
                    }
                } else {
                    if ($entry['name'] == '[there is no data]') {
                        $entry['disabled'] = TRUE;
                    }
                }
                if (strlen($entry['name']) == 0 && $k !== '') {
                    $entry['name'] = $k;
                }
                // if name still empty set it as value
                $values[$group][$value] = $entry;
            }
            // Generate optgroups for values
            foreach ($values as $group => $entries) {
                $optgroup[$group] = '';
                foreach ($entries as $value => $entry) {
                    $optgroup[$group] .= '<option value="' . $value . '"';
                    if (isset($entry['subtext']) && strlen($entry['subtext'])) {
                        $optgroup[$group] .= ' data-subtext="' . $entry['subtext'] . '"';
                    }
                    if ($entry['name'] == '[there is no data]') {
                        $optgroup[$group] .= ' disabled="1"';
                    }
                    if (isset($entry['class']) && $entry['class']) {
                        $optgroup[$group] .= ' class="' . $entry['class'] . '"';
                    } else {
                        if (isset($entry['style']) && $entry['style']) {
                            $optgroup[$group] .= ' style="' . $entry['style'] . '"';
                        } else {
                            if (isset($entry['color']) && $entry['color']) {
                                $optgroup[$group] .= ' style="color:' . $entry['color'] . ' !important;"';
                                //$optgroup[$group] .= ' data-content="<span style=\'color: ' . $entry['color'] . '\'>' . $entry['name'] . '</span>"';
                            }
                        }
                    }
                    // Icons
                    if (isset($entry['icon']) && $entry['icon']) {
                        $optgroup[$group] .= ' data-icon="' . $entry['icon'] . '"';
                    }
                    // Disabled, Selected
                    if (isset($entry['disabled']) && $entry['disabled']) {
                        $optgroup[$group] .= ' disabled="1"';
                    } else {
                        if (isset($entry['selected']) && $entry['selected']) {
                            $optgroup[$group] .= ' selected';
                        }
                    }
                    $optgroup[$group] .= '>' . escape_html($entry['name']) . '</option> ';
                }
            }
            // If item groups passed, use order passed from it
            $optgroups = array_keys($optgroup);
            if (isset($item['groups'])) {
                $groups = array_intersect((array) $item['groups'], $optgroups);
                $optgroups = array_diff($optgroups, $groups);
                $optgroups = array_merge($groups, $optgroups);
            }
            if (count($optgroups) === 1) {
                // Single optgroup, do not use optgroup tags
                $string .= array_shift($optgroup);
            } else {
                // Multiple optgroups implode
                foreach ($optgroups as $group) {
                    $entry = $optgroup[$group];
                    $label = $group !== '' ? ' label="' . $group . '"' : '';
                    $string .= '<optgroup' . $label . '>' . PHP_EOL;
                    $string .= $entry;
                    $string .= '</optgroup>' . PHP_EOL;
                }
            }
            $string .= PHP_EOL . '    </select>' . PHP_EOL;
            // End 'select' & 'multiselect'
            break;
        case 'submit':
            $button_type = 'submit';
            $button_onclick = '';
            $button_class = 'btn';
            if (!empty($item['class'])) {
                if (!preg_match('/btn-(default|primary|success|info|warning|danger)/', $item['class'])) {
                    // Add default class if custom class hot have it
                    $button_class .= ' btn-default';
                }
                $button_class .= ' ' . $item['class'];
            } else {
                $button_class .= ' btn-default';
            }
            if ($item['right']) {
                $button_class .= ' pull-right';
            }
            if ($item['form_id'] && $item['id'] == 'search') {
                // Note, used script form_to_path() stored in js/observium.js
                $button_type = 'button';
                $button_onclick = " onclick=\"form_to_path('" . $item['form_id'] . "');\"";
            }
            $button_disabled = $item['disabled'] || $item['readonly'];
            if ($button_disabled) {
                $button_class .= ' disabled';
            }
            $string .= '      <button id="' . $item['id'] . '" name="' . $item['id'] . '" type="' . $button_type . '"';
            // Add tooltip data
            if ($item['tooltip']) {
                $button_class .= ' tooltip-from-element';
                $string .= ' data-tooltip-id="tooltip-' . $item['id'] . '"';
                $element_tooltip .= '<div id="tooltip-' . $item['id'] . '" style="display: none;">' . $item['tooltip'] . '</div>' . PHP_EOL;
            }
            //$string .= ' class="'.$button_class.' text-nowrap" style="line-height: 20px;"'.$button_onclick;
            $string .= ' class="' . $button_class . ' text-nowrap"' . $button_onclick;
            if ($button_disabled) {
                $string .= ' disabled="1"';
            }
            if ($item['value']) {
                $string .= ' value="' . $item['value'] . '"';
            }
            $string .= '>';
            switch ($item['id']) {
                // Note. 'update' - use POST request, all other - use GET with generate url from js.
                case 'update':
                    $button_icon = 'icon-refresh';
                    $button_name = 'Update';
                    break;
                default:
                    $button_icon = 'icon-search';
                    $button_name = 'Search';
            }
            $nbsp = 0;
            if (array_key_exists('icon', $item)) {
                $button_icon = trim($item['icon']);
            }
            if (strlen($button_icon)) {
                $string .= '<i class="' . $button_icon . '"></i>';
                $nbsp++;
            }
            if (array_key_exists('name', $item)) {
                $button_name = trim($item['name']);
            }
            if (strlen($button_name)) {
                $nbsp++;
            }
            if ($nbsp == 2) {
                $string .= '&nbsp;';
            }
            $string .= $button_name . '</button>' . PHP_EOL;
            // End 'submit'
            break;
        case 'raw':
        case 'html':
            // Just add custom (raw) html element
            if (isset($item['html'])) {
                $string .= $item['html'];
            } else {
                $string .= '<span';
                if (isset($item['class'])) {
                    $string .= ' class="' . $item['class'] . '"';
                }
                $string .= '>' . $item['value'] . '</span>';
            }
            break;
        case 'newline':
            // Deprecated
            $string .= '<div class="clearfix" id="' . $item['id'] . '">';
            $string .= $item['hr'] ? '<hr />' : '<hr style="border-width: 0px;" />';
            $string .= '</div>' . PHP_EOL;
            // End 'newline'
            break;
    }
    return $string . $element_tooltip;
}
Пример #2
0
function detect_browser($user_agent = NULL)
{
    $ua_custom = !is_null($user_agent);
    // Used custom user agent?
    if (!$ua_custom && isset($GLOBALS['cache']['detect_browser'])) {
        //if (isset($_COOKIE['observium_screen_ratio']) && !isset($GLOBALS['cache']['detect_browser']['screen_resolution']))
        //{
        //  r($_COOKIE);
        //}
        // Return cached info
        return $GLOBALS['cache']['detect_browser'];
    }
    $detect = new Mobile_Detect();
    if ($ua_custom) {
        // Set custom User-Agent
        $detect->setUserAgent($user_agent);
    } else {
        $user_agent = $_SERVER['HTTP_USER_AGENT'];
    }
    // Default type and icon
    $type = 'generic';
    $icon = 'icon-laptop';
    if ($detect->isMobile()) {
        // Any phone device (exclude tablets).
        $type = 'mobile';
        $icon = 'glyphicon glyphicon-phone';
        if ($detect->isTablet()) {
            // Any tablet device.
            $type = 'tablet';
            $icon = 'icon-tablet';
        }
    }
    // Load additional function
    if (!function_exists('parse_user_agent')) {
        include_once $GLOBALS['config']['install_dir'] . '/libs/UserAgentParser.php';
    }
    // Detect Browser name, version and platform
    $ua_info = parse_user_agent($user_agent);
    $detect_browser = array('user_agent' => $user_agent, 'type' => $type, 'icon' => $icon, 'browser_full' => $ua_info['browser'] . ' ' . preg_replace('/^([^\\.]+(?:\\.[^\\.]+)?).*$/', '\\1', $ua_info['version']), 'browser' => $ua_info['browser'], 'version' => $ua_info['version'], 'platform' => $ua_info['platform']);
    // For custom UA, do not cache and return only base User-Agent info
    if ($ua_custom) {
        return $detect_browser;
    }
    // Load screen and DPI detector. This set cookies with:
    //  $_COOKIE['observium_screen_ratio'] - if ratio >= 2, than HiDPI screen is used
    //  $_COOKIE['observium_screen_resolution'] - screen resolution 'width x height', ie: 1920x1080
    //  $_COOKIE['observium_screen_size'] - current window size (less than resolution) 'width x height', ie: 1097x456
    register_html_resource('js', 'observium-screen.js');
    // Additional browser info (screen_ratio, screen_size, svg)
    if ($ua_info['browser'] == 'Firefox' && version_compare($ua_info['version'], '47.0') < 0) {
        // Do not use srcset in FF, while issue open:
        // https://bugzilla.mozilla.org/show_bug.cgi?id=1149357
        // Update, seems as in 47.0 partially fixed
        $zoom = 1;
    } else {
        if (isset($_COOKIE['observium_screen_ratio'])) {
            // Note, Opera uses ratio 1.5
            $zoom = round($_COOKIE['observium_screen_ratio']);
            // Use int zoom
        } else {
            // If JS not supported or cookie not set, use default zoom 2 (for allow srcset)
            $zoom = 2;
        }
    }
    $detect_browser['screen_ratio'] = $zoom;
    //$detect_browser['svg']          = ($ua_info['browser'] == 'Firefox'); // SVG supported or allowed
    if (isset($_COOKIE['observium_screen_resolution'])) {
        $detect_browser['screen_resolution'] = $_COOKIE['observium_screen_resolution'];
        //$detect_browser['screen_size']       = $_COOKIE['observium_screen_size'];
    }
    $GLOBALS['cache']['detect_browser'] = $detect_browser;
    // Store to cache
    //r($GLOBALS['cache']['detect_browser']);
    return $GLOBALS['cache']['detect_browser'];
}
Пример #3
0
<?php

register_html_resource('js', 'd3.v3.min.js');
register_html_resource('js', 'donut-chart.js');
?>
<div class="col-md-12" style="padding: 5px 20px 20px 20px;">
  <table style="width: 100%; background: none;">
    <tr style="align: center;">
      <td><div class="donut-chart" id="devices_chart"></div></td>
      <td><div class="donut-chart" id="ports_chart"></div></td>
      <td><div class="donut-chart" id="sensors_chart"></div></td>
      <td><div class="donut-chart" id="status_chart"></div></td>
      <td><div class="donut-chart" id="alerts_chart"></div></td>
    </tr>
  </table>
</div>

<script>
// Object.create() polyfill
if (typeof Object.create !== 'function') {
  Object.create = function(obj) {
    function F() {}
    F.prototype = obj;
    return new F();
  };
}

// Select containers
var chartContainer_devices = document.querySelector('#devices_chart');
var chartContainer_ports   = document.querySelector('#ports_chart');
var chartContainer_sensors = document.querySelector('#sensors_chart');
Пример #4
0
/**
 * Observium Network Management and Monitoring System
 * Copyright (C) 2006-2015, Adam Armstrong - http://www.observium.org
 *
 * @package    observium
 * @subpackage webui
 * @author     Adam Armstrong <*****@*****.**>
 * @copyright  (C) 2006-2013 Adam Armstrong, (C) 2013-2016 Observium Limited
 *
 */
//r(auth_user_level_permissions($_SESSION['userlevel']));
if ($_SESSION['userlevel'] >= 7) {
    // Enable google code prettify
    register_html_resource('js', 'google-code-prettify.js');
    register_html_resource('css', 'google-code-prettify.css');
    // Print device config navbar
    $navbar = array();
    $navbar['brand'] = "Config";
    $navbar['class'] = "navbar-narrow";
    $cmd_file = escapeshellarg($device_config_file);
    $rev = array('count' => 0);
    if (is_executable($config['svn'])) {
        //$svnlogs = external_exec($config['svn'] . ' log -q -l 8 ' . $device_config_file); // Last 8 entries
        $svnlogs = external_exec($config['svn'] . ' log -q ' . $cmd_file);
        foreach (explode("\n", $svnlogs) as $line) {
            // r1884 | rancid | 2014-09-19 19:50:12 +0400 (Fri, 19 Sep 2014)
            // ------------------------------------------------------------------------
            if (preg_match('/r(?<rev>\\d+) \\| .+? \\| (?<date>[\\d\\-]+ [\\d:]+ [\\+\\-]?\\d+)/', $line, $matches)) {
                $rev['list'][] = array('rev' => $matches['rev'], 'date' => format_timestamp(trim($matches['date'])));
                $rev['count']++;
Пример #5
0
/**
 * Observium
 *
 *   This file is part of Observium.
 *
 * @package    observium
 * @subpackage web
 * @copyright  (C) 2006-2013 Adam Armstrong, (C) 2013-2016 Observium Limited
 *
 */
if ($_SESSION['userlevel'] < 10) {
    print_error_permission();
    return;
}
register_html_resource('js', 'clipboard.min.js');
register_html_resource('script', 'new Clipboard("#clipboard");');
// Load SQL config into $database_config
load_sqlconfig($database_config);
// cache default and config.php-defined values
$defined_config = get_defined_settings();
$default_config = get_default_settings();
echo '<form id="settings" name="settings" method="post" action="" class="form form-inline">' . PHP_EOL;
// Pretty inefficient looping everything if section != all, but meh
// This is only done on this page, so there is no performance issue for the rest of Observium
foreach ($config_subsections as $section => $subdata) {
    if (isset($config_sections[$section]['edition']) && $config_sections[$section]['edition'] != OBSERVIUM_EDITION) {
        // Skip sections not allowed for current Observium edition
        continue;
    }
    echo '  <div class="row"> <div class="col-md-12"> <!-- BEGIN SECTION ' . $section . ' -->' . PHP_EOL;
    if ($vars['section'] == 'all' || $vars['section'] == $section) {
Пример #6
0
// Determine type of web browser.
$browser_type = detect_browser_type();
if ($browser_type == 'mobile' || $browser_type == 'tablet') {
    $_SESSION['touch'] = 'yes';
}
if ($vars['touch'] == "yes") {
    $_SESSION['touch'] = 'yes';
}
if ($vars['touch'] == "no") {
    unset($_SESSION['touch'], $vars['touch']);
}
if ($_SESSION['authenticated']) {
    $allow_mobile = in_array(detect_browser_type(), array('mobile', 'tablet')) ? $config['web_mouseover_mobile'] : TRUE;
    if ($config['web_mouseover'] && $allow_mobile) {
        // Enable qTip tooltips
        register_html_resource('js', 'jquery.qtip.min.js');
    }
    // Do various queries which we use in multiple places
    include $config['html_dir'] . "/includes/cache-data.inc.php";
    // Include navbar
    if ($vars['bare'] != "yes") {
        include $config['html_dir'] . "/includes/navbar.inc.php";
    }
}
?>

  <div class="container">

<?php 
if ($_SESSION['authenticated']) {
    if ($_SESSION['userlevel'] > 7) {
Пример #7
0
 *
 * @package    observium
 * @subpackage webui
 * @author     Adam Armstrong <*****@*****.**>
 * @copyright  (C) 2006-2013 Adam Armstrong, (C) 2013-2016 Observium Limited
 *
 */
register_html_title("Edit user");
if ($_SESSION['userlevel'] < 10) {
    print_error_permission();
    return;
}
include $config['html_dir'] . "/pages/usermenu.inc.php";
// Load JS entity picker
register_html_resource('js', 'tw-sack.js');
register_html_resource('js', 'observium-entities.js');
?>

<form method="post" action="" class="form form-inline">
<div class="navbar navbar-narrow">
  <div class="navbar-inner">
    <div class="container">
      <a class="brand">Edit User</a>
      <ul class="nav">

<?php 
$user_list_sort = array_sort_by(auth_user_list(), 'level', SORT_DESC, SORT_NUMERIC, 'username', SORT_ASC, SORT_STRING);
$user_list = array();
foreach ($user_list_sort as $entry) {
    humanize_user($entry);
    $user_list[$entry['user_id']] = $entry;
Пример #8
0
<?php

/**
 * Observium
 *
 *   This file is part of Observium.
 *
 * @package    observium
 * @subpackage map
 * @copyright  (C) 2006-2013 Adam Armstrong, (C) 2013-2016 Observium Limited
 *
 */
register_html_resource('css', 'leaflet.css');
register_html_resource('js', 'leaflet.js');
//register_html_resource('js', '/geo.php');
// [lat, lng], zoom
if (is_numeric($config['frontpage']['map']['zoom']) && is_numeric($config['frontpage']['map']['center']['lat']) && is_numeric($config['frontpage']['map']['center']['lng'])) {
    // Manual zoom & map center
    $leaflet_init = '[' . $config['frontpage']['map']['center']['lat'] . ', ' . $config['frontpage']['map']['center']['lng'] . '], ' . $config['frontpage']['map']['zoom'];
    $leaflet_bounds = '';
} else {
    // Auto zoom
    $leaflet_init = '[0, -0], 2';
    $leaflet_bounds = 'map.fitBounds(markers.getBounds(), { padding: [30, 30] });';
}
switch ($config['frontpage']['map']['api']) {
    case 'mapbox':
        /* Requires API key. Configurable tile sources in future.
           L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
             attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
             maxZoom: 18,
Пример #9
0
/**
 * Display Devices Inventory.
 *
 * @param array $vars
 * @return none
 *
 */
function print_inventory($vars)
{
    // On "Inventory" device tab display hierarchical list
    if ($vars['page'] == 'device' && is_numeric($vars['device']) && device_permitted($vars['device'])) {
        // DHTML expandable tree
        register_html_resource('js', 'mktree.js');
        register_html_resource('css', 'mktree.css');
        echo generate_box_open($vars['header']);
        echo '<table class="table table-striped  table-condensed "><tr><td>';
        echo '<div class="btn-group pull-right" style="margin-top:5px; margin-right: 5px;">
      <button class="btn btn-small" onClick="expandTree(\'enttree\');return false;"><i class="icon-plus muted small"></i> Expand</button>
      <button class="btn btn-small" onClick="collapseTree(\'enttree\');return false;"><i class="icon-minus muted small"></i> Collapse</button>
    </div>';
        echo '<div style="clear: left; margin: 5px;"><ul class="mktree" id="enttree" style="margin-left: -10px;">';
        print_ent_physical(0, 0, "liOpen");
        echo '</ul></div>';
        echo '</td></tr></table>';
        echo generate_box_close();
        return TRUE;
    }
    // With pagination? (display page numbers in header)
    $pagination = isset($vars['pagination']) && $vars['pagination'];
    pagination($vars, 0, TRUE);
    // Get default pagesize/pageno
    $pageno = $vars['pageno'];
    $pagesize = $vars['pagesize'];
    $start = $pagesize * $pageno - $pagesize;
    $param = array();
    $where = ' WHERE 1 ';
    foreach ($vars as $var => $value) {
        if ($value != '') {
            switch ($var) {
                case 'device':
                case 'device_id':
                    $where .= generate_query_values($value, 'device_id');
                    break;
                case 'os':
                    $where .= generate_query_values($value, 'os');
                    break;
                case 'parts':
                    $where .= generate_query_values($value, 'entPhysicalModelName', 'LIKE');
                    break;
                case 'serial':
                    $where .= generate_query_values($value, 'entPhysicalSerialNum', '%LIKE%');
                    break;
                case 'description':
                    $where .= generate_query_values($value, 'entPhysicalDescr', '%LIKE%');
                    break;
            }
        }
    }
    // Show inventory only for permitted devices
    //$query_permitted = generate_query_permitted(array('device'), array('device_table' => 'D'));
    $query = 'FROM `entPhysical`';
    $query .= ' LEFT JOIN `devices` USING(`device_id`) ';
    $query .= $where . $GLOBALS['cache']['where']['devices_permitted'];
    $query_count = 'SELECT COUNT(*) ' . $query;
    $query = 'SELECT * ' . $query;
    $query .= ' ORDER BY `hostname`';
    $query .= " LIMIT {$start},{$pagesize}";
    // Query inventories
    $entries = dbFetchRows($query, $param);
    // Query inventory count
    if ($pagination) {
        $count = dbFetchCell($query_count, $param);
    }
    $list = array('device' => FALSE);
    if (!isset($vars['device']) || empty($vars['device']) || $vars['page'] == 'inventory') {
        $list['device'] = TRUE;
    }
    $string = generate_box_open($vars['header']);
    $string .= '<table class="' . OBS_CLASS_TABLE_STRIPED . '">' . PHP_EOL;
    if (!$short) {
        $string .= '  <thead>' . PHP_EOL;
        $string .= '    <tr>' . PHP_EOL;
        if ($list['device']) {
            $string .= '      <th>Device</th>' . PHP_EOL;
        }
        $string .= '      <th>Name</th>' . PHP_EOL;
        $string .= '      <th>Description</th>' . PHP_EOL;
        $string .= '      <th>Part #</th>' . PHP_EOL;
        $string .= '      <th>Serial #</th>' . PHP_EOL;
        $string .= '    </tr>' . PHP_EOL;
        $string .= '  </thead>' . PHP_EOL;
    }
    $string .= '  <tbody>' . PHP_EOL;
    foreach ($entries as $entry) {
        $string .= '  <tr>' . PHP_EOL;
        if ($list['device']) {
            $string .= '    <td class="entity" style="white-space: nowrap">' . generate_device_link($entry, NULL, array('page' => 'device', 'tab' => 'entphysical')) . '</td>' . PHP_EOL;
        }
        if ($entry['ifIndex']) {
            $interface = get_port_by_ifIndex($entry['device_id'], $entry['ifIndex']);
            $entry['entPhysicalName'] = generate_port_link($interface);
        } elseif ($entry['entPhysicalClass'] == "sensor") {
            $sensor = dbFetchRow("SELECT * FROM `sensors` LEFT JOIN `sensors-state` USING(`sensor_id`)\n                            WHERE `device_id` = ? AND (`entPhysicalIndex` = ? OR `sensor_index` = ?)", array($entry['device_id'], $entry['entPhysicalIndex'], $entry['entPhysicalIndex']));
            //$ent_text .= ' ('.$sensor['sensor_value'] .' '. $sensor['sensor_class'].')';
            $entry['entPhysicalName'] = generate_entity_link('sensor', $sensor);
        }
        $string .= '    <td style="width: 160px;">' . $entry['entPhysicalName'] . '</td>' . PHP_EOL;
        $string .= '    <td>' . $entry['entPhysicalDescr'] . '</td>' . PHP_EOL;
        $string .= '    <td>' . $entry['entPhysicalModelName'] . '</td>' . PHP_EOL;
        $string .= '    <td>' . $entry['entPhysicalSerialNum'] . '</td>' . PHP_EOL;
        $string .= '  </tr>' . PHP_EOL;
    }
    $string .= '  </tbody>' . PHP_EOL;
    $string .= '</table>';
    $string .= generate_box_close();
    // Print pagination header
    if ($pagination) {
        $string = pagination($vars, $count) . $string . pagination($vars, $count);
    }
    $entries_allowed = array('entPhysical_id', 'device_id', 'entPhysicalIndex', 'entPhysicalDescr', 'entPhysicalClass', 'entPhysicalName', 'entPhysicalHardwareRev', 'entPhysicalFirmwareRev', 'entPhysicalSoftwareRev', 'entPhysicalAlias', 'entPhysicalAssetID', 'entPhysicalIsFRU', 'entPhysicalModelName', 'entPhysicalVendorType', 'entPhysicalSerialNum', 'entPhysicalContainedIn', 'entPhysicalParentRelPos', 'entPhysicalMfgName');
    foreach ($entries as $entry) {
        $entries_cleaned[$entry['entPhysical_id']] = array_intersect_key($entry, array_flip($entries_allowed));
    }
    // Print Inventories
    switch ($vars['format']) {
        case "csv":
            echo implode($entry, ", ");
            echo "\n";
            break;
        default:
            echo $string;
            break;
    }
}
Пример #10
0
          <li class="dropdown hidden-xs">
            <form id="searchform" class="navbar-search" action="#" style="margin-left: 5px; margin-right: 10px;  margin-top: 5px; margin-bottom: -5px;">
              <input style="width: 100px;" onkeyup="lookup(this.value);" onblur="$('#suggestions').fadeOut()" type="text" value="" class="dropdown-toggle" placeholder="Search" />
            </form>
            <div id="suggestions" class="typeahead dropdown-menu"></div>
          </li>
<?php 
// Script for go to first founded link in search
register_html_resource('script', '
$(function() {
  $(\'form#searchform\').each(function() {
    $(this).find(\'input\').keypress(function(e) {
      if (e.which==10 || e.which==13) {
        //console.log($(\'div#suggestions > li > a\').first().prop(\'href\'));
        $(\'form#searchform\').prop(\'action\', $(\'div#suggestions > li > a\').first().prop(\'href\'));
        // Only submit if we actually have a suggestion to link to
        if ($(\'div#suggestions > li > a\').length > 0) {
          this.form.submit();
        }
      }
    });
  });
});
');
$ua = array('browser' => detect_browser_type());
if ($_SESSION['touch'] == "yes") {
    $ua['url'] = generate_url($vars, array('touch' => 'no'));
} else {
    $ua['url'] = generate_url($vars, array('touch' => 'yes'));
}
if ($vars['touch'] == 'yes') {
    $ua['icon'] = 'glyphicon glyphicon-hand-up';