/** * Renew session */ public function action_renew() { $input = request::input(null, true, true); $result = ['success' => false, 'error' => []]; if (!empty($input['token'])) { $crypt = new crypt(); $token_data = $crypt->token_validate($input['token'], ['skip_time_validation' => true]); if (!($token_data === false || $token_data['id'] !== 'general')) { $result['success'] = true; } } layout::render_as($result, 'application/json'); }
/** * This would process error message sent from frontend */ public function action_index() { $input = request::input(); if (!empty($input['token'])) { $crypt = new crypt(); $token_data = $crypt->token_validate($input['token'], ['skip_time_validation' => true]); if (!($token_data === false || $token_data['id'] !== 'general')) { $input['data'] = json_decode($input['data'], true); error_base::error_handler('javascript', $input['data']['message'], $input['data']['file'], $input['data']['line']); } } // rendering layout::render_as(file_get_contents(__DIR__ . '/error.png'), 'image/png'); }
public static function process($options = []) { // start buffering helper_ob::start(true); $controller_class = self::$settings['mvc']['controller_class']; // if we are handling error message and controller class has not been loaded if ($controller_class == 'controller_error' && error_base::$flag_error_already && !class_exists('controller_error')) { require './controller/error.php'; } $controller = new $controller_class(); // processing options if (!empty($options)) { foreach ($options as $k => $v) { $controller->{$k} = $v; } } // put action into controller $controller->action = ['code' => self::$settings['mvc']['controller_action_code'], 'full' => self::$settings['mvc']['controller_action']]; // check ACL if ($controller_class != 'controller_error') { helper_acl::merge_data_with_db($controller, self::$settings['mvc']['controller_class']); if (helper_acl::can_be_executed($controller, true) == false) { throw new Exception('Permission denied!', -1); } } else { // important to unset controller data application::set('controller', null); } // auto populating input property in controller if (!empty(self::$settings['application']['controller']['input'])) { $controller->input = request::input(null, true, true); } // init method if (method_exists($controller, 'init')) { call_user_func(array($controller, 'init')); } // check if action exists if (!method_exists($controller, $controller->action['full'])) { throw new Exception('Action does not exists!'); } // calling action echo call_user_func(array($controller, $controller->action['full'])); // auto rendering view only if view exists, processing extension order as specified in .ini file $temp_reflection_obj = new ReflectionClass($controller); $controller_dir = pathinfo($temp_reflection_obj->getFileName(), PATHINFO_DIRNAME) . '/'; $controller_file = end(self::$settings['mvc']['controllers']); $view = self::$settings['mvc']['controller_view']; $flag_view_found = false; if (!empty($view)) { $extensions = explode(',', isset(self::$settings['application']['view']['extension']) ? self::$settings['application']['view']['extension'] : 'html'); foreach ($extensions as $extension) { $file = $controller_dir . $controller_file . '.' . $view . '.' . $extension; if (file_exists($file)) { $controller = new view($controller, $file, $extension); $flag_view_found = true; break; } } // if views are mandatory if (!empty(self::$settings['application']['view']['mandatory']) && !$flag_view_found) { throw new Exception('View ' . $view . ' does not exists!'); } } // autoloading media files layout::include_media($controller_dir, $controller_file, $view, $controller_class); // appending view after controllers output $controller->view = ($controller->view ?? '') . helper_ob::clean(); // if we have to render debug toolbar if (debug::$toolbar) { helper_ob::start(); } // call pre rendering method in bootstrap bootstrap::pre_render(); // rendering layout $__skip_layout = application::get('flag.global.__skip_layout'); if (!empty(self::$settings['mvc']['controller_layout']) && empty($__skip_layout)) { helper_ob::start(); if (file_exists(self::$settings['mvc']['controller_layout_file'])) { $controller = new layout($controller, self::$settings['mvc']['controller_layout_file'], self::$settings['mvc']['controller_layout_extension']); } // session expiry dialog before replaces session::expiry_dialog(); // buffer output and handling javascript files, chicken and egg problem $from = ['<!-- [numbers: messages] -->', '<!-- [numbers: title] -->', '<!-- [numbers: document title] -->', '<!-- [numbers: actions] -->', '<!-- [numbers: breadcrumbs] -->', '<!-- [numbers: javascript links] -->', '<!-- [numbers: javascript data] -->', '<!-- [numbers: css links] -->', '<!-- [numbers: layout onload] -->', '<!-- [numbers: layout onhtml] -->']; $to = [layout::render_messages(), layout::render_title(), layout::render_document_title(), layout::render_actions(), layout::render_breadcrumbs(), layout::render_js(), layout::render_js_data(), layout::render_css(), layout::render_onload(), layout::$onhtml]; echo str_replace($from, $to, helper_ob::clean()); } else { echo $controller->view; } // ajax calls that has not been processed by application if (application::get('flag.global.__ajax')) { layout::render_as(['success' => false, 'error' => [i18n(null, 'Could not process ajax call!')]], 'application/json'); } }
public function action_js() { layout::render_as('numbers.i18n.__custom.data = ' . json_encode(numbers_backend_i18n_basic_base::$data) . ';', 'application/javascript'); }
/** * Render * * @param string $type * @return string */ public function render($type) { $result = ''; $session = new session(); // main switch switch ($type) { case 'pdf': // document properties $this->header['pdf']['orientation'] = isset($this->header['pdf']['orientation']) ? $this->header['pdf']['orientation'] : 'P'; $this->header['pdf']['unit'] = 'mm'; $this->header['pdf']['format'] = isset($this->header['pdf']['format']) ? $this->header['pdf']['format'] : 'LETTER'; $this->header['pdf']['encoding'] = isset($this->header['pdf']['encoding']) ? $this->header['pdf']['encoding'] : 'UTF-8'; $this->header['pdf']['font'] = isset($this->header['pdf']['font']) ? $this->header['pdf']['font'] : array('family' => 'helvetica', 'style' => '', 'size' => 8); //include 'tcpdf/tcpdf.php'; // create new PDF document $pdf = new TCPDF($this->header['pdf']['orientation'], $this->header['pdf']['unit'], $this->header['pdf']['format'], true, $this->header['pdf']['encoding'], false); // set margins $pdf->SetMargins(0, 0, 0); $pdf->setPrintHeader(false); // disable auto break $pdf->SetAutoPageBreak(false, 0); // set default font subsetting mode $pdf->setFontSubsetting(true); // set color for background $pdf->SetFillColor(255, 255, 255); // set font $pdf->SetFont($this->header['pdf']['font']['family'], $this->header['pdf']['font']['style'], $this->header['pdf']['font']['size']); // stats $page_counter = 1; $page_y = 0; $flag_new_page = true; $flag_filter = true; $flag_first_row = true; $columns = array(); $all_columns = array(); // gethering all columns foreach ($this->data as $k => $v) { if ($v['t'] == 'columns') { $all_columns[] = $v; } } // looping through the data foreach ($this->data as $k => $v) { if ($v['t'] == 'columns') { continue; } if ($flag_new_page) { // add new page $pdf->AddPage($this->header['pdf']['orientation'], '', true); // drawing header $pdf->MultiCell(40, 5, format::datetime(format::now()), 0, 'L', 1, 0, 5, 5, true, 0, false, true, 10, 'T'); // company + book name $pw = $pdf->getPageWidth(); $pdf->SetFont($this->header['pdf']['font']['family'], 'B', $this->header['pdf']['font']['size']); // todo: fix here $pdf->MultiCell($pw - 90, 5, $session->company_name . ': ' . $session->book_name, 0, 'C', 1, 0, 40, 5, true, 0, false, true, 10, 'T'); // page counter $pdf->SetFont($this->header['pdf']['font']['family'], '', $this->header['pdf']['font']['size']); $pdf->MultiCell(40, 5, 'Page ' . $page_counter, 0, 'R', 1, 0, $pw - 45, 5, true, 0, false, true, 10, 'T'); // report name $pdf->SetFont($this->header['pdf']['font']['family'], 'B', $this->header['pdf']['font']['size']); $report_name = $this->header['name'] . ' (' . implode('-', application::get(array('mvc', 'controllers'))) . ')'; $pdf->MultiCell($pw - 10, 5, $report_name, 0, 'L', 1, 0, 5, 10, true, 0, false, true, 10, 'T'); if (isset($this->header['description'])) { $pdf->SetFont($this->header['pdf']['font']['family'], 'B', $this->header['pdf']['font']['size']); $pdf->MultiCell(205, 5, $this->header['description'], 0, 'L', 1, 0, 5, 15, true, 0, false, true, 10, 'T'); $page_y = 25; } else { $page_y = 20; } // if we need to add a filter if ($flag_filter) { if (isset($this->header['filter'])) { foreach ($this->header['filter'] as $k2 => $v2) { $pdf->SetFont($this->header['pdf']['font']['family'], 'B', $this->header['pdf']['font']['size']); $pdf->MultiCell(50, 5, $k2 . ':', 0, 'L', 1, 0, 5, $page_y, true, 0, false, true, 10, 'T'); $pdf->SetFont($this->header['pdf']['font']['family'], '', $this->header['pdf']['font']['size']); $number_of_cells = $pdf->MultiCell($pdf->getPageWidth() - 60, 5, $v2, 0, 'L', 1, 0, 55, $page_y, true, 0, false, true, 10, 'T'); if ($number_of_cells > 1) { $page_y += 5 * ($number_of_cells - 1); } $page_y += 5; } } $flag_filter = false; // adding one line space $page_y += 5; } // page counter $page_counter++; $flag_new_page = false; } // rendering rows if ($flag_first_row) { if (empty($columns)) { $columns = current($all_columns); // repopulate width $count_empty = 0; $taken = 0; foreach ($columns['d'] as $k2 => $v2) { if (empty($v2['w'])) { $count_empty++; } else { $taken += $v2['w']; } } if (!empty($count_empty)) { $new_width = floor(($pdf->getPageWidth() - 10 - $taken) / $count_empty); foreach ($v['d'] as $k2 => $v2) { $columns['d'][$k2]['w'] = $new_width; } } } $flag_first_row = false; // columns foreach ($all_columns as $k20 => $v20) { $x = 5; foreach ($columns['d'] as $k10 => $v10) { foreach (array('v', 'c', 'a', 'b', 's', 't', 'u') as $v30) { if (isset($v20['d'][$k10][$v30])) { $v10[$v30] = $v20['d'][$k10][$v30]; } } $new_width = @$v10['w']; if (!empty($v10['c'])) { // we need to get width of next elements for ($i = $k10 + 1; $i < $k10 + $v10['c']; $i++) { $new_width += $columns['d'][$k10]['w']; } } $align = str_replace(array('left', 'right', 'center'), array('L', 'R', 'C'), @$v10['a']); if (empty($align)) { $align = 'L'; } if (@$v10['b']) { $pdf->SetFont($this->header['pdf']['font']['family'], 'B', $this->header['pdf']['font']['size']); } else { $pdf->SetFont($this->header['pdf']['font']['family'], '', $this->header['pdf']['font']['size']); } $pdf->MultiCell($new_width, 5, @$v10['v'], $this->flag_pdf_show_borders, $align, 1, 0, $x, $page_y, true, 0, false, true, 10, 'T'); // underline if (@$v10['u']) { $pdf->SetLineStyle(array('width' => 0, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))); $pdf->Line($x, $page_y + 5, $x + @$v10['w'], $page_y + 5); } $x += @$v10['w']; } $page_y += 5; } } $pdf->SetFont($this->header['pdf']['font']['family'], '', $this->header['pdf']['font']['size']); $x = 5; foreach ($columns['d'] as $k10 => $v10) { // we do do render cells if no data if (isset($v['d'][$k10]['v'])) { $align = str_replace(array('left', 'right', 'center'), array('L', 'R', 'C'), @$v['d'][$k10]['a']); if (empty($align)) { $align = 'L'; } if (@$v['d'][$k10]['b']) { $pdf->SetFont($this->header['pdf']['font']['family'], 'B', $this->header['pdf']['font']['size']); } else { $pdf->SetFont($this->header['pdf']['font']['family'], '', $this->header['pdf']['font']['size']); } // if we override width $width = $v10['w']; if (isset($v['d'][$k10]['w'])) { $width = $v['d'][$k10]['w']; } else { if (isset($v['d'][$k10]['c'])) { // colspan // we need to get width of next elements for ($i = $k10 + 1; $i < $k10 + $v['d'][$k10]['c']; $i++) { $width += @$columns['d'][$i]['w']; } } } $value = @$v['d'][$k10]['v']; $value = str_replace(' ', ' ', $value); // rendering cell $pdf->MultiCell($width, 5, $value, $this->flag_pdf_show_borders, $align, 1, 0, $x, $page_y, true, 0, false, true, 10, 'T'); // underline if (@$v['d'][$k10]['u']) { $pdf->SetLineStyle(array('width' => 0, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))); $pdf->Line($x, $page_y + 5, $x + $v10['w'], $page_y + 5); } // subtotal if (@$v['d'][$k10]['s']) { $pdf->SetLineStyle(array('width' => 0, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))); $pdf->Line($x + 1, $page_y, $x + $v10['w'] - 1, $page_y); } // total if (@$v['d'][$k10]['t']) { $pdf->SetLineStyle(array('width' => 0, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))); $pdf->Line($x + 1, $page_y, $x + $v10['w'] - 1, $page_y); $pdf->Line($x + 1, $page_y - 0.75, $x + $v10['w'] - 1, $page_y - 0.75); } } $x += @$v10['w']; } // incrementing $page_y += 5; if ($page_y > $pdf->getPageHeight() - 10) { $flag_new_page = true; $flag_first_row = true; } } $pdf->Output($this->header['name'] . '.pdf', 'I'); exit; break; case 'csv': case 'txt': case 'xlsx': $sheet = strip_tags($this->header['name']); $sheet = str_replace(['/', '\\'], '', $sheet); // generating header $header = []; $header[$sheet][] = [format::datetime(format::now()), '', $session->company_name . ': ' . $session->book_name, '', 'Page 1']; $controllers = application::get(['mvc', 'controllers']); $header[$sheet][] = [strip_tags($this->header['name']) . ' (' . implode('-', $controllers) . ')']; if (isset($this->header['description'])) { $header[$sheet][] = [$this->header['description']]; } $header[$sheet][] = [' ']; $temp = $header; // displaying filter if (isset($this->header['filter'])) { $temp2 = []; foreach ($this->header['filter'] as $k => $v) { $temp[$sheet][] = [strip_tags($k), strip_tags($v)]; } $temp[$sheet][] = [' ']; } // converting data foreach ($this->data as $k => $v) { $temp2 = []; foreach ($v['d'] as $k2 => $v2) { if (is_array($v2)) { $value = $v2['v'] ?? null; } else { $value = $v2; } // replaces $value = str_replace(' ', ' ', $value); $temp2[] = strip_tags($value); } $temp[$sheet][] = $temp2; } // get output buffering helper_ob::clean_all(); // content switch ($type) { case 'xlsx': echo io::array_to_excel($temp, io::$formats[$type]['excel_code'], null); break; default: // csv or text header('Content-Type: ' . numbers_frontend_exports_csv_base::$formats[$type]['content_type']); header('Content-Disposition: attachment; filename="' . $sheet . '.' . $type . '"'); header('Cache-Control: max-age=0'); echo numbers_frontend_exports_csv_base::array_to_csv($temp, numbers_frontend_exports_csv_base::$formats[$type]['delimiter'], numbers_frontend_exports_csv_base::$formats[$type]['enclosure']); } exit; break; case 'html': case 'html2': default: // rendering data $table = ['options' => []]; $counter = 1; foreach ($this->data as $k => $v) { $flag_colspan = 0; $row = []; if (!empty($v['d'])) { foreach ($v['d'] as $k2 => $v2) { if ($flag_colspan > 0) { $flag_colspan--; continue; } $colspan = ''; if ($v2['c'] ?? null) { $colspan = $v2['c']; $flag_colspan = $v2['c'] - 1; } $align = 'left'; $title = ''; $style = ''; if (is_array($v2)) { $value = $v2['v'] ?? null; if (!empty($v2['h'])) { $v2['h']['value'] = $value; $value = html::a($v2['h']); } if (!empty($v2['a'])) { $align = $v2['a']; } if (!empty($v2['l'])) { $title = $v2['l']; } // bold lines if ($v2['b'] ?? null) { $value = '<b>' . $value . '</b>'; } // todo: convert styles to classes if ($v2['s'] ?? null) { $style .= 'border-top: 1px solid #000;'; } if ($v2['t'] ?? null) { $style .= 'border-top: 3px double #000;'; } if ($v2['u'] ?? null) { $style .= 'border-bottom: 1px solid #000;'; } } else { $value = $v2; } $row[$k2] = ['value' => $value, 'align' => $align, 'colspan' => $colspan, 'style' => $style, 'title' => $title, 'nowrap' => true]; } } else { $row[0] = ['value' => ' ']; } $table['options'][$counter] = $row; $counter++; } $result = html::table($table); // printable export if ($type == 'html2') { $header = ['options' => []]; $header['options'][] = [0 => format::datetime(format::now()), 1 => '', 2 => $session->company_name . ': ' . $session->book_name, 3 => '', 4 => 'Page 1']; $controllers = application::get(['mvc', 'controllers']); $header['options'][] = [['value' => strip_tags($this->header['name']) . ' (' . implode('-', $controllers) . ')', 'colspan' => 5]]; if (isset($this->header['description'])) { $header['options'][] = [$this->header['description']]; } $header['options'][] = [' ']; // displaying filter if (isset($this->header['filter'])) { $temp2 = []; foreach ($this->header['filter'] as $k => $v) { $header['options'][] = [strip_tags($k) . ':', strip_tags($v)]; } $header['options'][] = [' ']; } $header = html::table($header); layout::render_as($header . $result, 'text/html'); } } return $result; }
/** * 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; }
/** * 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; }
/** * Render list * * @return string */ public final function render() { $result = ''; // css & js layout::add_css('/numbers/media_submodules/numbers_frontend_html_list_media_css_base.css', 9000); layout::add_js('/numbers/media_submodules/numbers_frontend_html_list_media_js_base.js', 9000); // load mask numbers_frontend_media_libraries_loadmask_base::add(); // hidden fields $result .= html::hidden(['name' => 'offset', 'id' => 'offset', 'value' => $this->offset]); $result .= html::hidden(['name' => 'limit', 'id' => 'limit', 'value' => $this->limit]); // get total number of rows from count datasource if (!empty($this->datasources['count'])) { $temp = factory::model($this->datasources['count']['model'])->get($this->datasources['count']['options']); $this->total = $temp[0]['count'] ?? 0; } // get rows if (!empty($this->datasources['data'])) { $this->rows = factory::model($this->datasources['data']['model'])->get($this->datasources['data']['options']); $this->num_rows = count($this->rows); } // new record if (object_controller::can('record_new')) { $mvc = application::get('mvc'); $url = $mvc['controller'] . '/_edit'; $this->actions['list_new'] = ['value' => 'New', 'sort' => -32000, 'icon' => 'file-o', 'href' => $url]; } // filter if (!empty($this->filter)) { $this->actions['list_filter'] = ['value' => 'Filter', 'sort' => 1, 'icon' => 'filter', 'onclick' => "numbers.modal.show('list_{$this->list_link}_filter');"]; $result .= numbers_frontend_html_list_filter::render($this); } // order by $this->actions['list_sort'] = ['value' => 'Sort', 'sort' => 2, 'icon' => 'sort-alpha-asc', 'onclick' => "numbers.modal.show('list_{$this->list_link}_sort');"]; $result .= numbers_frontend_html_list_sort::render($this); // export, before pagination if (object_controller::can('list_export')) { // add export link to the panel $result .= numbers_frontend_html_list_export::render($this); $this->actions['list_export'] = ['value' => 'Export/Print', 'sort' => 3, 'icon' => 'print', 'onclick' => "numbers.modal.show('list_{$this->list_link}_export');"]; // if we are exporting if (!empty($this->options['input']['submit_export']) && !empty($this->options['input']['export']['format'])) { $result .= numbers_frontend_html_list_export::export($this, $this->options['input']['export']['format']); goto finish; } } // refresh $this->actions['form_refresh'] = ['value' => 'Refresh', 'sort' => 32000, 'icon' => 'refresh', 'href' => 'javascript:location.reload();', 'internal_action' => true]; // pagination top if (!empty($this->pagination['top'])) { $result .= factory::model($this->pagination['top'])->render($this, 'top'); } // data $result .= '<hr class="simple"/>'; if (method_exists($this, 'render_data')) { $result .= $this->render_data(); } else { $result .= $this->render_data_default(); } $result .= '<hr class="simple"/>'; // pagination bottom if (!empty($this->pagination['bottom'])) { $result .= factory::model($this->pagination['bottom'])->render($this, 'bottom'); } finish: $value = ''; if (!empty($this->actions)) { $value .= '<div style="text-align: right;">' . $this->render_actions() . '</div>'; $value .= '<hr class="simple" />'; } // we add hidden submit element $result .= html::submit(['name' => 'submit_hidden', 'value' => 1, 'style' => 'display: none;']); // build a form $value .= html::form(['name' => "list_{$this->list_link}_form", 'id' => "list_{$this->list_link}_form", 'value' => $result, 'onsubmit' => 'return numbers.frontend_list.on_form_submit(this);']); // if we came from ajax we return as json object if (!empty($this->options['input']['__ajax'])) { $result = ['success' => true, 'html' => $value, 'js' => layout::$onload]; layout::render_as($result, 'application/json'); } $value = "<div id=\"list_{$this->list_link}_form_mask\"><div id=\"list_{$this->list_link}_form_wrapper\">" . $value . '</div></div>'; $temp = ['type' => 'primary', 'value' => $value]; return html::segment($temp); }