Beispiel #1
0
 /**
  * Render preset url
  *
  * @param object $form
  * @return array
  */
 public function render_preset_url(&$form)
 {
     $result = ['success' => true, 'error' => [], 'data' => ['html' => '', 'js' => '', 'css' => '']];
     $params = ['lc_translation_language_code' => $form->values['lc_missing_language_code'], 'lc_translation_text_sys' => $form->values['lc_missing_text_sys']];
     $result['data']['html'] = html::a(['href' => '/numbers/backend/i18n/basic/controller/translations/_edit?' . http_build_query2($params), 'value' => 'Translate']) . '<br/><br/>';
     return $result;
 }
Beispiel #2
0
 /**
  * Generate url
  *
  * @param array $options
  *		controller - array or string controller parts
  *		action - string action
  *		id - mixed id
  *		virtual - boolean flag
  *		tinyurl - whether to generate tinuurl
  *		full - boolean flag
  *		get_params - array of GET parameters
  * @return string
  */
 public static function get($options = [])
 {
     // we need to fix controller, action and id
     $controller = $options['controller'] ?? '';
     if (is_array($controller)) {
         $controller = implode('/', $controller);
     }
     $controller = rtrim($controller, '/');
     $action = $options['action'] ?? null;
     $id = $options['id'] ?? null;
     // processing virtual
     if (!empty($options['virtual'])) {
         $virtual_object = new object_virtual_controllers();
         $virtual_data = $virtual_object->get();
         foreach ($virtual_data as $k => $v) {
             if ($v['no_virtual_controller_path'] == $controller) {
                 $controller = '/__' . $v['no_virtual_controller_code'];
                 break;
             }
         }
     }
     // assembling
     $result = '';
     $host = '';
     if (!empty($options['full'])) {
         $host = rtrim(request::host(), '/');
     }
     $result .= $host;
     $result .= $controller;
     if (!empty($id) && empty($action)) {
         $action = 'index';
     }
     if (!empty($action)) {
         $result .= '/_' . $action;
     }
     if (!empty($id)) {
         $result .= '/' . $id;
     }
     // if we have GET parameters
     if (!empty($options['get_params'])) {
         $result .= '?' . http_build_query2($options['get_params']);
     }
     // if we need to generate tinyurl
     if (!empty($options['tinyurl'])) {
         $tinyurl_result = url_tinyurl::set($result);
         if ($tinyurl_result['success']) {
             $result = $host . '/__tinyurl/_i/' . $tinyurl_result['data']['hash'];
         }
     }
     return $result;
 }
Beispiel #3
0
 function widget_button($icon, $query, $label, $tooltip, $link_suffix = NULL, $flags = 0)
 {
     $p = '';
     // detect if button is active/selected
     $t = array(array(), array());
     $a = parse_url($query);
     if (isset($a['query'])) {
         parse_str($a['query'], $t[0]);
     } else {
         if (isset($a['path'])) {
             parse_str($a['path'], $t[0]);
         }
     }
     parse_str($_SERVER['QUERY_STRING'], $t[1]);
     // DEBUG
     //  echo '<pre><tt>';
     //  print_r ($t);
     //  $a = array_keys ($t[0]);
     $selected = 1;
     // black-out link
     // check query
     //  if (isset ($t[0][0]))
     if (count(array_diff($t[0], $t[1])) > 0) {
         $selected = 0;
     }
     // check domain
     if ($selected == 1) {
         if (!isset($t[0][0])) {
             $t = parse_url($query);
             //      echo $t['host'].', '.$_SERVER['HTTP_HOST'].'<br>';
             if (isset($t['host'])) {
                 if ($t['host'] != '') {
                     if (strcasecmp($t['host'], $_SERVER['HTTP_HOST'])) {
                         $selected = 0;
                     }
                 }
             }
         }
     }
     $p .= '<a';
     if ($selected) {
         $p .= ' class="tv2_selected" style="color:#000;"';
     } else {
         $p .= ' class="tooltip"';
     }
     //      if (!strncasecmp ($query, 'http://', 7))
     if (strstr($query, '://') || !strncasecmp($query, 'mailto:', 7)) {
         $p .= ' href="' . $query . '"';
     } else {
         if ($link_suffix) {
             $t = array();
             parse_str($query, $t[0]);
             parse_str($link_suffix, $t[1]);
             $a = array_merge($t[1], $t[0]);
             $query = http_build_query2($a, false);
         }
         $p .= ' href="?' . $query . '"';
     }
     $p .= '' . ' alt="' . $label . '"';
     if ($tooltip) {
         if (trim($tooltip) != '') {
             $p .= '' . ' onmouseover="tv2_tt_show(\'' . str_replace('\'', '\\\'', $tooltip) . '\');"' . ' onmouseout="tv2_tt_hide();"';
         }
     }
     //  if (!$icon)
     //      $p .= '';
     $p .= '>';
     $s = '';
     if ($icon) {
         $s .= '<img src="' . $icon . '" border="0" alt=""';
         //      if ($flags & WIDGET_BUTTON_CLIP)
         //        $s .= ' style="width:20%;clip:rect(10px 150px 150px 70px);position:absolute;"';
         //      if ($flags & WIDGET_BUTTON_SMALL)
         //        $s .= ' height="16"';
         $s .= '' . ' onerror="this.parentNode.removeChild(this);"' . '>';
     }
     //  if ($icon && $label)
     //    $p .= '&nbsp;';
     //  if ($flags & WIDGET_BUTTON_STATIC)
     //    return ($icon ? $s : '');
     $p .= $s;
     if (!($flags & WIDGET_BUTTON_ONLY)) {
         //      if ($selected)
         //        $p .= '<span class="tv2_selected">';
         $p .= '' . $label;
         //      if ($selected)
         //        $p .= '</span>';
     }
     //  if ($tooltip)
     //    if (trim ($tooltip) != '')
     //      $p .= '<span>'.$tooltip.'</span>';
     //  if ($selected)
     //    $p .= '</span>';
     //  else
     $p .= '</a>';
     return $p;
 }
Beispiel #4
0
 function misc_getlink($args = array(), $use_existing_arguments = false)
 {
     return '?' . http_build_query2($args, $use_existing_arguments);
 }
Beispiel #5
0
 /**
  * Render form
  *
  * @return mixed
  */
 public function render()
 {
     // ajax requests from another form
     if ($this->flag_another_ajax_call) {
         return null;
     }
     $this->tabindex = 1;
     // css & js
     numbers_frontend_media_libraries_jssha_base::add();
     layout::add_js('/numbers/media_submodules/numbers_frontend_html_form_media_js_base.js', -10000);
     // include master js
     if (!empty($this->master_object) && method_exists($this->master_object, 'add_js')) {
         $this->master_object->add_js();
     }
     // include js
     $filename = str_replace('_model_', '_media_js_', $this->form_class) . '.js';
     if (file_exists('./../libraries/vendor/' . str_replace('_', '/', $filename))) {
         layout::add_js('/numbers/media_submodules/' . $filename);
     }
     $this->misc_settings['extended_js_class'] = 'numbers.' . $this->form_class;
     // include css
     $filename = str_replace('_model_', '_media_css_', $this->form_class) . '.css';
     if (file_exists('./../libraries/vendor/' . str_replace('_', '/', $filename))) {
         layout::add_css('/numbers/media_submodules/' . $filename);
     }
     // load mask
     numbers_frontend_media_libraries_loadmask_base::add();
     // new record action
     $mvc = application::get('mvc');
     if (object_controller::can('record_new')) {
         $onclick = 'return confirm(\'' . strip_tags(i18n(null, object_content_messages::confirm_blank)) . '\');';
         $this->actions['form_new'] = ['value' => 'New', 'sort' => -31000, 'icon' => 'file-o', 'href' => $mvc['full'] . '?' . $this::button_submit_blank . '=1', 'onclick' => $onclick, 'internal_action' => true];
     }
     // back to list
     if (object_controller::can('list_view')) {
         $this->actions['form_back'] = ['value' => 'Back', 'sort' => -32000, 'icon' => 'arrow-left', 'href' => $mvc['controller'] . '/_index', 'internal_action' => true];
     }
     // reload button
     if ($this->values_loaded) {
         $url = $mvc['full'] . '?' . http_build_query2($this->pk);
         $this->actions['form_refresh'] = ['value' => 'Refresh', 'sort' => 32000, 'icon' => 'refresh', 'href' => $url, 'internal_action' => true];
     }
     // handling override_field_value method
     if (!empty($this->wrapper_methods['pre_render']['main'])) {
         call_user_func_array($this->wrapper_methods['pre_render']['main'], [&$this]);
     }
     // assembling everything into result variable
     $result = [];
     // order containers based on order column
     array_key_sort($this->data, ['order' => SORT_ASC]);
     foreach ($this->data as $k => $v) {
         if (!$v['flag_child']) {
             if ($v['type'] == 'fields' || $v['type'] == 'details') {
                 // reset tabs
                 $this->current_tab = [];
                 $temp = $this->render_container($k);
                 if ($temp['success']) {
                     $result[$k] = $temp['data'];
                 }
             } else {
                 if ($v['type'] == 'tabs') {
                     // tabs
                     $tab_id = "form_tabs_{$this->form_link}_{$k}";
                     $tab_header = [];
                     $tab_values = [];
                     $tab_options = [];
                     $have_tabs = false;
                     // sort rows
                     array_key_sort($v['rows'], ['order' => SORT_ASC]);
                     foreach ($v['rows'] as $k2 => $v2) {
                         $this->current_tab[] = "{$tab_id}_{$k2}";
                         $labels = '';
                         foreach (['records', 'danger', 'warning', 'success', 'info'] as $v78) {
                             $labels .= html::label2(['type' => $v78 == 'records' ? 'primary' : $v78, 'style' => 'display: none;', 'value' => 0, 'id' => implode('__', $this->current_tab) . '__' . $v78]);
                         }
                         $tab_header[$k2] = i18n(null, $v2['options']['label_name']) . $labels;
                         $tab_values[$k2] = '';
                         // handling override_tabs method
                         if (!empty($this->wrapper_methods['override_tabs']['main'])) {
                             $tab_options[$k2] = call_user_func_array($this->wrapper_methods['override_tabs']['main'], [&$this, &$v2, &$k2, &$this->values]);
                             if (empty($tab_options[$k2]['hidden'])) {
                                 $have_tabs = true;
                             }
                         } else {
                             $have_tabs = true;
                         }
                         // tab index for not hidden tabs
                         if (empty($tab_options[$k2]['hidden'])) {
                             $tab_options[$k2]['tabindex'] = $this->tabindex;
                             $this->tabindex++;
                         }
                         // render containers
                         array_key_sort($v2['elements'], ['order' => SORT_ASC]);
                         foreach ($v2['elements'] as $k3 => $v3) {
                             $temp = $this->render_container($v3['options']['container']);
                             if ($temp['success']) {
                                 $tab_values[$k2] .= $temp['data']['html'];
                             }
                         }
                         // remove last element from an array
                         array_pop($this->current_tab);
                     }
                     // if we do not have tabs
                     if ($have_tabs) {
                         $result[$k]['html'] = html::tabs(['id' => $tab_id, 'class' => 'form-tabs', 'header' => $tab_header, 'options' => $tab_values, 'tab_options' => $tab_options]);
                     }
                 }
             }
         }
     }
     // formatting data
     $temp = [];
     foreach ($result as $k => $v) {
         $temp[] = $v['html'];
     }
     $result = implode('', $temp);
     // we need to skip internal actions
     if (!empty($this->options['no_actions'])) {
         foreach ($this->actions as $k0 => $v0) {
             if (!empty($v0['internal_action'])) {
                 unset($this->actions[$k0]);
             }
         }
     }
     // rendering actions
     if (!empty($this->actions)) {
         $value = '<div style="text-align: right;">' . $this->render_actions() . '</div>';
         $value .= '<hr class="simple" />';
         $result = $value . $result;
     }
     // messages
     if (!empty($this->errors['general'])) {
         $messages = '';
         foreach ($this->errors['general'] as $k => $v) {
             $messages .= html::message(['options' => $v, 'type' => $k]);
         }
         $result = '<div class="form_message_container">' . $messages . '</div>' . $result;
     }
     // couple hidden fields
     $result .= html::hidden(['name' => '__form_link', 'value' => $this->form_link]);
     $result .= html::hidden(['name' => '__form_values_loaded', 'value' => $this->values_loaded]);
     $result .= html::hidden(['name' => '__form_onchange_field_values_key', 'value' => '']);
     if (!empty($this->options['bypass_hidden_values'])) {
         foreach ($this->options['bypass_hidden_values'] as $k => $v) {
             $result .= html::hidden(['name' => $k, 'value' => $v]);
         }
     }
     // js to update counters in tabs
     if (!empty($this->errors['tabs'])) {
         foreach ($this->errors['tabs'] as $k => $v) {
             layout::onload("\$('#{$k}').html({$v}); \$('#{$k}').show();");
         }
     }
     // if we have form
     if (empty($this->options['skip_form'])) {
         $mvc = application::get('mvc');
         $result = html::form(['action' => $mvc['full'], 'name' => "form_{$this->form_link}_form", 'id' => "form_{$this->form_link}_form", 'value' => $result, 'onsubmit' => empty($this->options['no_ajax_form_reload']) ? 'return numbers.form.on_form_submit(this);' : null]);
     }
     // if we came from ajax we return as json object
     if (!empty($this->options['input']['__ajax'])) {
         $result = ['success' => true, 'error' => [], 'html' => $result, 'js' => layout::$onload];
         layout::render_as($result, 'application/json');
     }
     $result = "<div id=\"form_{$this->form_link}_form_mask\"><div id=\"form_{$this->form_link}_form_wrapper\">" . $result . '</div></div>';
     // if we have segment
     if (isset($this->options['segment'])) {
         $temp = is_array($this->options['segment']) ? $this->options['segment'] : [];
         $temp['value'] = $result;
         $result = html::segment($temp);
     }
     return $result;
 }
Beispiel #6
0
    /**
     * Render widget
     *
     * @return mixed
     */
    public function render()
    {
        $result = '';
        // action bar
        $result .= '<div style="text-align: right;">';
        $result .= html::a(array('value' => html::icon(['type' => 'comment']) . ' ' . i18n(null, 'New'), 'href' => 'javascript:void(0);', 'onclick' => "numbers.frontend_form.trigger_submit('#form_numbers_frontend_html_widgets_comments_model_form_comment_form', false, true); numbers.modal.show('widgets_comments_{$this->widget_link}_comment');"));
        $result .= '</div>';
        $result .= '<hr class="simple" />';
        // form
        $pk = http_build_query2($this->options['pk']);
        $js = <<<TTT
\t\t\tvar mask_id = 'widgets_comments_{$this->widget_link}_mask';
\t\t\t\$.ajax({
\t\t\t\turl: numbers.controller_full,
\t\t\t\tmethod: 'post',
\t\t\t\tdata: '__ajax=1&__ajax_form_id=widgets_comments_{$this->widget_link}_list&{$pk}',
\t\t\t\tdataType: 'json',
\t\t\t\tsuccess: function (data) {
\t\t\t\t\tif (data.success) {
\t\t\t\t\t\t\$('#widgets_comments_{$this->widget_link}_wrapper').html(data.html);
\t\t\t\t\t\teval(data.js);
\t\t\t\t\t\t// remove mask after 100 miliseconds to let js to take affect
\t\t\t\t\t\tsetTimeout(function() {
\t\t\t\t\t\t\t\$('#' + mask_id).unmask();
\t\t\t\t\t\t\t// we need to trigger resize to redraw a screen
\t\t\t\t\t\t\t\$(window).trigger('resize');
\t\t\t\t\t\t}, 100);
\t\t\t\t\t}
\t\t\t\t}
\t\t\t});
TTT;
        $form = new numbers_frontend_html_widgets_comments_model_form_comment(['input' => $this->options['input'], 'no_actions' => true, 'bypass_hidden_values' => $this->options['pk'], 'other' => ['model' => $this->options['model'], 'pk' => $this->options['pk'], 'map' => $this->options['map']], 'on_success_js' => "numbers.modal.hide('widgets_comments_{$this->widget_link}_comment');" . $js]);
        $body = $form->render();
        $footer = html::button2(['name' => 'submit_comment', 'value' => i18n(null, 'Submit'), 'type' => 'primary', 'onclick' => "numbers.frontend_form.trigger_submit('#form_numbers_frontend_html_widgets_comments_model_form_comment_form', true); return false;"]);
        $result .= html::modal(['id' => "widgets_comments_{$this->widget_link}_comment", 'class' => 'large', 'title' => i18n(null, 'Add Comment'), 'body' => $body, 'footer' => $footer]);
        // list of comments in descending order
        $where = [];
        foreach ($this->options['map'] as $k => $v) {
            $where[$v] = $this->options['pk'][$k];
        }
        $datasource = new numbers_frontend_html_widgets_comments_model_datasource_comments();
        $data = $datasource->get(['model' => $this->options['model'], 'where' => $where]);
        if (!empty($data)) {
            $table = ['header' => ['id' => ['value' => '#', 'width' => '1%'], 'inserted' => ['value' => i18n(null, 'Date & Time'), 'width' => '1%', 'nowrap' => true], 'important' => ['value' => i18n(null, 'Important'), 'width' => '1%'], 'em_entity_name' => ['value' => i18n(null, 'Entity'), 'width' => '10%'], 'comment_value' => i18n(null, 'Comment')], 'options' => []];
            $row_number = 1;
            foreach ($data as $k => $v) {
                // we need to hide old comments
                $row_style = '';
                if ($row_number > 10) {
                    $row_style = 'display: none;';
                }
                $table['options'][$v['id']] = ['id' => ['value' => $row_number . '.', 'row_style' => $row_style, 'row_class' => "widgets_comments_{$this->widget_link}_list_hiden " . ($v['important'] ? 'success' : null)], 'inserted' => format::datetime($v['inserted']), 'important' => ['value' => $v['important'] ? i18n(null, 'Yes') : ''], 'em_entity_name' => ['value' => $v['em_entity_name'], 'width' => '10%', 'nowrap' => true], 'comment_value' => nl2br($v['comment_value'])];
                $row_number++;
            }
            $result_list = html::table($table);
            // link to show all rows
            $total_comments = count($data);
            if ($total_comments > 10) {
                $result_list .= '<div style="text-align: right;">' . html::a(['href' => 'javascript:void(0);', 'value' => i18n(null, '[count] comment(s) are hidden. Show all comments.', ['replace' => ['[count]' => $total_comments - 10]]), 'onclick' => "\$('.widgets_comments_{$this->widget_link}_list_hiden').show(); \$(this).hide();"]) . '</div>';
            }
        } else {
            $result_list = html::message(['type' => 'warning', 'options' => [i18n(null, object_content_messages::no_rows_found)]]);
        }
        // if we are making an ajax call
        if (!empty($this->options['input']['__ajax']) && ($this->options['input']['__ajax_form_id'] ?? '') == "widgets_comments_{$this->widget_link}_list") {
            layout::render_as(['success' => true, 'error' => [], 'html' => $result_list, 'js' => ''], 'application/json');
        }
        // load mask
        numbers_frontend_media_libraries_loadmask_base::add();
        // put list into result
        $result .= "<div id=\"widgets_comments_{$this->widget_link}_mask\"><div id=\"widgets_comments_{$this->widget_link}_wrapper\">" . $result_list . '</div></div>';
        // wrap everything into segment
        if (isset($this->options['segment'])) {
            $temp = is_array($this->options['segment']) ? $this->options['segment'] : [];
            $temp['value'] = $result;
            $result = html::segment($temp);
        }
        // anchor
        $result = html::a(['name' => "widgets_comments_{$this->widget_link}_anchor"]) . $result;
        return $result;
    }
Beispiel #7
0
 public function process($data, $options = [])
 {
     $temp = [];
     // we need to precess items that are controller and suboptions at the same time
     $subgroups = [];
     foreach ($data as $k => $v) {
         // determine acl
         if (!empty($v['sm_menuitm_acl_controller_id']) && !helper_acl::can_see_this_controller($v['sm_menuitm_acl_controller_id'], $v['sm_menuitm_acl_action_id'])) {
             unset($data[$k]);
             continue;
         }
         // go though each group
         for ($i = 1; $i <= 4; $i++) {
             if (!empty($v["g{$i}_code"])) {
                 $subgroups[$v["g{$i}_code"]] = true;
             }
         }
     }
     $subgroup_items = [];
     foreach ($data as $k => $v) {
         if (isset($subgroups[$v['sm_menuitm_code']])) {
             $subgroup_items[$v['sm_menuitm_code']] = $v;
             unset($data[$k]);
         }
     }
     // loop though data
     foreach ($data as $k => $v) {
         // loop though groups and add them to menu
         $key = [];
         for ($i = 1; $i <= 4; $i++) {
             if (!empty($v['g' . $i . '_code'])) {
                 $key[] = $v['g' . $i . '_code'];
                 // we need to set all groups
                 $temp2 = array_key_get($temp, $key);
                 if (is_null($temp2)) {
                     // if we have a controller that acts as submenu
                     if (!empty($subgroup_items[$v['g' . $i . '_code']])) {
                         $v9 = $subgroup_items[$v['g' . $i . '_code']];
                         array_key_set($temp, $key, ['code' => $v9['sm_menuitm_code'], 'name' => $v9['sm_menuitm_name'], 'name_extension' => null, 'icon' => $v9['sm_menuitm_icon'], 'url' => $v9['sm_menuitm_url'], 'order' => $v9['sm_menuitm_order'], 'options' => []]);
                     } else {
                         // if we do not have url we assume visitor wants to see extended menu
                         if (empty($v['g' . $i . '_url'])) {
                             $params = [];
                             for ($j = 1; $j <= $i; $j++) {
                                 $params['group' . $j . '_code'] = $v['g' . $j . '_code'];
                             }
                             $v['g' . $i . '_url'] = '/numbers/backend/system/menu/controller/menu?' . http_build_query2($params);
                         }
                         array_key_set($temp, $key, ['code' => $v['g' . $i . '_code'], 'name' => $v['g' . $i . '_name'], 'icon' => $v['g' . $i . '_icon'], 'order' => $v['g' . $i . '_order'], 'url' => $v['g' . $i . '_url'], 'options' => []]);
                     }
                 }
                 $key[] = 'options';
             }
         }
         // some replaces
         $name_extension = null;
         if ($v['sm_menuitm_code'] == 'entites.authorization.__entity_name') {
             $name_extension = '<b>' . session::get(['numbers', 'entity', 'em_entity_name']) . '</b>';
         }
         // finally we need to add menu item to the array
         $key[] = $v['sm_menuitm_code'];
         array_key_set($temp, $key, ['code' => $v['sm_menuitm_code'], 'name' => $v['sm_menuitm_name'], 'name_extension' => $name_extension, 'icon' => $v['sm_menuitm_icon'], 'url' => $v['sm_menuitm_url'], 'order' => $v['sm_menuitm_order'], 'options' => []]);
         // options generator
         if (!empty($v['sm_menuitm_options_generator'])) {
             $temp3 = explode('::', $v['sm_menuitm_options_generator']);
             $temp_data = factory::model($temp3[0])->{$temp3[1]}();
             $temp_key = $key;
             $temp_key[] = 'options';
             foreach ($temp_data as $k2 => $v2) {
                 $temp_key2 = $temp_key;
                 $temp_key2[] = $k2;
                 array_key_set($temp, $temp_key2, $v2);
             }
         }
     }
     // sorting
     foreach ($temp as $k => $v) {
         if (!empty($v['options'])) {
             foreach ($v['options'] as $k2 => $v2) {
                 if (!empty($v2['options'])) {
                     foreach ($v2['options'] as $k3 => $v3) {
                         if (!empty($v3['options'])) {
                             foreach ($v3['options'] as $k4 => $v4) {
                                 if (!empty($v4['options'])) {
                                     array_key_sort($temp[$k]['options'][$k2]['options'][$k3]['options'][$k4]['options'], ['order' => SORT_ASC], ['order' => SORT_NUMERIC]);
                                 }
                             }
                             array_key_sort($temp[$k]['options'][$k2]['options'][$k3]['options'], ['order' => SORT_ASC], ['order' => SORT_NUMERIC]);
                         }
                     }
                     array_key_sort($temp[$k]['options'][$k2]['options'], ['order' => SORT_ASC], ['order' => SORT_NUMERIC]);
                 }
             }
             array_key_sort($temp[$k]['options'], ['order' => SORT_ASC], ['order' => SORT_NUMERIC]);
         }
     }
     // sort root
     array_key_sort($temp, ['order' => SORT_ASC], ['order' => SORT_NUMERIC]);
     return $temp;
 }
Beispiel #8
0
 /**
  * Data default renderer
  *
  * @return string
  */
 private final function render_data_default()
 {
     $result = '';
     // if we have no rows we display a messsage
     if ($this->num_rows == 0) {
         return html::message(['type' => 'warning', 'options' => [i18n(null, object_content_messages::no_rows_found)]]);
     }
     $counter = 1;
     $table = ['header' => [], 'options' => []];
     // action flags
     $actions = [];
     if (object_controller::can('record_view')) {
         $actions['view'] = true;
     }
     // generate columns
     foreach ($this->columns as $k => $v) {
         // if we can not view we skip action column
         if (empty($actions) && $k == 'action') {
             continue;
         }
         $table['header'][$k] = ['value' => i18n(null, $v['name']), 'nowrap' => true, 'width' => $v['width'] ?? null];
     }
     // generate rows
     foreach ($this->rows as $k => $v) {
         // process all columns first
         $row = [];
         foreach ($this->columns as $k2 => $v2) {
             // if we can not view we skip action column
             if (empty($actions) && $k2 == 'action') {
                 continue;
             }
             $value = [];
             // create cell properties
             foreach (['width', 'align'] as $v3) {
                 if (isset($v2[$v3])) {
                     $value[$v3] = $v2[$v3];
                 }
             }
             // process rows
             if ($k2 == 'action') {
                 $value['value'] = [];
                 if (!empty($actions['view'])) {
                     $mvc = application::get('mvc');
                     $pk = extract_keys($this->model_object->pk, $v);
                     $url = $mvc['controller'] . '/_edit?' . http_build_query2($pk);
                     $value['value'][] = html::a(['value' => i18n(null, 'View'), 'href' => $url]);
                 }
                 $value['value'] = implode(' ', $value['value']);
             } else {
                 if ($k2 == 'row_number') {
                     $value['value'] = format::id($counter) . '.';
                 } else {
                     if ($k2 == 'offset_number') {
                         $value['value'] = format::id($this->offset + $counter) . '.';
                     } else {
                         if (!empty($v2['options_model'])) {
                             if (strpos($v2['options_model'], '::') === false) {
                                 $v2['options_model'] .= '::options';
                             }
                             $params = $v2['options_params'] ?? [];
                             if (!empty($v2['options_depends'])) {
                                 foreach ($v2['options_depends'] as $k0 => $v0) {
                                     $params[$k0] = $v[$v0];
                                 }
                             }
                             $crypt_object = new crypt();
                             $hash = $crypt_object->hash($v2['options_model'] . serialize($params));
                             if (!isset($this->cached_options[$hash])) {
                                 $method = factory::method($v2['options_model'], null, true);
                                 $this->cached_options[$hash] = call_user_func_array($method, [['where' => $params]]);
                             }
                             if (isset($this->cached_options[$hash][$v[$k2]])) {
                                 $value['value'] = $this->cached_options[$hash][$v[$k2]]['name'];
                             } else {
                                 $value['value'] = null;
                             }
                         } else {
                             if (!empty($v2['options']) && !is_array($v[$k2])) {
                                 if (isset($v2['options'][$v[$k2]])) {
                                     $value['value'] = $v2['options'][$v[$k2]]['name'];
                                 } else {
                                     $value['value'] = null;
                                 }
                             } else {
                                 if (isset($v[$k2])) {
                                     $value['value'] = $v[$k2];
                                 } else {
                                     $value['value'] = null;
                                 }
                             }
                         }
                     }
                 }
             }
             // put value into row
             if (!empty($v2['format'])) {
                 $format_options = $v2['format_options'] ?? [];
                 if (!empty($v2['format_depends'])) {
                     $format_depends = $v2['format_depends'];
                     $this->process_params_and_depends($format_depends, $v);
                     $format_options = array_merge_hard($format_options, $format_depends);
                 }
                 $method = factory::method($v2['format'], 'format');
                 $value['value'] = call_user_func_array([$method[0], $method[1]], [$value['value'], $format_options]);
             }
             $row[$k2] = $value;
         }
         // put processed columns though user defined function
         if (method_exists($this, 'render_data_rows')) {
             $table['options'][$counter] = $this->render_data_rows($row, $v);
         } else {
             $table['options'][$counter] = $row;
         }
         $counter++;
     }
     return html::table($table);
 }