/** * Constructing cache object * * @param string $cache_link * @param string $class */ public function __construct($cache_link = null, $class = null) { // if we need to use default link from application if (empty($cache_link)) { $cache_link = application::get(['flag', 'global', 'cache', 'default_cache_link']); if (empty($cache_link)) { throw new Exception('You must specify cache link and/or class!'); } } // get object from factory $temp = factory::get(['cache', $cache_link]); // if we have class if (!empty($class) && !empty($cache_link)) { // replaces in case we have it as submodule $class = str_replace('.', '_', trim($class)); // if we are replacing database connection with the same link we // need to manually close connection if (!empty($temp['object']) && $temp['class'] != $class) { $object = $temp['object']; $object->close(); unset($this->object); } $this->object = new $class($cache_link); // putting every thing into factory factory::set(['cache', $cache_link], ['object' => $this->object, 'class' => $class]); } else { if (!empty($temp['object'])) { $this->object = $temp['object']; } else { throw new Exception('You must specify cache link and/or class!'); } } }
/** * Constructing crypt object * * @param string $db_link * @param string $class */ public function __construct($crypt_link = null, $class = null, $options = []) { // if we need to use default link from application if ($crypt_link == null) { $crypt_link = application::get(['flag', 'global', 'crypt', 'default_crypt_link']); if (empty($crypt_link)) { throw new Exception('You must specify crypt link!'); } } // get object from factory $temp = factory::get(['crypt', $crypt_link]); // if we have class if (!empty($class) && !empty($crypt_link)) { // replaces in case we have it as submodule $class = str_replace('.', '_', trim($class)); // creating new class unset($this->object); $this->object = new $class($crypt_link, $options); factory::set(['crypt', $crypt_link], ['object' => $this->object, 'class' => $class]); } else { if (!empty($temp['object'])) { $this->object = $temp['object']; } else { throw new Exception('You must specify crypt link and/or class!'); } } }
/** * 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); }
public function action_index() { // clear buffer helper_ob::clean_all(); // validating do { $options = application::get('flag.numbers.backend.cron.base'); // token if (!empty($options['token']) && request::input('token') != $options['token']) { break; } // ip if (!empty($options['ip']) && !in_array(request::ip(), $options['ip'])) { break; } // get date parts $date_parts = format::now('parts'); print_r($date_parts); echo "GOOD\n"; } while (0); // we need to validate token //$token = request::input('token'); echo "OK\n"; // exit exit; }
/** * Add library to the application * * @param string $library */ public static function add($library) { $connected = application::get('flag.global.library.' . $library . '.connected'); if (!$connected) { factory::submodule('flag.global.library.' . $library . '.submodule')->add(); application::set('flag.global.library.' . $library . '.connected', true); } }
/** * Release the lock * * @param string $id * @return boolean */ public static function release($id) { $temp_dir = application::get(array('directory', 'temp')); if (isset($temp_dir['dir'])) { return unlink($temp_dir['dir'] . '__lock_' . $id); } return true; }
/** * Serve js and/or css files, mostly used in development * * @param string $filename */ public static function serve_media_if_exists($filename, $application_path) { // we need to remove question mark and all after it if (strpos($filename, '?') !== false) { $temp = explode('?', $filename); $filename = $temp[0]; } // generated files first if (strpos($filename, '/numbers/media_generated/') === 0) { $filename = str_replace('/numbers/media_generated/application_', '', $filename); $filename = $application_path . str_replace('_', '/', $filename); } else { if (strpos($filename, '/numbers/media_submodules/') === 0) { $temp = str_replace('/numbers/media_submodules/', '', $filename); $temp = str_replace('_', '/', $temp); $filename = './../libraries/vendor/' . $temp; } else { // we must return, do not exit !!! return; } } // check if file exists on file system if (!file_exists($filename)) { return; } // we need to know extension of a file $ext = pathinfo($filename, PATHINFO_EXTENSION); if ($ext == 'css' || $ext == 'js') { $new = $filename; $flag_scss = false; if (strpos($filename, '.scss.css') !== false) { $new = str_replace('.scss.css', '.scss', $new); $flag_scss = true; } if (file_exists($new)) { if ($ext == 'js') { header('Content-Type: application/javascript'); echo file_get_contents($new); } if ($ext == 'css') { header('Content-type: text/css'); if (!$flag_scss) { echo file_get_contents($new); } else { if (application::get('dep.submodule.numbers.frontend.media.scss')) { $temp = numbers_frontend_media_scss_base::serve($new); if ($temp['success']) { echo $temp['data']; } } } } exit; } } }
/** * Indicator whether widgets are enabled * * @param string $widget * @return boolean */ public static function enabled($widget) { if (!application::get('numbers.data', ['backend_exists' => true])) { return false; } if (!application::get("flag.global.widgets.{$widget}.submodule")) { return false; } return true; }
public function action_index() { $id = application::get(['mvc', 'controller_id']); if ($id) { $result = url_tinyurl::get($id); if ($result['success']) { request::redirect($result['data']['url']); } } }
/** * Model * * @param string $class */ public static function model($class) { $temp = explode('__virtual__', $class); $last = array_pop($temp); // fetch submodule $submodule = application::get("flag.global.widgets.{$last}.submodule"); $class = str_replace('.base__123', '', $submodule . '__123'); $class = str_replace('.', '_', $class) . '_model_virtual_' . $last; // create an object $object = new $class(implode('__virtual__', $temp)); return $object; }
/** * 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); } }
/** * Write content to file and sets permissions * * @param string $filename * @param mixed $data * @param int $permission * @param int $flags * @param boolean $relative */ public static function write($filename, $data, $permission = 0777, $flags = LOCK_EX, $relative = true) { // if we have relative path we convert it to full path if ($relative && $filename[0] == '.') { $path = application::get('application.path_full'); $info = pathinfo($filename); $filename = realpath($path . $info['dirname']) . '/' . $info['basename']; } // write file if (file_put_contents($filename, $data, $flags) !== false) { @chmod($filename, $permission); return true; } return false; }
/** * Get translation * * @param string $i18n * @param string $text * @param array $options * @return string */ public static function get($i18n, $text, $options = []) { $result = $text; // if we need to handle replaces, for example: // "Error occured on line [line_number]" if (!empty($options['replace'])) { foreach ($options['replace'] as $k => $v) { $result = str_replace($k, $v, $result); } } // todo: add debug mode, maybe append i18n if (debug::$debug && application::get('flag.global.__content_type') == 'text/html') { $result .= ' <span style="color:blue">i</span>'; } return $result; }
/** * Send an email * * Usage example: * * $result = mail::send([ * 'to' => 'test@localhost', * 'cc' => 'cc@localhost', * 'bcc' => 'bcc@localhost', * 'subject' => 'test subject', * 'message' => 'test message', * 'attachments' => [ * ['path' => 'path to file', 'name' => 'test.txt'], * ['data' => '!!!data!!!', 'name' => 'test.txt', 'type' => 'plain/text'] * ] * ]); * * @param array $options */ public static function send($options) { $result = ['success' => false, 'error' => []]; // mail delivery first $mail_delivery_class = application::get('flag.global.mail.delivery.submodule', ['class' => 1]); if (empty($mail_delivery_class)) { throw new Exception('You need to specify mail delivery submodule'); } $mail_delivery_object = new $mail_delivery_class(); $temp = $mail_delivery_object->send($options); if (!$temp['success']) { array_merge3($result['error'], $temp['error']); } else { $result['success'] = true; } return $result; }
/** * Constructing object * * @throws Exception */ public function __construct() { // we need to determine db link if (empty($this->db_link)) { // get from flags first if (!empty($this->db_link_flag)) { $this->db_link = application::get($this->db_link_flag); } // get default link if (empty($this->db_link)) { $this->db_link = application::get('flag.global.db.default_db_link'); } // if we could not determine the link we throw exception if (empty($this->db_link)) { throw new Exception('Could not determine db link in function!'); } } }
/** * Constructing database object * * @param string $db_link * @param string $class */ public function __construct($db_link = null, $class = null) { // if we need to use default link from application if (empty($db_link)) { $db_link = application::get(['flag', 'global', 'db', 'default_db_link']); if (empty($db_link)) { throw new Exception('You must specify database link and/or class!'); } } // get object from factory $temp = factory::get(['db', $db_link]); // if we have class if (!empty($class) && !empty($db_link)) { // replaces in case we have it as submodule $class = str_replace('.', '_', trim($class)); // if we are replacing database connection with the same link we // need to manually close database connection if (!empty($temp['object']) && $temp['class'] != $class) { $object = $temp['object']; $object->close(); unset($this->object); } // creating new class $this->object = new $class($db_link); // determining ddl class & object $ddl_class = str_replace('_base_abc123', '_ddl', $class . '_abc123'); $ddl_object = new $ddl_class(); // backend $this->backend = str_replace(['numbers_backend_db_', '_base'], '', $class); // putting every thing into factory factory::set(['db', $db_link], ['object' => $this->object, 'class' => $class, 'backend' => $this->backend, 'ddl_class' => $ddl_class, 'ddl_object' => $ddl_object]); } else { if (!empty($temp['object'])) { $this->object =& $temp['object']; $this->backend = $temp['backend']; } else { throw new Exception('You must specify database link and/or class!'); } } }
/** * User IP * * @return string */ public static function ip() { // for development purposes we might need to have specific IP address $request_ip = application::get('flag.numbers.framework.request.ip'); if (!empty($request_ip)) { return $request_ip; } // get users IP $result = $_SERVER['REMOTE_ADDR']; // if request goes through the proxy if (!empty($_SERVER['HTTP_X_REAL_IP'])) { $result = $_SERVER['HTTP_X_REAL_IP']; } if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $result = $_SERVER['HTTP_X_FORWARDED_FOR']; } // sometimes we have few IP addresses we take last one if (strpos($result, ',') !== false) { $temp = explode(',', $result); $result = trim($temp[sizeof($temp) - 1]); } return $result; }
/** * Initialize * * @param array $options */ public static function init($options = []) { // default options self::$defaut_options = ['language_code' => 'sys', 'locale' => 'en_CA.UTF-8', 'timezone' => 'America/Toronto', 'server_timezone' => application::get('php.date.timezone'), 'date' => 'Y-m-d', 'time' => 'H:i:s', 'datetime' => 'Y-m-d H:i:s', 'timestamp' => 'Y-m-d H:i:s.u', 'amount_frm' => 20, 'amount_fs' => 40, 'settings' => ['currency_codes' => []], 'locale_locales' => [], 'locale_locale_js' => null, 'locale_set_name' => null, 'locale_options' => [], 'locale_override_class' => null]; // settings from config files $config = application::get('flag.global.format'); // settings from user account $entity = entity::groupped('format'); // merge all of them together self::$options = array_merge_hard(self::$defaut_options, $config, i18n::$options, $entity, $options); // fix utf8 self::$options['locale'] = str_replace(['utf8', 'utf-8'], 'UTF-8', self::$options['locale']); // generate a list of available locales $locale_settings = self::set_locale(self::$options['locale'], self::$defaut_options['locale']); self::$options = array_merge_hard(self::$options, $locale_settings); // fix values self::$options['amount_frm'] = (int) self::$options['amount_frm']; self::$options['amount_fs'] = (int) self::$options['amount_fs']; self::$options['locale_options']['mon_thousands_sep'] = self::$options['locale_options']['mon_thousands_sep'] ?? ','; self::$options['locale_options']['mon_decimal_point'] = self::$options['locale_options']['mon_decimal_point'] ?? '.'; if (empty(self::$options['locale_options']['mon_grouping'])) { self::$options['locale_options']['mon_grouping'] = [3, 3]; } // load data from models if (!empty(self::$options['model'])) { foreach (self::$options['model'] as $k => $v) { $method = factory::method($v, null); self::$options['settings'][$k] = factory::model($method[0], true)->{$method[1]}(); } unset(self::$options['model']); } // push js format version to frontend if (!empty(self::$options['locale_override_class'])) { $locale_override_class = self::$options['locale_override_class']; $locale_override_class::js(); } }
public static function import_from_file_id($file_id, $model_class, $options = array()) { $result = array('success' => false, 'error' => array()); do { $file_name = time() . '_' . rand(10000, 99999) . '_' . rand(10000, 99999) . '_' . trim($_FILES[$file_id]['name']); $directory = application::get(array('directory', 'temp', 'dir')); $file_result = file::upload($file_id, $file_name, $directory, array_keys(self::$formats)); if (!$file_result['success']) { $result['error'] = array_merge($result['error'], $file_result['error']); break; } $import_result = self::import($file_result['file_name_full'], $model_class, $options); if ($import_result['error']) { array_merge3($result['error'], $import_result['error']); break; } $result['success'] = true; } while (0); return $result; }
/** * Constructing cache object * * @param string $cache_link * @param array $options */ public function __construct($cache_link) { $this->cache_link = $cache_link; $this->cache_key = application::get(['wildcard', 'keys', $cache_link, 'cache_key']); }
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'); } }
/** * Deploy application * * @param array $options * @return array */ public static function deploy($options = array()) { $result = array('success' => false, 'error' => array()); do { if (empty($options['mode'])) { $options['mode'] = 'code'; } $temp = rtrim(getcwd(), '/'); $deployed_dir = $temp . '/../../deployed'; $code_dir = $temp . '/../../code'; // for development we handle deployment differently, just symlink to the code if ($options['mode'] == 'code_dev') { if (file_exists($deployed_dir)) { shell_exec("rm -r {$deployed_dir}"); } symlink($code_dir, $deployed_dir); $result['success'] = true; break; } $all_deps_dir = $temp . '/../../deployments'; $time = time(); $dep_id = 'build.' . $time . '.' . rand(100, 999); $dep_dir = $all_deps_dir . '/' . $dep_id; $media_dir = $dep_dir . '/public_html/numbers'; if (mkdir($dep_dir, 0777) === false) { $result['error'][] = ' - unable to create new deployment directory ' . $dep_dir; break; } // copying code repository shell_exec("cp -r {$code_dir}/. {$dep_dir}"); // removing what we do not want to have $dels = array('.git', 'Makefile'); foreach ($dels as $v) { shell_exec("rm -r {$dep_dir}/{$v}"); } // js, css, scss, files here $files_to_copy = []; $process_extensions = ['js', 'css']; if (application::get('dep.submodule.numbers.frontend.media.scss')) { $process_extensions[] = 'scss'; } $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dep_dir)); foreach ($iterator as $filename => $cur) { $extension = $cur->getExtension(); if (in_array($extension, $process_extensions)) { $parent_dir_name = basename(dirname($filename)); if (strpos($filename, '/controller/') !== false) { $key = str_replace($dep_dir, '', $filename); $files_to_copy[$extension][$key] = $filename; } } } // create media directory $media_dir_full = $media_dir . '/media_generated'; if (!empty($files_to_copy['js']) || !empty($files_to_copy['css']) || !empty($files_to_copy['scss'])) { mkdir($media_dir_full, 0777); } // coping javescript files if (!empty($files_to_copy['js'])) { foreach ($files_to_copy['js'] as $k => $v) { $newname = ltrim(str_replace('/', '_', $k), '_'); shell_exec("cp -r {$v} {$media_dir_full}/{$newname}"); } } // coping css files if (!empty($files_to_copy['css'])) { foreach ($files_to_copy['css'] as $k => $v) { $newname = ltrim(str_replace('/', '_', $k), '_'); shell_exec("cp -r {$v} {$media_dir_full}/{$newname}"); } } // coping scss files if (!empty($files_to_copy['scss'])) { foreach ($files_to_copy['scss'] as $k => $v) { $newname = ltrim(str_replace('/', '_', $k), '_'); // processing scss files $temp = numbers_frontend_media_scss_base::serve($v); if ($temp['success']) { file_put_contents("{$media_dir_full}/{$newname}.css", $temp['data']); } } } // we need to load media from dependencies $result = system_dependencies::process_deps_all(['mode' => 'test']); // copying js, css & scss files $media_dir_submodule = $dep_dir . '/public_html'; if (!empty($result['data']['media'])) { mkdir($media_dir_submodule . '/numbers/media_submodules', 0777); foreach ($result['data']['media'] as $k => $v) { if (!in_array($k, ['js', 'css', 'scss'])) { continue; } foreach ($v as $k2 => $v2) { if (!isset($v2['origin']) || !isset($v2['destination'])) { continue; } // js and css we just copy $copy_from = $dep_dir . '/libraries/vendor' . $v2['origin']; $copy_to = $media_dir_submodule . $v2['destination']; if ($k == 'js' || $k == 'css') { shell_exec("cp -r {$copy_from} {$copy_to}"); } else { if ($k == 'scss' && application::get('dep.submodule.numbers.frontend.media.scss')) { // we need to process scss $temp = numbers_frontend_media_scss_base::serve($copy_from); if ($temp['success']) { file_put_contents($copy_to, $temp['data']); } } } } } } // setting permissions shell_exec("chmod -R 0777 {$dep_dir}"); // now we need to create a symlink if (file_exists($deployed_dir)) { shell_exec("rm -r {$deployed_dir}"); } symlink($dep_dir, $deployed_dir); // cleanup older deployments,older than 5 days $iterator = new DirectoryIterator($all_deps_dir); foreach ($iterator as $filedir => $fileinfo) { if ($fileinfo->isDir()) { $filename = $fileinfo->getFilename(); // sanity check if ($filename == $dep_id) { continue; } if (strpos($filename, 'build.') === 0) { if ($time - $fileinfo->getMTime() > 259200) { $temp = $fileinfo->getPathname(); shell_exec("rm -r {$temp}"); } } } } $result['success'] = true; } while (0); return $result; }
/** * Render debug toolbar * * @return string */ public static function render() { $loaded_classes = application::get(['application', 'loaded_classes']); self::$data['session'] = []; if (!empty($_SESSION)) { self::$data['session'] = [$_SESSION]; } $application = application::get(); $result = '<div class="container" dir="ltr">'; $result .= '<table cellpadding="2" cellspacing="2" width="100%">'; $result .= '<tr>'; $result .= '<td>'; $result .= '<table width="100%">'; $result .= '<tr>'; $result .= '<td nowrap> ' . html::a(['value' => 'Hide All', 'href' => 'javascript:void(0);', 'onclick' => "\$('.debuging_toolbar_class').hide();"]) . ' </td>'; foreach (self::$data as $k => $v) { if ($k == 'errors') { $count = count(error_base::$errors); } else { if ($k == 'classes') { $count = count($loaded_classes); } else { if ($k == 'application') { $count = count($application); } else { if ($k == 'phpinfo') { $count = 1; } else { $count = count($v); } } } } $result .= '<td nowrap> ' . html::a(['value' => ucwords($k) . ' (' . $count . ')', 'id' => "debuging_toolbar_{$k}_a", 'href' => 'javascript:void(0);', 'onclick' => "\$('#debuging_toolbar_{$k}').toggle();"]) . ' </td>'; } $result .= '<td width="50%" align="right">' . html::a(['href' => '/numbers/frontend/system/controller/dev', 'value' => 'Dev. Portal']) . '</td>'; $result .= '</tr>'; $result .= '</table>'; $result .= '</td>'; $result .= '</tr>'; // errors $result .= '<tr id="debuging_toolbar_errors" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>Errors (' . count(error_base::$errors) . ')</h3>'; $result .= '<table border="1" cellpadding="2" cellspacing="2" width="100%">'; foreach (error_base::$errors as $k => $v) { $result .= '<tr>'; $result .= '<td><b>' . error_base::$error_codes[$v['errno']] . ' (' . $v['errno'] . ') - ' . implode('<br/>', $v['error']) . '</b></td>'; $result .= '</tr>'; $result .= '<tr>'; $result .= '<td>File: ' . $v['file'] . ', Line: ' . $v['line'] . '</td>'; $result .= '</tr>'; $result .= '<tr>'; $result .= '<td><pre>' . $v['code'] . '</pre></td>'; $result .= '</tr>'; $result .= '<tr>'; $result .= '<td><pre>' . implode("\n", $v['backtrace']) . '</pre></td>'; $result .= '</tr>'; } $result .= '</table>'; $result .= '</td>'; $result .= '</tr>'; // suppressed $result .= '<tr id="debuging_toolbar_suppressed" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>Suppressed (' . count(self::$data['suppressed']) . ')</h3>'; $result .= '<table border="1" cellpadding="2" cellspacing="2" width="100%">'; foreach (self::$data['suppressed'] as $k => $v) { $result .= '<tr>'; $result .= '<td><b>' . error_base::$error_codes[$v['errno']] . ' (' . $v['errno'] . ') - ' . implode('<br/>', $v['error']) . '</b></td>'; $result .= '</tr>'; $result .= '<tr>'; $result .= '<td>File: ' . $v['file'] . ', Line: ' . $v['line'] . '</td>'; $result .= '</tr>'; $result .= '<tr>'; $result .= '<td><pre>' . $v['code'] . '</pre></td>'; $result .= '</tr>'; } $result .= '</table>'; $result .= '</td>'; $result .= '</tr>'; // javascript $result .= '<tr id="debuging_toolbar_js" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>Javascript Errors (' . count(self::$data['js']) . ')</h3>'; $result .= '<table border="1" cellpadding="2" cellspacing="2" width="100%">'; foreach (self::$data['js'] as $k => $v) { $result .= '<tr>'; $result .= '<td><b>' . implode('<br/>', $v['error']) . '</b></td>'; $result .= '</tr>'; $result .= '<tr>'; $result .= '<td>File: ' . $v['file'] . ', Line: ' . $v['line'] . '</td>'; $result .= '</tr>'; } $result .= '</table>'; $result .= '<div id="debuging_toolbar_js_data">'; $result .= ' '; $result .= '</div>'; $result .= '</td>'; $result .= '</tr>'; // benchmark first $result .= '<tr id="debuging_toolbar_benchmark" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>Benchmark (' . count(self::$data['benchmark']) . ')' . '</h3>'; $result .= '<table border="1" cellpadding="2" cellspacing="2" width="100%">'; $result .= '<tr>'; $result .= '<th>Name</th>'; $result .= '<th>Time</th>'; $result .= '<th>Start</th>'; $result .= '<th>Total</th>'; $result .= '<th>Memory</th>'; $result .= '</tr>'; foreach (self::$data['benchmark'] as $k => $v) { $result .= '<tr>'; $result .= '<td>' . $v['name'] . '</td>'; $result .= '<td align="right">' . $v['time'] . '</td>'; $result .= '<td align="right">' . $v['start'] . '</td>'; $result .= '<td align="right">' . $v['total'] . '</td>'; $result .= '<td align="right">' . format::memory($v['memory'], 'm') . '</td>'; $result .= '</tr>'; } $result .= '</table>'; $result .= '</td>'; $result .= '</tr>'; // sql $result .= '<tr id="debuging_toolbar_sql" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>Sql (' . count(self::$data['sql']) . ')' . '</h3>'; $result .= '<table border="1" cellpadding="2" cellspacing="2" width="100%">'; $result .= '<tr>'; $result .= '<th>Sql</th>'; $result .= '<th>Error</th>'; $result .= '<th>Errno</th>'; $result .= '<th>Num Rows</th>'; $result .= '<th>Affected Rows</th>'; //$result.= '<th>Rows</th>'; $result .= '<th>Key</th>'; $result .= '<th>Structure</th>'; $result .= '<th>Time</th>'; $result .= '</tr>'; foreach (self::$data['sql'] as $k => $v) { $temp = is_array($v['key']) ? implode('<br/>', $v['key']) : $v['key']; // header first $result .= '<tr>'; $result .= '<td valign="top"><pre style="width: 500px;">' . nl2br($v['sql']) . '</pre></td>'; $result .= '<td valign="top">' . implode('<br/>', $v['error']) . ' - ' . implode('<br/>', $v['error_original'] ?? []) . '</td>'; $result .= '<td valign="top">' . $v['errno'] . '</td>'; $result .= '<td valign="top">' . $v['num_rows'] . '</td>'; $result .= '<td valign="top">' . $v['affected_rows'] . '</td>'; //$result.= '<td valign="top">' . html::table(['options' => $v['rows']]) . '</td>'; $result .= '<td valign="top">' . $temp . '</td>'; $result .= '<td valign="top">' . html::table(['options' => $v['structure']]) . '</td>'; $result .= '<td valign="top">' . $v['time'] . '</td>'; $result .= '</tr>'; // results second if (!empty($v['rows'])) { $temp = array_keys(current($v['rows'])); $header = array_combine($temp, $temp); if (!empty($header)) { $result .= '<tr>'; $result .= '<td valign="top" colspan="8" style="max-width: 1000px; overflow: scroll;">' . html::table(['header' => $header, 'options' => $v['rows']]) . '</td>'; $result .= '</tr>'; } } } $result .= '</table>'; $result .= '</td>'; $result .= '</tr>'; // cache $result .= '<tr id="debuging_toolbar_cache" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>Cache (' . count(self::$data['cache']) . ')' . '</h3>'; $result .= '<table border="1" cellpadding="2" cellspacing="2" width="100%">'; $result .= '<tr>'; $result .= '<th>Type</th>'; $result .= '<th>Link</th>'; $result .= '<th>Cache #</th>'; $result .= '<th>Has Data</th>'; $result .= '</tr>'; foreach (self::$data['cache'] as $k => $v) { $result .= '<tr>'; $result .= '<td valign="top">' . $v['type'] . '</td>'; $result .= '<td valign="top">' . $v['link'] . '</td>'; $result .= '<td valign="top">' . $v['cache_id'] . '</td>'; $result .= '<td valign="top">' . ($v['have_data'] ? 'Yes' : 'No') . '</td>'; $result .= '</tr>'; } $result .= '</table>'; $result .= '</td>'; $result .= '</tr>'; // dump $result .= '<tr id="debuging_toolbar_dump" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>Dump (' . count(self::$data['dump']) . ')' . '</h3>'; $result .= '<table border="1" cellpadding="2" cellspacing="2" width="100%">'; $result .= '<tr>'; $result .= '<th>Name</th>'; $result .= '<th>Dump</th>'; $result .= '</tr>'; foreach (self::$data['dump'] as $k => $v) { $result .= '<tr>'; $result .= '<td valign="top">' . $v['name'] . '</td>'; $result .= '<td valign="top"><pre>' . print_r($v['value'], true) . '</pre></td>'; $result .= '</tr>'; } $result .= '</table>'; $result .= '</td>'; $result .= '</tr>'; // input $result .= '<tr id="debuging_toolbar_input" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>Input (' . count(self::$data['input']) . ')' . '</h3>'; $result .= '<table border="1" cellpadding="2" cellspacing="2" width="100%">'; $result .= '<tr>'; $result .= '<th>Input</th>'; $result .= '</tr>'; foreach (self::$data['input'] as $k => $v) { $result .= '<tr>'; $result .= '<td valign="top"><pre>' . print_r($v, true) . '</pre></td>'; $result .= '</tr>'; } $result .= '</table>'; $result .= '</td>'; $result .= '</tr>'; // session $result .= '<tr id="debuging_toolbar_session" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>Session (' . count(self::$data['session']) . ')' . '</h3>'; $result .= '<table border="1" cellpadding="2" cellspacing="2" width="100%">'; $result .= '<tr>'; $result .= '<th>Session</th>'; $result .= '</tr>'; foreach (self::$data['session'] as $k => $v) { $result .= '<tr>'; $result .= '<td valign="top"><pre>' . print_r($v, true) . '</pre></td>'; $result .= '</tr>'; } $result .= '</table>'; $result .= '</td>'; $result .= '</tr>'; // autoloaded classes $result .= '<tr id="debuging_toolbar_classes" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>Loaded Classes (' . count($loaded_classes) . ')</h3>'; $result .= '<table border="1" cellpadding="2" cellspacing="2" width="100%">'; $result .= '<tr>'; $result .= '<th>Class Name</th>'; $result .= '<th>File</th>'; $result .= '<th>Media</th>'; $result .= '</tr>'; foreach ($loaded_classes as $k => $v) { $result .= '<tr>'; $result .= '<td><b>' . $v['class'] . '</b></td>'; $result .= '<td>' . $v['file'] . '</td>'; $result .= '<td>' . html::table(['options' => $v['media']]) . '</td>'; $result .= '</tr>'; } $result .= '</table>'; $result .= '</td>'; $result .= '</tr>'; // application $result .= '<tr id="debuging_toolbar_application" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>Application (' . count($application) . ')</h3>'; $result .= print_r2($application, true); $result .= '</td>'; $result .= '</tr>'; // phpinfo $result .= '<tr id="debuging_toolbar_phpinfo" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>PHPInfo</h3>'; helper_ob::start(); phpinfo(); $str = helper_ob::clean(); $str = preg_replace('%^.*<body>(.*)</body>.*$%ms', '$1', $str); $str .= <<<TTT \t\t\t\t\t\t\t<style type="text/css"> \t\t\t\t\t\t\t\t#phpinfo table { \t\t\t\t\t\t\t\t\tborder: 1px solid #000; \t\t\t\t\t\t\t\t} \t\t\t\t\t\t\t\t#phpinfo table tr { \t\t\t\t\t\t\t\t\tborder-bottom: 1px solid #000; \t\t\t\t\t\t\t\t} \t\t\t\t\t\t\t</style> TTT; $result .= '<div id="phpinfo">' . $str . '</div>'; $result .= '</td>'; $result .= '</tr>'; // acls $result .= '<tr id="debuging_toolbar_acls" class="debuging_toolbar_class" style="display: none;">'; $result .= '<td>'; $result .= '<h3>Acls (' . count(debug::$data['acls']) . ')</h3>'; $result .= print_r2(debug::$data['acls'], true); $result .= '</td>'; $result .= '</tr>'; $result .= '</table>'; $result .= '</div>'; return $result; }
/** * 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; }
/** * @see html::grid() */ public static function grid($options = []) { $rtl = i18n::rtl(); $grid_columns = application::get('flag.numbers.framework.html.options.grid_columns') ?? 12; $rows = isset($options['options']) ? $options['options'] : []; unset($options['options']); $result = ''; foreach ($rows as $k => $v) { // we need to determine field sizes $field_sizes = []; foreach ($v as $k2 => $v2) { foreach ($v2 as $k3 => $v3) { $field_sizes[] = $v3['options']['percent'] ?? null; } } $field_new_sizes = html::percentage_to_grid_columns($field_sizes); // count number of fields $count_fields = count($v); //$count_class = html::number_to_word($count_fields); // find all row classes $row_class = ''; foreach ($v as $k2 => $v2) { foreach ($v2 as $k3 => $v3) { if (!empty($v3['row_class'])) { $row_class .= ' ' . $v3['row_class']; } } } $result .= '<div class="row' . $row_class . '">'; // we need to determine if we have label in the row $flag_have_label = false; foreach ($v as $k2 => $v2) { foreach ($v2 as $k3 => $v3) { if (($v3['label'] ?? '') . '' != '') { $flag_have_label = true; } } } // we need to fill up empty columns if rtl if ($rtl) { $index = 0; $current_grid_columns = 0; foreach ($v as $k2 => $v2) { foreach ($v2 as $k3 => $v3) { // if we are mannually set field sizes we skip if (!empty($v3['options']['field_size'])) { $current_grid_columns = 12; break; } $current_grid_columns += $field_new_sizes['data'][$index]; $v[$k2][$k3]['options']['field_size'] = 'col-sm-' . $field_new_sizes['data'][$index]; // a must $index++; } } if ($current_grid_columns != $grid_columns) { $v['__empty_column_fill__']['__empty_column_fill__'] = ['value' => ' ']; $field_new_sizes['data'][$index] = $grid_columns - $current_grid_columns; } $v = array_reverse($v, true); } // loop though each field and render it $index = 0; foreach ($v as $k2 => $v2) { $flag_first_field = true; if ($rtl) { $v2 = array_reverse($v2, true); } foreach ($v2 as $k3 => $v3) { $error_class = ''; if (!empty($v3['error']['type'])) { if ($v3['error']['type'] == 'danger') { $v3['error']['type'] = 'error'; } $error_class = 'has-' . $v3['error']['type']; } // style $style = ''; if (isset($v3['options']['style'])) { $style = ' style="' . $v3['options']['style'] . '"'; } $field_size = $v3['options']['field_size'] ?? 'col-sm-' . $field_new_sizes['data'][$index]; $class = $v3['class'] ?? ''; $result .= '<div class="' . $field_size . ' form-group ' . $error_class . ' ' . $class . '"' . $style . '>'; // label if ($flag_first_field) { if (($v3['label'] ?? '') . '' != '') { $result .= $v3['label']; } else { if ($flag_have_label) { $result .= '<label> </label>'; } } $flag_first_field = false; } else { if ($flag_have_label) { $result .= '<label> </label>'; } } $result .= $v3['value'] ?? ''; // error messages if (!empty($v3['error']['message'])) { $result .= $v3['error']['message']; } // description after error message if (!empty($v3['description'])) { $result .= html::text(['type' => 'muted', 'value' => $v3['description']]); } $result .= '</div>'; $index++; } } $result .= '</div>'; } return '<div class="container-fluid">' . $result . '</div>'; }
/** * Title * * @return string */ public static function title() { return application::get(['controller', 'title']); }
public function action_index() { echo application::get('environment'); echo "<h3>This is index controller</h3>"; }
/** * 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%"> </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%"> </td>'; $temp .= '<td width="90%">' . $value . '</td>'; $temp .= '<td width="1%"> </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%"> </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%"> </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; }
/** * Destroy everything */ public static function destroy() { $__run_only_bootstrap = application::get(['flag', 'global', '__run_only_bootstrap']); // we need to set working directory again chdir(application::get(['application', 'path_full'])); // error processing if (empty(error_base::$flag_error_already)) { $last_error = error_get_last(); $flag_render = false; if (in_array($last_error['type'], [E_COMPILE_ERROR, E_PARSE, E_ERROR])) { error_base::error_handler($last_error['type'], $last_error['message'], $last_error['file'], $last_error['line']); error_base::$flag_error_already = true; $flag_render = true; } if ($flag_render || error_base::$flag_exception) { error_base::$flag_error_already = true; if ($__run_only_bootstrap) { helper_ob::clean_all(); print_r(error_base::$errors); } else { // set mvc + process application::set_mvc('/error/_error/500'); application::process(); } } } // write sessions session_write_close(); // final benchmark if (debug::$debug) { debug::benchmark('application end'); } // debugging toolbar last if (debug::$toolbar && !$__run_only_bootstrap) { echo str_replace('<!-- [numbers: debug toolbar] -->', debug::render(), helper_ob::clean()); } // flush data to client flush(); // closing caches before db $cache = factory::get(['cache']); if (!empty($cache)) { foreach ($cache as $k => $v) { $object = $v['object']; if (!empty(cache::$reset_caches[$k])) { $object->gc(1, cache::$reset_caches[$k]); } $object->close(); } } // destroy i18n if (i18n::$initialized) { i18n::destroy(); } // close db connections $dbs = factory::get(['db']); if (!empty($dbs)) { foreach ($dbs as $k => $v) { $object = $v['object']; $object->close(); } } // emails with erros if (debug::$debug && !empty(debug::$email)) { debug::send_errors_to_admin(); } }
/** * 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; }