/**
  * Process options
  *
  * @param string $model_and_method - model::method
  * @param object $existing_object
  * @param array $where
  * @param array $existing_values
  * @param array $skip_values
  * @param array $options
  * @return array
  */
 public static function process_options($model_and_method, $existing_object = null, $where = [], $existing_values = [], $skip_values = [], $options = [])
 {
     // put changes into options
     $options['where'] = array_merge_hard($options['where'] ?? [], $where);
     $options['existing_values'] = $existing_values;
     $options['skip_values'] = $skip_values;
     // see if we have cached version
     $hash = sha1($model_and_method . serialize($options));
     if (isset(self::$cached_options[$hash])) {
         return self::$cached_options[$hash];
     } else {
         $temp = explode('::', $model_and_method);
         if (count($temp) == 1) {
             $model = $temp[0];
             $method = 'options';
         } else {
             $model = $temp[0];
             $method = $temp[1];
         }
         if ($model == 'this' && !empty($existing_object)) {
             $object = $existing_object;
         } else {
             $object = factory::model($model, true);
         }
         self::$cached_options[$hash] = $object->{$method}($options);
         return self::$cached_options[$hash];
     }
 }
 /**
  * Initializing i18n
  *
  * @param array $options
  */
 public static function init($options = [])
 {
     $i18n = application::get('flag.global.i18n') ?? [];
     $i18n = array_merge_hard($i18n, $options ?? []);
     // determine final language
     $languages = factory::model('numbers_backend_i18n_languages_model_languages')->get();
     $final_language = application::get('flag.global.__language_code') ?? session::get('numbers.entity.format.language_code') ?? $i18n['language_code'] ?? 'sys';
     if (empty($languages[$final_language])) {
         $final_language = 'sys';
         $i18n['rtl'] = 0;
     }
     // put settings into system
     if (!empty($languages[$final_language])) {
         foreach ($languages[$final_language] as $k => $v) {
             $k = str_replace('lc_language_', '', $k);
             if (in_array($k, ['code', 'inactive'])) {
                 continue;
             }
             if (empty($v)) {
                 continue;
             }
             $i18n[$k] = $v;
         }
     }
     $i18n['language_code'] = $final_language;
     self::$options = $i18n;
     session::set('numbers.entity.format.language_code', $final_language);
     application::set('flag.global.i18n', $i18n);
     self::$initialized = true;
     // initialize the module
     return factory::submodule('flag.global.i18n.submodule')->init($i18n);
 }
 /**
  * Process
  */
 public function get()
 {
     $result = [];
     foreach ($this->data as $k => $v) {
         $model = new $v();
         $result = array_merge_hard($result, [$k => $model->get()]);
     }
     return $result;
 }
 /**
  * Render field
  *
  * @param array $field
  * @param string $key
  * @param boolean $flag_second
  * @param array $input
  * @return string
  */
 public static function render_column($field, $key, $flag_second = false, $input = [])
 {
     $field['method'] = $field['method'] ?? 'html::input';
     $options = ['id' => 'filter_' . $key . ($flag_second ? '2' : ''), 'name' => 'filter[' . $key . ($flag_second ? '2' : '') . ']', 'value' => $input['filter'][$key . ($flag_second ? '2' : '')] ?? null];
     $options = array_merge_hard($field, $options);
     if (!empty($field['options_model'])) {
         $params = $field['options_params'] ?? [];
         $options['options'] = factory::model($field['options_model'])->options(['where' => $params, 'i18n' => true]);
     }
     return call_user_func_array(explode('::', $field['method']), [$options]);
 }
 /**
  * Delegate arguments to submodule
  *
  * @param string $flag
  * @param string $submodule
  * @param array $arguments
  * @return mixed
  */
 public static function delegate($flag, $submodule, $arguments)
 {
     $options = application::get($flag . '.' . $submodule . '.options');
     if (!empty($options)) {
         // todo: maybe add to first array instead to first element in arguments
         $arguments[0] = array_merge_hard($options, $arguments[0]);
     }
     // we need to determine whether we need to use additional submodule
     if (application::get($flag . '.' . $submodule . '.submodule') && empty($arguments[0]['flag_call_previous_parent'])) {
         return call_user_func_array([self::submodule($flag . '.' . $submodule . '.submodule'), $submodule], $arguments);
     } else {
         return call_user_func_array([self::submodule($flag . '.submodule'), $submodule], $arguments);
     }
 }
Exemple #6
0
 /**
  * Frontend action
  */
 public function action_frontend()
 {
     $input = request::input();
     // legend
     echo self::render_topic('frontend');
     // processing submit
     $input['name'] = $input['name'] ?? 'numbers.frontend.html.class.base';
     $frontend_frameworks = ['numbers.frontend.html.class.base' => ['name' => 'Plain'], 'numbers.frontend.html.semanticui.base' => ['name' => 'Semantic UI'], 'numbers.frontend.html.bootstrap.base' => ['name' => 'Bootstrap']];
     if (!empty($input['submit_yes'])) {
         $settings = [];
         $libraries = [];
         if ($input['name'] == 'numbers.frontend.html.class.base') {
             $settings = ['submodule' => $input['name'], 'options' => ['grid_columns' => 16], 'calendar' => ['submodule' => 'numbers.frontend.components.calendar.numbers.base']];
             $libraries['semanticui']['autoconnect'] = false;
             $libraries['bootstrap']['autoconnect'] = false;
         } else {
             if ($input['name'] == 'numbers.frontend.html.semanticui.base') {
                 $settings = ['submodule' => $input['name'], 'options' => ['grid_columns' => 16], 'calendar' => ['submodule' => 'numbers.frontend.components.calendar.numbers.base']];
                 $libraries['semanticui']['autoconnect'] = true;
                 $libraries['bootstrap']['autoconnect'] = false;
             } else {
                 if ($input['name'] == 'numbers.frontend.html.bootstrap.base') {
                     $settings = ['submodule' => $input['name'], 'options' => ['grid_columns' => 12], 'calendar' => ['submodule' => 'numbers.frontend.components.calendar.numbers.base']];
                     $libraries['semanticui']['autoconnect'] = false;
                     $libraries['bootstrap']['autoconnect'] = true;
                 }
             }
         }
         // we need to merge old and new values
         session::set('numbers.flag.global.html', array_merge_hard(session::get('numbers.flag.global.html'), $settings));
         session::set('numbers.flag.global.library', array_merge_hard(session::get('numbers.flag.global.library'), $libraries));
         header('Location: /numbers/frontend/system/controller/dev/~frontend?name=' . $input['name']);
         exit;
     }
     // form
     $ms = 'Name: ' . html::select(['name' => 'name', 'options' => $frontend_frameworks, 'no_choose' => true, 'value' => $input['name']]) . ' ';
     $ms .= html::submit(['name' => 'submit_yes']);
     echo html::form(['name' => 'db', 'action' => '#db_test', 'value' => $ms]);
 }
 /**
  * Money format
  *
  * @param mixed $amount
  * @param array $options
  * @return string
  */
 public static function money_format($amount, $options = [])
 {
     $format = array_merge_hard(self::$options['locale_options'], $options['locale_options'] ?? []);
     $options['decimals'] = $options['decimals'] ?? 2;
     // sometimes symbols contain decimal point, we change it to thousands_sep
     if (!empty($options['symbol'])) {
         $options['symbol'] = str_replace($format['mon_decimal_point'], $format['mon_thousands_sep'], $options['symbol']);
     } else {
         $options['symbol'] = '';
     }
     // convert to string
     if (!is_string($amount)) {
         $amount = $amount . '';
     }
     $negative = strpos($amount, '-') !== false;
     $amount = ltrim($amount, '-');
     // if the number portion has been formatted
     if (empty($options['amount_partially_formatted'])) {
         $temp = explode('.', $amount);
         $number = $temp[0];
         $fraction = $temp[1] ?? '';
         // process number
         if (empty($number)) {
             $number = '0';
         }
         if ($format['mon_thousands_sep'] . '' !== '' && !empty($format['mon_grouping'])) {
             $counter = 0;
             $mon_grouping = [];
             $symbols = array_reverse(mb_str_split($number), true);
             $number = '';
             foreach ($symbols as $k => $v) {
                 // grab group size
                 if ($counter == 0) {
                     if (empty($mon_grouping)) {
                         $mon_grouping = $format['mon_grouping'];
                     }
                     if (count($mon_grouping) > 1) {
                         $counter = array_shift($mon_grouping);
                     } else {
                         $counter = $mon_grouping[0];
                     }
                 }
                 // skip number of characters
                 $counter--;
                 $number = $v . $number;
                 if ($counter == 0 && $k > 0) {
                     $number = $format['mon_thousands_sep'] . $number;
                 }
             }
         }
         // left precision
         if (!empty($options['digits'])) {
             if (strlen($number) < $options['digits']) {
                 $number = str_pad($number, $options['digits'], ' ', STR_PAD_LEFT);
             }
         }
         // right precision
         if ($options['decimals'] > 0) {
             $fraction = substr(str_pad($fraction, $options['decimals'], '0', STR_PAD_RIGHT), 0, $options['decimals']);
             $number = $number . $format['mon_decimal_point'] . $fraction;
         }
     } else {
         $number = $amount;
     }
     // translate characters
     $number = self::number_to_from_native_language($number, $options);
     // format based on settings
     $cs_precedes = $negative ? $format['n_cs_precedes'] : $format['p_cs_precedes'];
     $sep_by_space = $negative ? $format['n_sep_by_space'] : $format['p_sep_by_space'];
     $sign_posn = $negative ? $format['n_sign_posn'] : $format['p_sign_posn'];
     // if accounting formatting
     if (!empty($options['accounting'])) {
         // if we have currency symbol we added it based on settings
         if (!empty($options['symbol'])) {
             $number = ($cs_precedes ? $options['symbol'] . ($sep_by_space === 1 ? ' ' : '') : '') . $number . (!$cs_precedes ? ($sep_by_space === 1 ? ' ' : '') . $options['symbol'] : '');
         }
         if ($negative) {
             $number = '(' . $number . ')';
         } else {
             $number = ' ' . $number . ' ';
         }
     } else {
         $positive_sign = $format['positive_sign'];
         $negative_sign = $format['negative_sign'];
         $sign = $negative ? $negative_sign : $positive_sign;
         $other_sign = $negative ? $positive_sign : $negative_sign;
         $sign_padding = '';
         if ($sign_posn) {
             for ($i = 0; $i < strlen($other_sign) - strlen($sign); $i++) {
                 $sign_padding .= ' ';
             }
         }
         $temp_value = '';
         switch ($sign_posn) {
             case 0:
                 // parentheses surround value and currency symbol
                 if (!empty($options['symbol'])) {
                     $number = $cs_precedes ? $options['symbol'] . ($sep_by_space === 1 ? ' ' : '') . $number : $number . ($sep_by_space === 1 ? ' ' : '') . $options['symbol'];
                 }
                 $number = '(' . $number . ')';
                 break;
             case 1:
                 // sign precedes
                 if (!empty($options['symbol'])) {
                     $number = $cs_precedes ? $options['symbol'] . ($sep_by_space === 1 ? ' ' : '') . $number : $number . ($sep_by_space === 1 ? ' ' : '') . $options['symbol'];
                 }
                 $number = $sign_padding . $sign . ($sep_by_space === 2 ? ' ' : '') . $number;
                 break;
             case 2:
                 // sign follows
                 if (!empty($options['symbol'])) {
                     $number = $cs_precedes ? $options['symbol'] . ($sep_by_space === 1 ? ' ' : '') . $number : $number . ($sep_by_space === 1 ? ' ' : '') . $options['symbol'];
                 }
                 $number = $number . ($sep_by_space === 2 ? ' ' : '') . $sign . $sign_padding;
                 break;
             case 3:
                 //sign precedes currency symbol
                 $symbol = '';
                 if (!empty($options['symbol'])) {
                     $symbol = $cs_precedes ? $options['symbol'] . ($sep_by_space === 1 ? ' ' : '') : ($sep_by_space === 2 ? ' ' : '') . $options['symbol'];
                 }
                 $number = $cs_precedes ? $sign_padding . $sign . ($sep_by_space === 2 ? ' ' : '') . $symbol . $number : $number . ($sep_by_space === 1 ? ' ' : '') . $sign . $sign_padding . $symbol;
                 break;
             case 4:
                 // sign succeeds currency symbol
                 $symbol = '';
                 $symbol_sep = '';
                 if (!empty($options['symbol'])) {
                     $symbol = $options['symbol'];
                     $symbol_sep = $sep_by_space === 1 ? ' ' : '';
                 }
                 $number = $cs_precedes ? $symbol . ($sep_by_space === 2 ? ' ' : '') . $sign_padding . $sign . $symbol_sep . $number : $number . $symbol_sep . $symbol . ($sep_by_space === 2 ? ' ' : '') . $sign . $sign_padding;
                 break;
         }
     }
     return $number;
 }
Exemple #8
0
 /**
  * @see html::table()
  */
 public static function table($options = [])
 {
     $rows = isset($options['options']) ? $options['options'] : [];
     if (!empty($options['header']) && is_array($options['header'])) {
         $header = $options['header'];
     } else {
         // we need to grab header from first row
         $header = current($rows);
         $options['skip_header'] = true;
     }
     $result = [];
     $first_column = null;
     // header first
     if (!empty($header) && empty($options['skip_header'])) {
         $temp2 = '<thead>';
         $temp2 .= '<tr>';
         foreach ($header as $k => $v) {
             // determine first column
             if ($first_column === null) {
                 $first_column = $k;
             }
             if (is_array($v)) {
                 $tag = !empty($v['header_use_td_tag']) ? 'td' : 'th';
                 $temp_value = isset($v['value']) ? $v['value'] : '';
                 unset($v['value']);
                 $temp2 .= '<' . $tag . ' ' . self::generate_attributes($v, $tag) . '>' . $temp_value . '</' . $tag . '>';
             } else {
                 $temp2 .= '<th nowrap>' . $v . '</th>';
             }
         }
         $temp2 .= '</tr>';
         $temp2 .= '</thead>';
         $result[] = $temp2;
     }
     // unsetting some values
     unset($options['options'], $options['header'], $options['skip_header']);
     // rows second
     foreach ($rows as $k => $v) {
         // we need to extract row attributes from first column
         $row_options = [];
         foreach ($header as $k2 => $v2) {
             if (isset($v[$k2]) && is_array($v[$k2])) {
                 $row_options = array_merge_hard($row_options, array_key_extract_by_prefix($v[$k2], 'row_'));
             }
         }
         $temp2 = '<tr ' . self::generate_attributes($row_options, 'tr') . '>';
         // important we render based on header array and not on what is in rows
         $flag_colspan = 0;
         foreach ($header as $k2 => $v2) {
             if ($flag_colspan > 0) {
                 $flag_colspan--;
                 continue;
             }
             if (!isset($v[$k2])) {
                 $v[$k2] = null;
             }
             if (is_array($v[$k2])) {
                 $temp3 = isset($v[$k2]['value']) ? $v[$k2]['value'] : '';
                 unset($v[$k2]['value']);
                 if (!empty($v[$k2]['nowrap'])) {
                     $v[$k2]['nowrap'] = 'nowrap';
                 }
                 if (!empty($v[$k2]['colspan'])) {
                     $flag_colspan = $v[$k2]['colspan'];
                     $flag_colspan--;
                 }
                 $temp2 .= '<td ' . self::generate_attributes($v[$k2], 'td') . '>' . $temp3 . '</td>';
             } else {
                 $temp2 .= '<td nowrap>' . $v[$k2] . '</td>';
             }
         }
         // reset colspan
         $flag_colspan = 0;
         $temp2 .= '</tr>';
         $result[] = $temp2;
     }
     // todo: add footer
     // todo: maybe use <thead>, <tfoot>, and a <tbody> tags
     return '<table ' . self::generate_attributes($options, 'table') . '>' . implode('', $result) . '</table>';
 }
Exemple #9
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);
 }
Exemple #10
0
 /**
  * Render elements value
  *
  * @param array $options
  * @param mixed $value
  * @param array $neighbouring_values
  * @return string
  * @throws Exception
  */
 public function render_element_value(&$options, $value = null, &$neighbouring_values = [])
 {
     // field name and values_key
     $options['options']['field_name'] = $options['options']['details_field_name'] ?? $options['options']['name'];
     $options['options']['field_values_key'] = implode('[::]', $options['options']['field_values_key'] ?? [$options['options']['field_name']]);
     // custom renderer
     if (!empty($options['options']['custom_renderer'])) {
         $method = factory::method($options['options']['custom_renderer'], null, true);
         $options_custom_renderer = $options;
         call_user_func_array($method, [&$this, &$options, &$value, &$neighbouring_values]);
     }
     // handling override_field_value method
     if (!empty($this->wrapper_methods['override_field_value']['main'])) {
         call_user_func_array($this->wrapper_methods['override_field_value']['main'], [&$this, &$options, &$value, &$neighbouring_values]);
     }
     $result_options = $options['options'];
     $options['options']['value'] = $value;
     array_key_extract_by_prefix($result_options, 'label_');
     $element_expand = !empty($result_options['expand']);
     $html_suffix = $result_options['html_suffix'] ?? '';
     // unset certain keys
     unset($result_options['order'], $result_options['required'], $result_options['html_suffix']);
     // processing options
     $flag_select_or_autocomplete = !empty($result_options['options_model']) || !empty($result_options['options']);
     if (!empty($result_options['options_model'])) {
         if (empty($result_options['options_params'])) {
             $result_options['options_params'] = [];
         }
         if (empty($result_options['options_options'])) {
             $result_options['options_options'] = [];
         }
         $result_options['options_options']['i18n'] = $result_options['options_options']['i18n'] ?? true;
         $result_options['options_options']['acl'] = $result_options['options_options']['acl'] ?? $this->acl;
         if (empty($result_options['options_depends'])) {
             $result_options['options_depends'] = [];
         }
         // options depends & params
         $this->process_params_and_depends($result_options['options_depends'], $neighbouring_values, $options, true);
         $this->process_params_and_depends($result_options['options_params'], $neighbouring_values, $options, false);
         $result_options['options_params'] = array_merge_hard($result_options['options_params'], $result_options['options_depends']);
         // we do not need options for autocomplete
         if (strpos($result_options['method'], 'autocomplete') === false) {
             $skip_values = [];
             if (!empty($options['options']['details_key'])) {
                 if (!empty($options['options']['details_parent_key'])) {
                     $temp_key = $options['options']['details_parent_key'] . '::' . $options['options']['details_key'];
                     if (!empty($this->misc_settings['details_unique_select'][$temp_key][$options['options']['details_field_name']][$options['options']['__parent_row_number']])) {
                         $skip_values = array_keys($this->misc_settings['details_unique_select'][$temp_key][$options['options']['details_field_name']][$options['options']['__parent_row_number']]);
                     }
                 } else {
                     if (!empty($this->misc_settings['details_unique_select'][$options['options']['details_key']][$options['options']['details_field_name']])) {
                         $skip_values = array_keys($this->misc_settings['details_unique_select'][$options['options']['details_key']][$options['options']['details_field_name']]);
                     }
                 }
             }
             $result_options['options'] = object_data_common::process_options($result_options['options_model'], $this, $result_options['options_params'], $value, $skip_values, $result_options['options_options']);
         } else {
             // we need to inject form id into autocomplete
             $result_options['form_id'] = "form_{$this->form_link}_form";
         }
     }
     // by default all selects are searchable if not specified otherwise
     if ($flag_select_or_autocomplete) {
         $result_options['searchable'] = $result_options['searchable'] ?? false;
     }
     // different handling for different type
     switch ($options['type']) {
         case 'container':
             $options_container = $options;
             //$options_container['previous_data'] = $v;
             // todo: pass $form_data_key from parent
             $options_container['previous_key'] = $options['previous_key'];
             // render container
             $temp_container_value = $this->render_container($data['fm_part_child_container_name'], $parents, $options_container);
             if (!empty($html_expand)) {
                 // get part id
                 $temp_id = $this->id('part_details', ['part_name' => $data['fm_part_name'], 'part_id' => $options_container['previous_id']]);
                 $temp_id_div_inner = $temp_id . '_html_expand_div_inner';
                 $temp_expand_div_inner = ['id' => $temp_id_div_inner, 'style' => 'display: none;', 'value' => $temp_container_value];
                 $temp_expand_div_a = ['href' => 'javascript:void(0);', 'onclick' => "numbers.element.toggle('{$temp_id_div_inner}');", 'value' => '+ / -'];
                 $temp_expand_div_outer = ['align' => 'left', 'value' => html::a($temp_expand_div_a) . '<br />' . html::div($temp_expand_div_inner)];
                 $value = html::div($temp_expand_div_outer);
             } else {
                 $value = $temp_container_value;
             }
             $result_options['value'] = $value;
             break;
         case 'field':
             $element_method = $result_options['method'] ?? 'html::input';
             if (strpos($element_method, '::') === false) {
                 $element_method = 'html::' . $element_method;
             }
             // value in special order
             $flag_translated = false;
             if (in_array($element_method, ['html::a', 'html::submit', 'html::button', 'html::button2'])) {
                 // translate value
                 $result_options['value'] = i18n($result_options['i18n'] ?? null, $result_options['value'] ?? null);
                 // process confirm_message
                 $result_options['onclick'] = $result_options['onclick'] ?? '';
                 if (!empty($result_options['confirm_message'])) {
                     $result_options['onclick'] .= 'return confirm(\'' . strip_tags(i18n(null, $result_options['confirm_message'])) . '\');';
                 }
                 // processing onclick for buttons
                 if (in_array($element_method, ['html::submit', 'html::button', 'html::button2'])) {
                     if (!empty($result_options['onclick']) && strpos($result_options['onclick'], 'this.form.submit();') !== false) {
                         $result_options['onclick'] = str_replace('this.form.submit();', "numbers.form.trigger_submit(this.form);", $result_options['onclick']) . ' return true;';
                     } else {
                         if (empty($result_options['onclick'])) {
                             $result_options['onclick'] .= 'numbers.form.trigger_submit_on_button(this); return true;';
                         } else {
                             $result_options['onclick'] = 'numbers.form.trigger_submit_on_button(this); ' . $result_options['onclick'];
                         }
                     }
                 }
                 $flag_translated = true;
                 // icon
                 if (!empty($result_options['icon'])) {
                     $result_options['value'] = html::icon(['type' => $result_options['icon']]) . ' ' . $result_options['value'];
                 }
                 // accesskey
                 if (isset($result_options['accesskey'])) {
                     $accesskey = explode('::', i18n(null, 'accesskey::' . $result_options['name'] . '::' . $result_options['accesskey'], ['skip_translation_symbol' => true]));
                     $result_options['accesskey'] = $accesskey[2];
                     $result_options['title'] = ($result_options['title'] ?? '') . ' ' . i18n(null, 'Shortcut Key: ') . $accesskey[2];
                 }
             } else {
                 if (in_array($element_method, ['html::div', 'html::span'])) {
                     if (!empty($result_options['i18n'])) {
                         $result_options['value'] = i18n($result_options['i18n'] ?? null, $result_options['value'] ?? null);
                         $flag_translated = true;
                     }
                 } else {
                     // editable fields
                     $result_options['value'] = $value;
                     // if we need to empty value, mostly for password fields
                     if (!empty($result_options['empty_value'])) {
                         $result_options['value'] = '';
                     }
                     // we need to empty zero integers and sequences, before format
                     if (($result_options['php_type'] ?? '') == 'integer' && ($result_options['type'] ?? '') != 'boolean' && ($result_options['domain'] ?? '') != 'counter' && 'counter' && empty($result_options['value'])) {
                         $result_options['value'] = '';
                     }
                     // format, not for selects/autocompletes/presets
                     if (!$flag_select_or_autocomplete) {
                         if (!empty($result_options['format'])) {
                             if (!empty($this->errors['fields'][$result_options['error_name']]) && empty($this->errors['formats'][$result_options['error_name']])) {
                                 // nothing
                             } else {
                                 $result_options['format_options'] = $result_options['format_options'] ?? [];
                                 if (!empty($result_options['format_depends'])) {
                                     $this->process_params_and_depends($result_options['format_depends'], $neighbouring_values, $options, true);
                                     $result_options['format_options'] = array_merge_hard($result_options['format_options'], $result_options['format_depends']);
                                 }
                                 $method = factory::method($result_options['format'], 'format');
                                 $result_options['value'] = call_user_func_array([$method[0], $method[1]], [$result_options['value'], $result_options['format_options']]);
                             }
                         }
                     }
                     // align
                     if (!empty($result_options['align'])) {
                         $result_options['style'] = ($result_options['style'] ?? '') . 'text-align:' . $result_options['align'] . ';';
                     }
                     // processing persistent
                     if (!empty($result_options['persistent']) && $this->values_loaded) {
                         if ($result_options['persistent'] === 'if_set') {
                             $original_value = $detail = array_key_get($this->original_values, $result_options['values_key']);
                             if (!empty($original_value)) {
                                 $result_options['readonly'] = true;
                             }
                         } else {
                             if (count($result_options['values_key']) == 1) {
                                 // parent record
                                 $result_options['readonly'] = true;
                             } else {
                                 if (empty($result_options['__new_row'])) {
                                     // details
                                     $temp = $result_options['values_key'];
                                     array_pop($temp);
                                     $detail = array_key_get($this->original_values, $temp);
                                     if (!empty($detail)) {
                                         $result_options['readonly'] = true;
                                     }
                                 }
                             }
                         }
                     }
                     // maxlength
                     if (in_array($result_options['type'] ?? '', ['char', 'varchar']) && !empty($result_options['length'])) {
                         $result_options['maxlength'] = $result_options['length'];
                     }
                     // global readonly
                     if (!empty($this->misc_settings['global']['readonly']) && empty($result_options['navigation'])) {
                         $result_options['readonly'] = true;
                     }
                     // title
                     if (isset($options['options']['label_name'])) {
                         $result_options['title'] = ($result_options['title'] ?? '') . ' ' . strip_tags(i18n(null, $options['options']['label_name']));
                     }
                 }
             }
             // translate place holder
             if (array_key_exists('placeholder', $result_options)) {
                 if (!empty($result_options['placeholder'])) {
                     $result_options['placeholder'] = strip_tags(i18n(null, $result_options['placeholder']));
                 }
             } else {
                 if (!empty($result_options['validator_method']) && empty($result_options['value'])) {
                     $temp = object_validator_base::method($result_options['validator_method'], $result_options['value'], $result_options['validator_params'] ?? [], $options['options'], $neighbouring_values);
                     if ($flag_select_or_autocomplete) {
                         $placeholder = $temp['placeholder_select'];
                     } else {
                         $placeholder = $temp['placeholder'];
                     }
                     if (!empty($placeholder)) {
                         $result_options['placeholder'] = strip_tags(i18n(null, $placeholder));
                     }
                 }
             }
             // events
             foreach (numbers_frontend_html_class_html5::$events as $e) {
                 if (!empty($result_options['readonly'])) {
                     // important - readonly emenets cannot have events
                     unset($result_options[$e]);
                 } else {
                     if (!empty($result_options[$e])) {
                         $result_options[$e] = str_replace('this.form.submit();', 'numbers.form.trigger_submit(this);', $result_options[$e]);
                         $result_options[$e] = str_replace('this.form.extended.', $this->misc_settings['extended_js_class'] . '.', $result_options[$e]);
                     }
                 }
             }
             break;
         case 'html':
             $element_method = null;
             break;
         default:
             throw new Exception('Render detail type: ' . $data['fm_part_type']);
     }
     // handling html_method
     if (isset($element_method)) {
         $method = factory::method($element_method, 'html');
         $field_method_object = factory::model($method[0], true);
         // todo: unset non html attributes
         $value = $field_method_object->{$method[1]}($result_options);
         // building navigation
         if (!empty($result_options['navigation'])) {
             $name = 'navigation[' . $result_options['name'] . ']';
             $temp = '<table width="100%" dir="ltr">';
             // always left to right
             $temp .= '<tr>';
             $temp .= '<td width="1%">' . html::button2(['name' => $name . '[first]', 'value' => html::icon(['type' => 'step-backward']), 'onclick' => 'numbers.form.trigger_submit_on_button(this);', 'title' => i18n(null, 'First')]) . '</td>';
             $temp .= '<td width="1%">&nbsp;</td>';
             $temp .= '<td width="1%">' . html::button2(['name' => $name . '[previous]', 'value' => html::icon(['type' => 'caret-left']), 'onclick' => 'numbers.form.trigger_submit_on_button(this);', 'title' => i18n(null, 'Previous')]) . '</td>';
             $temp .= '<td width="1%">&nbsp;</td>';
             $temp .= '<td width="90%">' . $value . '</td>';
             $temp .= '<td width="1%">&nbsp;</td>';
             $temp .= '<td width="1%">' . html::button2(['name' => $name . '[refresh]', 'value' => html::icon(['type' => 'refresh']), 'onclick' => 'numbers.form.trigger_submit_on_button(this);', 'title' => i18n(null, 'Refresh')]) . '</td>';
             $temp .= '<td width="1%">&nbsp;</td>';
             $temp .= '<td width="1%">' . html::button2(['name' => $name . '[next]', 'value' => html::icon(['type' => 'caret-right']), 'onclick' => 'numbers.form.trigger_submit_on_button(this);', 'title' => i18n(null, 'Next')]) . '</td>';
             $temp .= '<td width="1%">&nbsp;</td>';
             $temp .= '<td width="1%">' . html::button2(['name' => $name . '[last]', 'value' => html::icon(['type' => 'step-forward']), 'onclick' => 'numbers.form.trigger_submit_on_button(this);', 'title' => i18n(null, 'Last')]) . '</td>';
             $temp .= '</tr>';
             $temp .= '</table>';
             $value = $temp;
         }
     }
     // html suffix and prefix
     if (!empty($html_suffix)) {
         $value .= $html_suffix;
     }
     // if we need to display settings
     if (application::get('flag.numbers.frontend.html.form.show_field_settings')) {
         $id_original = $result_options['id'] . '__settings_original';
         $id_modified = $result_options['id'] . '__settings_modified';
         $value .= html::a(['href' => 'javascript:void(0);', 'onclick' => "\$('#{$id_original}').toggle();", 'value' => html::label2(['type' => 'primary', 'value' => count($options['options'])])]);
         $value .= html::a(['href' => 'javascript:void(0);', 'onclick' => "\$('#{$id_modified}').toggle();", 'value' => html::label2(['type' => 'warning', 'value' => count($result_options)])]);
         $value .= '<div id="' . $id_original . '" style="display:none; position: absolute; text-align: left; width: 500px; z-index: 32000;">' . print_r2($options['options'], true) . '</div>';
         $value .= '<div id="' . $id_modified . '" style="display:none; position: absolute; text-align: left; width: 500px; z-index: 32000;">' . print_r2($result_options, true) . '</div>';
     }
     // we need to put original options back
     if (!empty($options['options']['custom_renderer'])) {
         $options = $options_custom_renderer;
     }
     return $value;
 }
/**
 * Merge variables into object
 *
 * @param object $object
 * @param array $vars
 */
function object_merge_values(&$object, $vars)
{
    foreach ($vars as $k => $v) {
        if (property_exists($object, $k) && is_array($object->{$k})) {
            foreach ($v as $k2 => $v2) {
                if ($v2 === null) {
                    unset($object->{$k}[$k2]);
                } else {
                    if (isset($object->{$k}[$k2]) && is_array($object->{$k}[$k2])) {
                        $object->{$k}[$k2] = array_merge_hard($object->{$k}[$k2], $v2);
                    } else {
                        $object->{$k}[$k2] = $v2;
                    }
                }
            }
        } else {
            $object->{$k} = $v;
        }
    }
}
Exemple #12
0
 /**
  * Constructor
  *
  * @param array $options
  *		input - form input
  *		form - form options
  *		segment - segment options
  *			type
  *			header
  *			footer
  */
 public function __construct($options = [])
 {
     // we need to handle overrrides
     parent::override_handle($this);
     // step 0: apply data fixes
     if (method_exists($this, 'overrides')) {
         $this->overrides($this);
     }
     // we need to merge override input
     if (!empty($this->values)) {
         $options['input'] = array_merge_hard($options['input'] ?? [], $this->values);
     }
     if (isset($options['form_link'])) {
         $this->form_link = $options['form_link'];
     }
     // step 1: create form object
     $this->form_object = new numbers_frontend_html_form_base($this->form_link, array_merge_hard($this->options, $options));
     // class
     $this->form_object->form_class = get_called_class();
     $this->form_object->form_parent =& $this;
     $this->form_object->acl = $this->acl;
     // add collection
     $this->form_object->collection = $this->collection;
     $this->form_object->preload_collection_object();
     // must initialize it before calls to container/row/element
     $this->form_object->column_prefix = $this->column_prefix ?? $this->form_object->collection_object->primary_model->column_prefix ?? null;
     // master object
     if (!empty($this->master_options['model'])) {
         $this->master_options['type'] = $this->master_options['type'] ?? '';
         $this->master_options['ledger'] = strtoupper($this->master_options['ledger']) ?? '';
         $this->form_object->master_options = $this->master_options;
         $this->form_object->master_object = factory::model($this->master_options['model'], true);
     }
     // title
     if (!empty($this->title)) {
         $this->form_object->title = $this->title;
     } else {
         // we generate a title based on class name
         $temp = explode('_model_form_', get_called_class());
         $temp = explode('_', $temp[1]);
         $this->title = $this->form_object->title = ucwords(implode(' ', $temp));
     }
     // step 2: create all containers
     foreach ($this->containers as $k => $v) {
         if ($v === null) {
             continue;
         }
         $this->form_object->container($k, $v);
     }
     // step 3: create all rows
     foreach ($this->rows as $k => $v) {
         foreach ($v as $k2 => $v2) {
             if ($v2 === null) {
                 continue;
             }
             $this->form_object->row($k, $k2, $v2);
         }
     }
     // step 3: create all elements
     foreach ($this->elements as $k => $v) {
         foreach ($v as $k2 => $v2) {
             foreach ($v2 as $k3 => $v3) {
                 if ($v3 === null) {
                     continue;
                 }
                 $this->form_object->element($k, $k2, $k3, $v3);
             }
         }
     }
     // step 3: methods
     foreach (['save', 'validate', 'refresh', 'success', 'pre_render', 'override_field_value', 'override_tabs', 'process_default_value'] as $v) {
         if (method_exists($this, $v)) {
             $this->form_object->wrapper_methods[$v]['main'] = [&$this, $v];
         }
     }
     // extensions can have their own verify methods
     if (!empty($this->wrapper_methods)) {
         foreach ($this->wrapper_methods as $k => $v) {
             $index = 1;
             foreach ($v as $k2 => $v2) {
                 $this->form_object->wrapper_methods[$k][$index] = [new $k2(), $v2];
                 $index++;
             }
         }
     }
     // last step: process form
     if (empty($options['skip_processing'])) {
         $this->form_object->process();
     }
 }
 /**
  * Determine model map
  *
  * @param string $class
  * @param string $widget_name
  * @return boolean
  * @throws Exception
  */
 public final function determine_model_map($class, $widget_name)
 {
     $this->virtual_class_name = $class . '__virtual__' . $widget_name;
     $model = factory::model($class, true);
     $this->name = $model->name . '__' . $widget_name;
     // determine pk
     $counter = 1;
     $all_int = true;
     $columns = [];
     $this->map = [];
     $this->__relation_pk = [];
     foreach ($model->pk as $v) {
         if ($model->columns[$v]['php_type'] == 'integer') {
             if ($v == $model->column_prefix . 'id') {
                 $temp = explode('_', $v);
                 unset($temp[0]);
                 $new = $this->column_prefix . implode('_', $temp);
             } else {
                 $new = str_replace($model->column_prefix, $this->column_prefix, $v);
             }
             $columns[$new] = $model->columns[$v];
             // copy the same settings
             if (!empty($columns[$new]['domain'])) {
                 $columns[$new]['domain'] = str_replace('_sequence', '', $columns[$new]['domain']);
                 unset($columns[$new]['type'], $columns[$new]['php_type']);
             }
             $this->map[$v] = $new;
         } else {
             $all_int = false;
         }
         $counter++;
     }
     // if we have no integer pk
     if (!$all_int) {
         if (!empty($model->relation['field'])) {
             $new = str_replace($model->column_prefix, $this->column_prefix, $model->relation['field']);
             $columns = [];
             $columns[$new] = $model->columns[$model->relation['field']];
             // copy the same settings
             if (!empty($columns[$new]['domain'])) {
                 $columns[$new]['domain'] = str_replace('_sequence', '', $columns[$new]['domain']);
                 unset($columns[$new]['type'], $columns[$new]['php_type']);
             }
             $this->map = [$model->relation['field'] => $new];
             $this->__relation_pk = $model->pk;
         } else {
             throw new Exception('Unable to create widget model!');
         }
     }
     $this->columns = array_merge_hard($this->columns, $columns);
     return true;
 }
Exemple #14
0
 /**
  * Convert array of percentages to grid columns
  *
  * @param mixed $percentage_array
  * @return array
  */
 public static function percentage_to_grid_columns($percentage_array, $options = [])
 {
     if (!is_array($percentage_array)) {
         $percentage_array = [$percentage_array];
     }
     $options = array_merge_hard(application::get('flag.numbers.framework.html.options'), $options);
     if (empty($options['grid_columns'])) {
         $options['grid_columns'] = 12;
     }
     $step = 100 / $options['grid_columns'];
     $total = 0;
     $empty = 0;
     $arr = ['percent' => [], 'final' => [], 'temp' => [], 'grouped' => []];
     foreach ($percentage_array as $k => $v) {
         $arr['percent'][$k] = $v ? $v : 0;
         if (!empty($v)) {
             $total += $v;
         } else {
             $empty += 1;
         }
     }
     // if we have empty columns and percent is less than 100 we prepopulate
     if ($total < 100 && $empty != 0) {
         $temp = (100 - $total) / $empty;
         foreach ($arr['percent'] as $k => $v) {
             if ($v == 0) {
                 $arr['percent'][$k] = $temp;
                 $total += $temp;
             }
         }
     }
     // we need to rescale if percent is more than 100
     if ($total > 100) {
         $scale = 100 / $total;
         foreach ($arr['percent'] as $k => $v) {
             $arr['percent'][$k] = $v * $scale;
         }
     }
     // sort in ascending order
     asort($arr['percent']);
     $cells_left = $options['grid_columns'];
     foreach ($arr['percent'] as $k => $v) {
         if ($v <= $step) {
             $arr['final'][$k] = 1;
             $cells_left--;
         } else {
             $rounded = floor($v / $step);
             $leftover = $v - $rounded * $step;
             $arr['final'][$k] = $rounded;
             $cells_left -= $rounded;
             if ($leftover > 0) {
                 $arr['temp'][$k] = $leftover;
             }
         }
     }
     // if we have cells left we distribute
     if ($cells_left > 0) {
         // grouping & sorting for special handling
         /* todo: polish login for left overs
         			foreach ($arr['percent'] as $k => $v) {
         				$arr['grouped'][$v][$k] = 1;
         			}
         			krsort($arr['grouped']);
         			$temp = array_values($arr['grouped']);
         			if ($cells_left == 2 && count($arr['grouped']) > 1 && count($temp[0]) == 1 && count($temp[1]) > 1) {
         				$arr['final'][key($temp[0])]+= 2;
         				$cells_left = 0;
         			}
         			*/
         // if we got here we distribute on by one
         if ($cells_left > 0) {
             arsort($arr['temp']);
             foreach ($arr['temp'] as $k => $v) {
                 $arr['final'][$k]++;
                 $cells_left--;
                 unset($arr['temp'][$k]);
                 if ($cells_left == 0) {
                     break;
                 }
             }
         }
     }
     return ['success' => true, 'error' => [], 'data' => $arr['final']];
 }
 /**
  * Process models
  *
  * @param array $options
  * @return array
  */
 public static function process_models($options = [])
 {
     $result = ['success' => false, 'error' => [], 'hint' => [], 'data' => []];
     do {
         // we need to process all dependencies first
         $dep = self::process_deps_all($options);
         if (!$dep['success']) {
             $result = $dep;
             $result['error'][] = 'You must fix all dependency related errors first before processing models.';
             break;
         }
         // proccesing models
         if (empty($dep['data']['model_processed'])) {
             $result['error'][] = 'You do not have models to process!';
             break;
         }
         $object_attributes = [];
         $object_relations = [];
         $object_forms = [];
         $flag_relation = application::get('dep.submodule.numbers.data.relations') ? true : false;
         $object_documentation = [];
         $object_import = [];
         $ddl = new numbers_backend_db_class_ddl();
         // run 1 to deterine virtual tables
         $first = true;
         $virtual_models = $dep['data']['model_processed'];
         run_again:
         foreach ($virtual_models as $k => $v) {
             $k2 = str_replace('.', '_', $k);
             if ($v == 'object_table') {
                 $model = factory::model($k2, true);
                 foreach (['attributes', 'audit', 'addresses'] as $v0) {
                     if ($model->{$v0}) {
                         $v01 = $v0 . '_model';
                         $virtual_models[str_replace('_', '.', $model->{$v01})] = 'object_table';
                     }
                 }
             }
         }
         if ($first) {
             $first = false;
             goto run_again;
             // some widgets have attributes
         }
         $dep['data']['model_processed'] = array_merge_hard($dep['data']['model_processed'], $virtual_models);
         $domains = object_data_domains::get_static();
         // run 2
         foreach ($dep['data']['model_processed'] as $k => $v) {
             $k2 = str_replace('.', '_', $k);
             if ($v == 'object_table') {
                 $model = factory::model($k2, true);
                 $temp_result = $ddl->process_table_model($model);
                 if (!$temp_result['success']) {
                     array_merge3($result['error'], $temp_result['error']);
                 }
                 $object_documentation[$v][$k2] = $k2;
                 // relation
                 if ($flag_relation) {
                     if (!empty($model->relation)) {
                         $domain = $model->columns[$model->relation['field']]['domain'] ?? null;
                         if (!empty($domain)) {
                             $domain = str_replace('_sequence', '', $domain);
                             $type = $domains[$domain]['type'];
                         } else {
                             $type = $model->columns[$model->relation['field']]['type'];
                         }
                         $object_relations[$k2] = ['rn_relattr_code' => $model->relation['field'], 'rn_relattr_name' => $model->title, 'rn_relattr_model' => $k2, 'rn_relattr_domain' => $domain, 'rn_relattr_type' => $type, 'rn_relattr_inactive' => !empty($model->relation['inactive']) ? 1 : 0];
                     }
                     if (!empty($model->attributes)) {
                         $object_attributes[$k2] = ['rn_attrmdl_code' => $k2, 'rn_attrmdl_name' => $model->title, 'rn_attrmdl_inactive' => 0];
                     }
                 }
             } else {
                 if ($v == 'object_sequence') {
                     $temp_result = $ddl->process_sequence_model($k2);
                     if (!$temp_result['success']) {
                         array_merge3($result['error'], $temp_result['error']);
                     }
                     $object_documentation[$v][$k2] = $k2;
                 } else {
                     if ($v == 'object_function') {
                         $temp_result = $ddl->process_function_model($k2);
                         if (!$temp_result['success']) {
                             array_merge3($result['error'], $temp_result['error']);
                         }
                         $object_documentation[$v][$k2] = $k2;
                     } else {
                         if ($v == 'object_extension') {
                             $temp_result = $ddl->process_function_extension($k2);
                             if (!$temp_result['success']) {
                                 array_merge3($result['error'], $temp_result['error']);
                             }
                             $object_documentation[$v][$k2] = $k2;
                         } else {
                             if ($v == 'object_import') {
                                 $object_import[$k2] = ['model' => $k2];
                             }
                         }
                     }
                 }
             }
         }
         // if we have erros
         if (!empty($result['error'])) {
             break;
         }
         // db factory
         $db_factory = factory::get('db');
         // we load objects from database
         $loaded_objects = [];
         foreach ($ddl->db_links as $k => $v) {
             $ddl_object = $db_factory[$k]['ddl_object'];
             $temp_result = $ddl_object->load_schema($k);
             if (!$temp_result['success']) {
                 array_merge3($result['error'], $temp_result['error']);
             } else {
                 $loaded_objects[$k] = $temp_result['data'];
             }
         }
         // if we have erros
         if (!empty($result['error'])) {
             break;
         }
         // get a list of all db links
         $db_link_list = array_unique(array_merge(array_keys($ddl->objects), array_keys($loaded_objects)));
         // if we are dropping schema
         if ($options['mode'] == 'drop') {
             $ddl->objects = [];
         }
         // compare schemas per db link
         $schema_diff = [];
         $total_per_db_link = [];
         $total = 0;
         foreach ($db_link_list as $k) {
             // we need to have a back end for comparison
             $compare_options['backend'] = $db_factory[$k]['backend'];
             // comparing
             $temp_result = $ddl->compare_schemas(isset($ddl->objects[$k]) ? $ddl->objects[$k] : [], isset($loaded_objects[$k]) ? $loaded_objects[$k] : [], $compare_options);
             if (!$temp_result['success']) {
                 array_merge3($result['hint'], $temp_result['error']);
             } else {
                 $schema_diff[$k] = $temp_result['data'];
                 if (!isset($total_per_db_link[$k])) {
                     $total_per_db_link[$k] = 0;
                 }
                 $total_per_db_link[$k] += $temp_result['count'];
                 $total += $temp_result['count'];
             }
         }
         // if there's no schema changes
         if ($total == 0) {
             if ($options['mode'] == 'commit') {
                 goto import_data;
             } else {
                 $result['success'] = true;
             }
             break;
         }
         // we need to provide a list of changes
         foreach ($total_per_db_link as $k => $v) {
             $result['hint'][] = '';
             $result['hint'][] = "Db link {$k} requires {$v} changes!";
             // printing summary
             $result['hint'][] = ' * Link ' . $k . ': ';
             foreach ($schema_diff[$k] as $k2 => $v2) {
                 $result['hint'][] = '   * ' . $k2 . ': ';
                 foreach ($v2 as $k3 => $v3) {
                     $result['hint'][] = '    * ' . $k3 . ' - ' . $v3['type'];
                 }
             }
         }
         // if we are in no commit mode we exit
         if (!in_array($options['mode'], ['commit', 'drop'])) {
             break;
         }
         // generating sql
         foreach ($total_per_db_link as $k => $v) {
             if ($v == 0) {
                 continue;
             }
             $ddl_object = $db_factory[$k]['ddl_object'];
             foreach ($schema_diff[$k] as $k2 => $v2) {
                 foreach ($v2 as $k3 => $v3) {
                     // we need to make fk constraints last to sort MySQL issues
                     if ($k2 == 'new_constraints' && $v3['type'] == 'constraint_new' && $v3['data']['type'] == 'fk') {
                         $schema_diff[$k][$k2 . '_fks'][$k3]['sql'] = $ddl_object->render_sql($v3['type'], $v3);
                     } else {
                         $schema_diff[$k][$k2][$k3]['sql'] = $ddl_object->render_sql($v3['type'], $v3, ['mode' => $options['mode']]);
                     }
                 }
             }
         }
         //			print_r($schema_diff);
         //			exit;
         // executing sql
         foreach ($total_per_db_link as $k => $v) {
             if ($v == 0) {
                 continue;
             }
             $db_object = new db($k);
             // if we are dropping we need to disable foregn key checks
             if ($options['mode'] == 'drop') {
                 if ($db_object->backend == 'mysqli') {
                     $db_object->query('SET foreign_key_checks = 0;');
                     // we also need to unset sequences
                     unset($schema_diff[$k]['delete_sequences']);
                 }
             }
             foreach ($schema_diff[$k] as $k2 => $v2) {
                 foreach ($v2 as $k3 => $v3) {
                     if (empty($v3['sql'])) {
                         continue;
                     }
                     if (is_array($v3['sql'])) {
                         $temp = $v3['sql'];
                     } else {
                         $temp = [$v3['sql']];
                     }
                     foreach ($temp as $v4) {
                         $temp_result = $db_object->query($v4);
                         if (!$temp_result['success']) {
                             array_merge3($result['error'], $temp_result['error']);
                             goto error;
                         }
                     }
                 }
             }
         }
         // if we got here - we are ok
         $result['success'] = true;
     } while (0);
     import_data:
     // we need to import data
     if (!empty($object_import) && $options['mode'] == 'commit') {
         $result['hint'][] = '';
         foreach ($object_import as $k => $v) {
             $data_object = new $k();
             $data_result = $data_object->process();
             if (!$data_result['success']) {
                 throw new Exception(implode("\n", $data_result['error']));
             }
             $result['hint'] = array_merge($result['hint'], $data_result['hint']);
         }
     }
     // relation
     if ($flag_relation && $options['mode'] == 'commit') {
         $result['hint'][] = '';
         $model2 = factory::model('numbers_data_relations_model_relation_attributes');
         // insert new models
         if (!empty($object_relations)) {
             foreach ($object_relations as $k => $v) {
                 $result_insert = $model2->save($v, ['pk' => ['rn_relattr_code'], 'ignore_not_set_fields' => true]);
             }
             $result['hint'][] = ' * Imported relation models!';
         }
         // we need to process forms
         foreach ($dep['data']['submodule_dirs'] as $v) {
             $dir = $v . 'model/form/';
             if (!file_exists($dir)) {
                 continue;
             }
             $files = helper_file::iterate($dir, ['only_extensions' => ['php']]);
             foreach ($files as $v2) {
                 $model_name = str_replace(['../libraries/vendor/', '.php'], '', $v2);
                 $model_name = str_replace('/', '_', $model_name);
                 $model = new $model_name(['skip_processing' => true]);
                 if (empty($model->form_object->misc_settings['option_models'])) {
                     continue;
                 }
                 // loop though fields
                 foreach ($model->form_object->misc_settings['option_models'] as $k3 => $v3) {
                     $object_forms[$model_name . '::' . $k3] = ['rn_relfrmfld_form_code' => $model_name, 'rn_relfrmfld_form_name' => $model->title, 'rn_relfrmfld_field_code' => $k3, 'rn_relfrmfld_field_name' => $v3['field_name'], 'rn_relfrmfld_relattr_id' => $v3['model'], 'rn_relfrmfld_inactive' => 0];
                 }
             }
         }
         if (!empty($object_forms)) {
             // load all relation models
             $data = $model2->get(['pk' => ['rn_relattr_model']]);
             $model = factory::model('numbers_data_relations_model_relation_formfields');
             foreach ($object_forms as $k => $v) {
                 if (empty($data[$v['rn_relfrmfld_relattr_id']])) {
                     continue;
                 }
                 $v['rn_relfrmfld_relattr_id'] = $data[$v['rn_relfrmfld_relattr_id']]['rn_relattr_id'];
                 $result_insert = $model->save($v, ['pk' => ['rn_relfrmfld_form_code', 'rn_relfrmfld_field_code'], 'ignore_not_set_fields' => true]);
             }
             $result['hint'][] = ' * Imported relation form fields!';
         }
         // todo: import models
         //print_r2($object_attributes);
         if (!empty($object_attributes)) {
             $model = factory::model('numbers_data_relations_model_attribute_models');
             foreach ($object_attributes as $k => $v) {
                 $result_insert = $model->save($v, ['pk' => ['rn_attrmdl_code'], 'ignore_not_set_fields' => true]);
             }
             $result['hint'][] = ' * Imported attribute models!';
         }
     }
     // we need to generate documentation
     $system_documentation = application::get('system_documentation');
     if (!empty($system_documentation) && $options['mode'] == 'commit') {
         $model = factory::model($system_documentation['model']);
         /*
         print_r2($object_documentation);
         $documentation_result = $model->update($object_documentation, $system_documentation);
         if (!$documentation_result['success']) {
         	$result['error'] = array_merge($result['error'], $documentation_result['error']);
         }
         */
     }
     error:
     return $result;
 }
 /**
  * Initialize db connections, cache and session
  */
 public static function init($options = [])
 {
     // initialize mbstring
     mb_internal_encoding('UTF-8');
     mb_regex_encoding('UTF-8');
     // get flags & dependencies
     $flags = application::get('flag');
     $backend = application::get('numbers.backend', ['backend_exists' => true]);
     // processing wildcard first
     $wildcard = application::get('wildcard');
     $wildcard_keys = null;
     if (!empty($wildcard['enabled']) && !empty($wildcard['model'])) {
         $wildcard_keys = call_user_func($wildcard['model']);
         application::set(['wildcard', 'keys'], $wildcard_keys);
     }
     // initialize cryptography
     $crypt = application::get('crypt');
     if (!empty($crypt) && $backend) {
         foreach ($crypt as $crypt_link => $crypt_settings) {
             if (!empty($crypt_settings['submodule']) && !empty($crypt_settings['autoconnect'])) {
                 $crypt_object = new crypt($crypt_link, $crypt_settings['submodule'], $crypt_settings);
             }
         }
     }
     // create database connections
     $db = application::get('db');
     if (!empty($db) && $backend) {
         foreach ($db as $db_link => $db_settings) {
             if (empty($db_settings['autoconnect']) || empty($db_settings['servers']) || empty($db_settings['submodule'])) {
                 continue;
             }
             $connected = false;
             foreach ($db_settings['servers'] as $server_key => $server_values) {
                 $db_object = new db($db_link, $db_settings['submodule']);
                 // wildcards replaces
                 if (isset($wildcard_keys[$db_link])) {
                     $server_values['dbname'] = $wildcard_keys[$db_link]['dbname'];
                 }
                 // connecting
                 $server_values = array_merge2($server_values, $db_settings);
                 $db_status = $db_object->connect($server_values);
                 if ($db_status['success'] && $db_status['status']) {
                     $connected = true;
                     break;
                 }
             }
             // checking if not connected
             if (!$connected) {
                 throw new Exception('Unable to open database connection!');
             }
         }
     }
     // initialize cache
     $cache = application::get('cache');
     if (!empty($cache) && $backend) {
         foreach ($cache as $cache_link => $cache_settings) {
             if (empty($cache_settings['submodule']) || empty($cache_settings['autoconnect'])) {
                 continue;
             }
             $connected = false;
             foreach ($cache_settings['servers'] as $cache_server) {
                 $cache_object = new cache($cache_link, $cache_settings['submodule']);
                 $cache_status = $cache_object->connect($cache_server);
                 if ($cache_status['success']) {
                     $connected = true;
                     break;
                 }
             }
             // checking if not connected
             if (!$connected) {
                 throw new Exception('Unable to open cache connection!');
             }
         }
     }
     // if we are from command line we exit here
     if (!empty($options['__run_only_bootstrap'])) {
         return;
     }
     // initialize session
     $session = application::get('flag.global.session');
     if (!empty($session['start']) && $backend && !application::get('flag.global.__skip_session')) {
         session::start(isset($session['options']) ? $session['options'] : []);
     }
     // we need to get overrides from session and put them back to flag array
     $flags = array_merge_hard($flags, session::get('numbers.flag'));
     application::set('flag', $flags);
     // initialize i18n
     if ($backend) {
         $temp_result = i18n::init();
         if (!$temp_result['success']) {
             throw new Exception('Could not initialize i18n.');
         }
     }
     // format
     format::init();
     // including libraries that we need to auto include
     if (!empty($flags['global']['library'])) {
         foreach ($flags['global']['library'] as $k => $v) {
             // we need to skip certain keys
             if ($k == 'submodule' || $k == 'options') {
                 continue;
             }
             // we only include if autoconnect is on
             if (!empty($v['autoconnect'])) {
                 factory::submodule('flag.global.library.' . $k . '.submodule')->add();
             }
         }
     }
     // check if we need to include system files from frontend
     if (application::get('dep.submodule.numbers.frontend.system')) {
         numbers_frontend_system_model_base::start();
     }
 }
Exemple #17
0
 /**
  * Constructing database object
  *
  * @param string $db_link
  */
 public function __construct($db_link)
 {
     $this->db_link = $db_link;
     // keywords overrides
     $this->sql_keywords = array_merge_hard($this->sql_keywords, $this->sql_keywords_overrides);
 }