Esempio n. 1
0
    /**
     */
    function tabs($tabs = [], $extra = [])
    {
        $extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
        $extra_by_id = [];
        if (isset($extra['by_id'])) {
            $extra_by_id = (array) $extra['by_id'];
            unset($extra['by_id']);
        }
        $links_prefix = $extra['links_prefix'] ?: 'tab_';
        $headers = [];
        $items = [];
        foreach ((array) $tabs as $k => $v) {
            $desc_raw = null;
            $disabled = null;
            if (!is_array($v)) {
                $content = $v;
                $v = [];
            } else {
                $content = $v['content'];
                $desc_raw = $v['desc_raw'];
                $disabled = $v['disabled'];
            }
            $content = trim($content);
            $_extra = (array) $extra_by_id[$k] + (array) $extra;
            if ($_extra['hide_empty'] && !strlen($content)) {
                continue;
            }
            $name = $v['name'] ?: $k;
            $desc = $v['desc'] ?: (!$_extra['no_auto_desc'] ? ucfirst(str_replace('_', ' ', $name)) : $name);
            $id = preg_replace('~[^a-z0-9_-]+~i', '', $v['id'] ?: $links_prefix . $k);
            if (isset($_extra['selected'])) {
                $is_active = $_extra['selected'] == $k;
            } else {
                $is_active = ++$i == 1;
            }
            if (isset($_extra['totals'][$name])) {
                $v['badge'] = intval(isset($_extra['totals'][$name]['total']) ? $_extra['totals'][$name]['total'] : $_extra['totals'][$name]);
            }
            $badge = isset($v['badge']) ? ' <sup class="badge badge-' . ($v['class_badge'] ?: 'info') . '">' . $v['badge'] . '</sup>' : '';
            if (!$_extra['no_headers']) {
                $class_head = $v['class_head'] ?: $_extra['class_head'];
                $class_head .= $_extra['class_add_head'] ? ' ' . $_extra['class_add_head'] : '';
                if ($is_active) {
                    $class_head = trim('active ' . $class_head);
                }
                $_extra_head = (array) $_extra['tab_head'];
                $_extra_head['class'] = $_extra_head['class'] ?: $class_head;
                $headers[] = '<li' . _attrs($_extra_head, ['id', 'class', 'style']) . '>
						<a ' . (!$disabled ? 'href="#' . fix_html_attr_id($id) . '" ' : '') . 'data-toggle="tab">' . ($desc_raw ?: t($desc)) . $badge . '</a>
					</li>';
            }
            $class_body = $_extra['class'] ?: $v['class_body'] ?: $_extra['class_body'];
            $class_body = $class_body ?: 'tab-pane';
            $class_body .= $_extra['class_add_body'] ? ' ' . $_extra['class_add_body'] : '';
            if ($is_active || $_extra['show_all']) {
                $class_body = trim('active ' . $class_body);
            } else {
                $class_body = trim('fade ' . $class_body);
            }
            $_extra_body = (array) $_extra['tab_body'];
            $_extra_body['id'] = $_extra_body['id'] ?: $id;
            $_extra_body['class'] = $_extra_body['class'] ?: $class_body;
            $items[] = '<div' . _attrs($_extra_body, ['id', 'class', 'style']) . '>' . $content . '</div>';
        }
        $body .= $headers ? '<ul id="' . $extra['id'] . '" class="nav nav-tabs">' . implode(PHP_EOL, (array) $headers) . '</ul>' . PHP_EOL : '';
        $body .= '<div id="' . $extra['id'] . '_content" class="tab-content">' . implode(PHP_EOL, (array) $items) . '</div>';
        return $body;
    }
Esempio n. 2
0
 function _attrs($extra, $names)
 {
     $body = [];
     $a = [];
     foreach ((array) $names as $name) {
         if (strlen($name) && isset($extra[$name])) {
             $a[$name] = $extra[$name];
         }
     }
     // Try to find and allow all data-* and ng-* attributes automatically
     foreach ((array) $extra as $name => $val) {
         if (strpos($name, 'data-') === 0 || strpos($name, 'ng-') === 0) {
             $a[$name] = $val;
         }
     }
     // Custom html attributes forced with sub-array "attr"
     if (is_array($extra['attr'])) {
         foreach ($extra['attr'] as $name => $val) {
             if (strlen($name)) {
                 $a[$name] = $val;
             }
         }
     }
     // Make sure that class attribute contains unique names and also cleanup extra spaces
     if (isset($a['class']) && strpos($a['class'], ' ') !== false) {
         $a['class'] = _attr_class_clean($a['class']);
     }
     foreach ($a as $name => $val) {
         if (is_array($val)) {
             $body[$name] = _htmlchars($name) . '="' . http_build_query(_htmlchars($val)) . '"';
         } else {
             if (!strlen($val)) {
                 continue;
             }
             if ($name == 'id') {
                 $val = fix_html_attr_id($val);
             }
             $body[$name] = _htmlchars($name) . '="' . _htmlchars($val) . '"';
         }
     }
     return $body ? ' ' . implode(' ', $body) : '';
 }
Esempio n. 3
0
 /**
  * Render result form html, gathered by row functions
  * Params here not required, but if provided - will be passed to form_begin()
  */
 function render($extra = [], $replace = [])
 {
     if (isset($this->_rendered)) {
         return $this->_rendered;
     }
     if (DEBUG_MODE) {
         $ts = microtime(true);
     }
     _class('core_events')->fire('form.before_render', [$extra, $replace, $this]);
     $this->_extra = $extra;
     $on_before_render = isset($extra['on_before_render']) ? $extra['on_before_render'] : $this->_on['on_before_render'];
     if (is_callable($on_before_render)) {
         $on_before_render($extra, $replace, $this);
     }
     if (!is_array($this->_body)) {
         $this->_body = [];
     }
     if (!is_array($extra)) {
         $extra = [];
     }
     $extra_override = [];
     $form_id = $this->_get_form_id($extra, $replace);
     if ($form_id) {
         $extra_override = $this->_get_extra_override($form_id);
     }
     $headless_form = $extra['no_form'] || $this->_params['no_form'];
     $csrf_protect = isset($extra['csrf']) ? (bool) $extra['csrf'] : (isset($this->_params['csrf']) ? $this->_params['csrf'] : $this->CONF_CSRF_PROTECTION);
     if (isset($extra['method']) && strtolower($extra['method']) != 'post') {
         $csrf_protect = false;
     }
     if ($headless_form) {
         $csrf_protect = false;
     }
     if ($csrf_protect && is_callable($csrf_protect)) {
         $csrf_protect = $csrf_protect($this, $extra);
     }
     if ($csrf_protect) {
         $csrf_guard = _class('csrf_guard')->configure(['form_id' => $form_id, 'token_name' => $this->CONF_CSRF_NAME]);
     }
     if (is_post()) {
         $is_current_form = isset($_POST[$this->CONF_FORM_ID_FIELD]) && $_POST[$this->CONF_FORM_ID_FIELD] == $form_id;
         if ($csrf_protect && $is_current_form && !$csrf_guard->validate($_POST[$this->CONF_CSRF_NAME])) {
             // We need this as validation now is skipping empty values
             if (!isset($_POST[$this->CONF_CSRF_NAME]) || trim($_POST[$this->CONF_CSRF_NAME]) == '') {
                 $_POST[$this->CONF_CSRF_NAME] = '__wrong_token_' . md5(microtime()) . '__';
             }
             $this->_params['show_alerts'] = true;
             $this->_validate_rules[$this->CONF_CSRF_NAME] = function ($in, $p, $a, &$error_msg) use($form_id, $csrf_guard) {
                 $csrf_guard->log_error(['form_id' => $form_id]);
                 $error_msg = 'Invalid CSRF token. Send the form again. If you did not send this request then close this page.';
                 return false;
             };
             $this->_set_hidden_token($csrf_guard);
         }
         $on_post = isset($extra['on_post']) ? $extra['on_post'] : $this->_on['on_post'];
         if (is_callable($on_post)) {
             $on_post($extra, $replace, $this);
         }
         $v = $this->_validate;
         if (isset($v) && is_callable($v['func'])) {
             $func = $v['func'];
             $func($v['validate_rules'], $v['post'], $v['extra'], $this);
         }
         $up = $this->_db_change_if_ok;
         if (isset($up) && is_callable($up['func'])) {
             $func = $up['func'];
             $func($up['table'], $up['fields'], $up['type'], $up['extra'], $this);
         }
     }
     if ($csrf_protect) {
         $this->_set_hidden_token($csrf_guard);
     }
     $r = (array) $this->_replace + (array) $replace;
     if (!$headless_form) {
         // Call these methods, if not done yet, save 2 api calls
         if (!isset($this->_body['form_begin'])) {
             $this->form_begin('', '', $extra + (array) $extra_override['form_begin'], $r);
         }
         if (!isset($this->_body['form_end'])) {
             $this->form_end($extra + (array) $extra_override['form_end'], $r);
         }
         // Force form_begin as first array element
         $form_begin = $this->_body['form_begin'];
         unset($this->_body['form_begin']);
         array_unshift($this->_body, $form_begin);
         // Force form_end as last array element
         $form_end = $this->_body['form_end'];
         unset($this->_body['form_end']);
         $this->_body['form_end'] = $form_end;
     }
     $tabbed_mode = false;
     $tabbed_buffer = [];
     $tabs = [];
     $tabs_extra = [];
     $tabs_name = '';
     $tabs_container = '';
     // Create tree of row_start and its children
     $item_row = [];
     $row_items = [];
     $row = false;
     $body_ids_to_extra = [];
     foreach ((array) $this->_body as $k => $v) {
         if ($v['name'] == 'row_start') {
             $row = $k;
         } elseif ($v['name'] == 'row_end') {
             $row = false;
         } elseif ($row) {
             $item_row[$k] = $row;
             $row_items[$row][$k] = $v['extra']['id'] ?: $v['extra']['name'];
         }
     }
     $all_errors = common()->_get_error_messages();
     foreach ((array) $this->_body as $k => $v) {
         if (!is_array($v)) {
             continue;
         }
         $_extra = (array) $v['extra'] + (array) $extra_override[$v['extra']['name']];
         $_replace = (array) $r + (array) $v['replace'];
         $func = $v['func'];
         if ($v['name'] == 'row_start') {
             // Mark row as containing errors, if children elements has at least one error
             foreach ((array) $row_items[$k] as $_k => $_id) {
                 if (!$_id || !isset($all_errors[$_id])) {
                     continue;
                 }
                 $_extra['errors'][$v['extra']['name']] = $all_errors[$_id];
             }
         }
         if ($this->_stacked_mode_on) {
             $_extra['stacked'] = $_extra['stacked'] ?: true;
         }
         // Callback to decide if we need to show this field or not
         if (isset($_extra['display_func']) && is_callable($_extra['display_func'])) {
             $_display_allowed = $_extra['display_func']($_extra, $_replace, $this);
             if (!$_display_allowed) {
                 $this->_body[$k] = '';
                 continue;
             }
         }
         if (DEBUG_MODE) {
             $_debug_fields[$k] = ['name' => $v['name'], 'extra' => $_extra];
         }
         $this->_body[$k]['rendered'] = $func($_extra, $_replace, $this);
         if ($this->_tabbed_mode_on) {
             $tabbed_mode = true;
             $tabbed_buffer[$k] = $this->_body[$k]['rendered'];
             if ($v['name'] == 'tab_start') {
                 $this->_tabs_counter++;
                 $tabs_name = $this->_tabs_name ?: 'tabs_' . $this->_tabs_counter;
                 $tabs_extra['by_id'][$tabs_name] = $this->_tabs_extra;
             }
             if ($v['name'] == 'tab_start' && !$tabs_container) {
                 $tabs_container = $k;
                 $this->_body[$k]['rendered'] = '__TAB_START__';
             } else {
                 unset($this->_body[$k]);
             }
         } elseif ($tabbed_mode) {
             // switch off
             if (!$this->_tabbed_mode_on) {
                 $tabbed_mode = false;
             }
             $tabs[$tabs_name] = implode(PHP_EOL, $tabbed_buffer);
             $tabbed_buffer = [];
             $tabs_name = '';
         }
     }
     if ($tabbed_buffer) {
         $tabs['tab_last'] = implode(PHP_EOL, $tabbed_buffer);
         $tabbed_buffer = [];
     }
     if ($tabs) {
         $this->_body[$tabs_container]['rendered'] = _class('html')->tabs($tabs, (array) $this->_params['tabs'] + (array) $tabs_extra);
     }
     if ($this->_params['show_alerts']) {
         $errors = common()->_get_error_messages();
         if ($errors) {
             $e = [];
             foreach ((array) $errors as $msg) {
                 $e[] = '<div class="' . $this->CLASS_ERROR . '"><button type="button" class="close" data-dismiss="alert">&times;</button>' . $msg . '</div>';
             }
             $this->_body = array_slice($this->_body, 0, 1, true) + ['error_message' => implode(PHP_EOL, $e)] + array_slice($this->_body, 1, null, true);
         }
     }
     if ($this->_params['stpl'] || $this->_params['return_array']) {
         $data = [];
         foreach ($this->_body as $k => $v) {
             $name = fix_html_attr_id($v['extra']['name'] ?: $v['extra']['id'] ?: $k);
             if ($name === 'form_action') {
                 $name = 'form_begin';
             }
             if (isset($data['form'][$name]) && !empty($data['form'][$name])) {
                 if (in_array($name, ['form_id', '_token', 'token'])) {
                     // allow only once
                 } else {
                     if (!is_array($data['form'][$name])) {
                         $tmp = $data['form'][$name];
                         $data['form'][$name] = [];
                         $data['form'][$name][] = $tmp;
                         unset($tmp);
                     }
                     $data['form'][$name][] = $v['rendered'];
                 }
             } else {
                 $_rendered = '';
                 if (is_array($v)) {
                     $_rendered = array_key_exists('rendered', $v) ? (string) $v['rendered'] : '';
                 } else {
                     $_rendered = $v;
                 }
                 $data['form'][$name] = $_rendered;
             }
         }
         // Fixes for easier usage
         if ($data['form']['form_id']) {
             $data['form']['form_begin'] .= PHP_EOL . $data['form']['form_id'];
             unset($data['form']['form_id']);
         }
         if (isset($data['form']['token']) && !isset($data['form']['_token'])) {
             $data['form']['_token'] = $data['form']['token'];
             unset($data['form']['token']);
         }
         if (isset($data['form']['_token'])) {
             $data['form']['form_begin'] .= PHP_EOL . $data['form']['_token'];
             unset($data['form']['_token']);
         }
         if (!isset($data['form']['begin'])) {
             $data['form']['begin'] = $data['form']['form_begin'];
             unset($data['form']['form_begin']);
         }
         if (!isset($data['form']['end'])) {
             $data['form']['end'] = $data['form']['form_end'];
             unset($data['form']['form_end']);
         }
         if ($this->_params['return_array']) {
             return $data['form'];
         } else {
             if (false === strpos($this->_params['stpl'], ' ') && tpl()->exists($this->_params['stpl'])) {
                 $this->_rendered = tpl()->parse($this->_params['stpl'], $data);
             } else {
                 $this->_rendered = tpl()->parse_string($this->_params['stpl'], $data);
             }
         }
         unset($data);
     } else {
         $rendered = [];
         foreach ($this->_body as $k => $v) {
             if (is_array($v)) {
                 $rendered[$k] = array_key_exists('rendered', $v) ? (string) $v['rendered'] : '';
             } else {
                 $rendered[$k] = $v;
             }
         }
         $this->_rendered = implode(PHP_EOL, $rendered);
         unset($rendered);
     }
     unset($this->_body);
     // Save some memory
     $css_framework = $extra['css_framework'] ?: ($this->_params['css_framework'] ?: conf('css_framework'));
     $extra['css_framework'] = $css_framework;
     $this->_rendered = _class('html5fw')->form_render_out($this->_rendered, $extra, $r, $this);
     $on_after_render = isset($extra['on_after_render']) ? $extra['on_after_render'] : $this->_on['on_after_render'];
     if (is_callable($on_after_render)) {
         $on_after_render($extra, $replace, $this);
     }
     _class('core_events')->fire('form.after_render', [$extra, $replace, $this]);
     if (DEBUG_MODE) {
         debug('form2[]', ['params' => $this->_params, 'fields' => $_debug_fields, 'time' => round(microtime(true) - $ts, 5), 'trace' => main()->trace_string()]);
     }
     return $this->_rendered;
 }