public static function getView() { global $start_microtime; $tt = microtime(1) - $start_microtime; $db_tt = 0; foreach (self::$db_queries as $db_query) { $db_tt += $db_query['time']; } $so_queris = count(self::$db_queries); $base_dir_l = strlen(rtrim(DIR_BASE, '/')); $inc_f = array(); foreach (get_included_files() as $v) { $inc_f[] = substr($v, $base_dir_l); } $def_c = get_defined_constants(true); $def_c = $def_c['user']; if (isset($def_c['CFG_DB_LOGIN'])) { $def_c['CFG_DB_LOGIN'] = '******'; } if (isset($def_c['CFG_DB_PASSWORD'])) { $def_c['CFG_DB_PASSWORD'] = '******'; } if (isset($def_c['CFG_DB_NAME'])) { $def_c['CFG_DB_NAME'] = '***'; } if (isset($def_c['CFG_DB_SERVER'])) { $def_c['CFG_DB_SERVER'] = '***'; } foreach ($def_c as $k => $v) { $def_c[$k] = $k . '=' . $v; } $data = array('total' => round($tt, 4), 'php' => round($tt - $db_tt, 4), 'db' => round($db_tt, 4), 'so_queries' => $so_queris, 'memory_peak' => round(memory_get_peak_usage() / 1024), 'memory_current' => round(memory_get_usage() / 1024), 'queries' => self::$db_queries, 'included_files' => $inc_f, 'defined_constants' => $def_c); // Generate unique UID $uid = UID::uid32(); while (Cacher::getInstance()->getDefaultCacher()->get('debug_panel_' . $uid)) { $uid = UID::uid32(); } Cacher::getInstance()->getDefaultCacher()->set('debug_panel' . $uid, $data, 3600); ?> <script> $.ajax({ url: '/-/<?php echo CFG_AJAX_ROUTE; ?> /debug_panel?uid=<?php echo $uid; ?> ', success: function (data) { $('body').append(data); } }); </script> <?php }
/** * Updates files from composer */ public function updateComposerVendors() { chdir(DIR_BASE); exec('COMPOSER_HOME="' . substr(DIR_BASE, 0, -1) . '" php composer.phar -v update 2>&1', $out); if ($out) { $this->result_message[] = $out; } // Clear all caches - may be required to show fresh data Cacher::getInstance()->clearAllCaches(); return $this; }
public static function addNewFeedback(array $data, $need_to_save_in_db = true, $send_to_emails = [], $files = []) { $send_to_emails = (array) $send_to_emails; $cacher = Cacher::getInstance()->getDefaultCacher(); $cache_key = 'module_feedback_add_new_feedback_last_send_ts' . VISITOR_HASH; // Check message is not sent too quick $last_sent_ts = $cacher->get($cache_key); if (NOW - $last_sent_ts < self::$sending_period_seconds) { return false; } // Autocreate db $feedbacks = new FeedbackRepository(); $feedback = NULL; // Save to Db if ($need_to_save_in_db) { $feedback = new Feedback(); $feedback->loadDataFromArray($data); $feedback->save(); } // Send email to manager if ($send_to_emails) { $msg = '<table><tr><th>Field</th><th>Value</th></tr>'; foreach ($data as $k => $v) { if ($v) { $msg .= '<tr><td>' . $k . '</td><td>' . htmlspecialchars($v) . '</td></tr>'; } } $msg .= '</table>'; $mailer = Mailer::getInstance()->setSubject('New feedback from ' . CFG_DOMAIN)->setSender(Settings::getCommonEmail())->setMessage($msg); foreach ($send_to_emails as $email) { $mailer->setRecipient($email); } foreach ($files as $file) { $mailer->addAttachment($file); } $mailer->send(); } // Save last send ts $cacher->set($cache_key, NOW); return $feedback; }
/** * @return array|mixed */ private function _select() { if (self::$cache) { $data = Cacher::getInstance()->getDefaultCacher()->get('sql_parser' . md5($this->sql)); if ($data) { $this->res = unserialize($data); return $this->res; } } $pos = 0; $str_matched = []; $patient = $this->sql; for ($i = 0, $so = count(self::$str_select); $i < $so; $i++) { $str =& self::$str_select[$i]; if (isset($str['depends']) && $str['depends'] && !$str_matched[$str['depends']]) { continue; } switch ($str['type']) { case 'word': $pos = self::_parserCheckFragment($patient, $str['word']); if ($pos === false && $str['obligatory']) { trigger_error('Required fragment "' . $str['word'] . '" not found.'); } break; case 'word_variations': $found = 0; foreach ($str['variations'] as &$v) { $pos = self::_parserCheckFragment($patient, $v); if ($pos !== false) { $found = 1; break; } } if (!$found && $str['obligatory']) { trigger_error('Required fragment "' . implode(', ', $str['variations']) . '" not found.'); } unset($v, $found); break; case 'expression': $variations = []; if (isset($str['go_to'])) { $next_o =& self::$str_select[$str['go_to']]; switch ($next_o['type']) { case 'word': $variations[] = $next_o['word']; break; case 'word_variations': $variations = $next_o['variations']; break; default: exit('Internal error. Invalid type in element "' . $next_o . '". Expression should be always followed by "word" or "word_variations" type or be the last in structure.'); } unset($next_o); } $next = $i + 1; if (isset(self::$str_select[$next])) { $next_o =& self::$str_select[$next]; switch ($next_o['type']) { case 'word': case 'word_variations': $variations = array_merge($variations, $this->_makeStopWordsVariations($i)); break; default: exit('Internal error. Invalid type in element "' . $next . '". Expression should be always followed by "word" or "word_variations" type or be the last in structure.'); } unset($next_o); } $pos = self::_parserPrepareExpression($patient, $variations ? array_unique($variations) : NULL); unset($next); break; default: exit('Internal error. Unknown structure type "' . $str['type'] . '".'); } //order_conditions if (ctype_digit((string) $pos)) { if (isset($str['desc']) && !isset($this->res[$str['desc']])) { $this->res[$str['desc']] = []; } $fragment = substr($patient, 0, $pos); if (isset($str['desc']) && ($str['desc'] === 'join_conditions' || $str['desc'] === 'where_conditions')) { $this->res[$str['desc']][] = new SQLWhereParser($fragment); } elseif (isset($str['desc']) && $str['desc'] === 'limit_conditions') { $this->res[$str['desc']][] = new SQLLimitParser($fragment); } elseif (isset($str['desc'])) { $this->res[$str['desc']][] = $fragment; } $patient = substr($patient, $pos); $str_matched[$i] = 1; unset($fragment); } else { $str_matched[$i] = 0; } // WTF // $patient = substr($patient, self::_skipShittySymbols($patient)); // echo '<span style="color:', (ctype_digit((string)$pos) ? 'green' : 'red') ,'">', $str['type']; // switch ($str['type']) { // case 'word': echo ' "', $str['word'] ,'"'; break; // case 'word_variations': echo ' "', implode(', ', $str['variations']) ,'"'; break; // } // echo '<br><small><i>', // $str['desc'] ,'</i></small><br><b>', $fragment ,'</b> ', // $patient ,'<br><small>', (microtime(1) - $step_ts) ,'</small></span><hr>'; if (isset($str['go_to'])) { $i = $str['go_to'] - 1; // echo 'Going to ', $i ,'<hr>'; } } if (!isset($this->res['flags'])) { $this->res['flags'] = []; } if (!in_array('LIMIT', $this->res['sql'])) { $this->res['sql'][] = 'LIMIT'; $this->res['limit_conditions'] = [new SQLLimitParser('')]; } if (self::$cache) { Cacher::getInstance()->getDefaultCacher()->set('sql_parser' . md5($this->sql), serialize($this->res)); } return $this->res; }
/** * Show all columns in table * @param string $tbl - table name * @return array - list */ public static function getFields($tbl) { if (Settings::isCacheEnabled()) { $cache_key = 'db_table_columns_' . $tbl; $cacher = Cacher::getInstance()->getDefaultCacher(); if (!isset(self::$_cached_tbl_columns[$tbl])) { self::$_cached_tbl_columns[$tbl] = $cacher->get($cache_key); } } if (isset(self::$_cached_tbl_columns[$tbl])) { return self::$_cached_tbl_columns[$tbl]; } $res = []; $sql = self::getInstance()->sql_query("SHOW COLUMNS FROM `{$tbl}`"); while ($q = $sql->fetch(PDO::FETCH_NUM)) { $res[] = $q[0]; } if (Settings::isCacheEnabled()) { $cacher->set($cache_key, $res, 86400); } return self::$_cached_tbl_columns[$tbl] = $res; }
/** * Print processed page template with all data * @return string */ public function __toString() { // If content is is rendered from cache if (Settings::isCacheEnabled() && $this->cached_page_html) { return $this->cached_page_html; } // Using clickmap script for client click tracking if (Settings::get('clickmap')) { // Show map on page if (isset($_GET['cms_view_clickmap'])) { // Load script to show clickmap container PageTail::getInstance()->addJsUrl('clickmap_frontend.js'); PageHead::getInstance()->addJs('cms_page_id = ' . PAGE_ID); } else { // Just saving clicks - request scripts for registering clicks PageTail::getInstance()->addJsUrl('clickmap_register.js'); PageHead::getInstance()->addJs('cms_page_id = ' . PAGE_ID); } } // Require js for Visual editor if (VisualEdit::getInstance()->isEnabled()) { PageHead::getInstance()->addJsUrl('visual_edit.js'); PageHead::getInstance()->addJs('cms_page_id = "' . PAGE_ID . '"'); } // Render HTML ob_start(); // Static page from file if ($this->use_html_file_without_parse) { echo $this->html; } else { // Parse content // Hide e-mails from bots if (strpos($this->html, '@') !== false && preg_match_all('`\\<a([^>]+)href\\=\\"mailto\\:([^">]+)\\"([^>]*)\\>(.+)\\<\\/a\\>`ismU', $this->html, $matches)) { PageHead::getInstance()->addJsUrl('email_rewrite.js'); $matches[5] = []; // Replace emails in content with script calls foreach ($matches[0] as $k => $v) { // No email? if (isset($matches[5][$v])) { continue; } // No @ symbol? $s = explode('@', $matches[2][$k]); if (count($s) !== 2) { continue; } // No zone? $domain1 = explode('.', $s[1]); $s = $s[0]; if (count($domain1) < 2) { continue; } // Now can replace $domain0 = array_pop($domain1); $s = '<script>rewem2nortex("' . preg_replace('/\\sclass=\\"(.+)\\"/', '\\1', str_replace('"', '\'', $matches[3][$k])) . '","' . $s . '","' . implode('.', $domain1) . '","' . $domain0 . '"'; if ($matches[2][$k] !== $matches[4][$k]) { $s .= ',"' . trim(str_replace(['@', '.'], ['"+"@"+"', '"+"."+"'], preg_replace('`\\<([a-z])`', '<"+"\\1', str_replace('"', '\\"', $matches[4][$k])))) . '"'; } $s .= ');</script>'; $matches[5][$v] = $s; } $matches = $matches[5]; // Replace found emails with scripts in content $this->html = str_replace(array_keys($matches), $matches, $this->html); } // For developers using git - site version from latest git commit, add to last meta tag if (function_exists('exec')) { $output = []; exec('git log -1 --pretty=format:\'%h (%ci)\' --abbrev-commit', $output); if ($output && isset($output[0])) { PageHead::getInstance()->addMeta($output[0], 'X-Version'); } } // Page with components itself $this->outputHead(); // Put body tag if not found in template if (!strpos($this->html, '<body')) { // No trailing bracket ! may have class $classes = PageHead::getInstance()->getBodyCssClasses(); echo '<body' . ($classes ? ' class="' . implode(' ', $classes) . '"' : '') . '>'; } // Main page content $this->outputHtml(); // Post-scripts $this->outputTail(); // Put closing body tag if not found in template if (!strpos($this->html, '</body>')) { echo '</body>'; } echo '</html>'; } $html = ob_get_clean(); // HTML optimization in rendered content if (Settings::get('optimize_html')) { $html = Optimize::HTML($html); } // Put in cache if (Settings::get('use_file_cache_for_all_pages') && Settings::isCacheEnabled()) { Cacher::getInstance()->getDefaultCacher()->set('html_' . PATH_INTERNAL_MD5, $html); } // Encode ff browser supports gzip if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) { $html = gzencode($html, 6); // 6 is ok with speed and compression rate header('Content-Encoding: gzip'); } // Set cache headers for one hour if (Settings::isCacheEnabled() && !headers_sent()) { header("Cache-Control: max-age=2592000"); header('Expires: ' . gmdate('D, d M Y H:i:s \\G\\M\\T', time() + 3600)); } return $html; }
/** * Get Setting object * @param string $module * @param string $key * @return CustomSetting */ public static function getCustomSetting($module, $key) { // Check cache if (Settings::isCacheEnabled()) { $cache_key = 'module_custom_settings_all'; $cacher = Cacher::getInstance()->getDefaultCacher(); if (!self::$cached_settings) { self::$cached_settings = $cacher->get($cache_key); } } if (!self::$cached_settings) { // To prevent more iterations self::$cached_settings['empty']['empty'] = ''; $settings = new CustomSettingRepository(); foreach ($settings->getAsArrayOfObjects() as $setting) { /** @var CustomSetting $setting */ self::$cached_settings[$setting->getModule()][$setting->getKey()] = $setting; } } // Save cache if (Settings::isCacheEnabled()) { $cacher->set($cache_key, self::$cached_settings, 86400); } return isset(self::$cached_settings[$module][$key]) ? self::$cached_settings[$module][$key] : NULL; }
<?php use TMCms\Cache\Cacher; if (!isset($_GET['uid']) || strlen($_GET['uid']) !== 32) { return; } $data = Cacher::getInstance()->getDefaultCacher()->get('debug_panel' . $_GET['uid']); if (!$data) { return; } $trace = '<table>'; foreach ($data['queries'] as $query_data) { $q = $query_data['query']; $trace .= '<tr><td colspan="3"><br><br>' . $query_data['backtrace'][0]['args'][0] . '<br><br></td></tr>'; foreach ($query_data['backtrace'] as $tr) { if (!isset($tr['file'])) { $tr['file'] = ''; } if (!isset($tr['line'])) { $tr['line'] = ''; } if (!isset($tr['function'])) { $tr['function'] = ''; } $trace .= '<tr><td>' . substr($tr['file'], strlen(DIR_BASE) - 1) . '</td><td>' . $tr['line'] . '</td><td>' . $tr['function'] . '</td></tr>'; } } $trace .= '</table>'; ob_start(); ?>
<?php defined('INC') or exit; use TMCms\Admin\Messages; use TMCms\Cache\Cacher; use TMCms\Config\Configuration; use TMCms\Log\App; use TMCms\Network\Mailer; Mailer::getInstance()->setSubject('Message from ' . Configuration::getInstance()->get('site')['name'] . ' (' . CFG_DOMAIN . ')')->setSender(Configuration::getInstance()->get('site')['email'], Configuration::getInstance()->get('site')['name'])->setRecipient(CMS_SUPPORT_EMAIL, CMS_NAME)->setMessage($_POST['message'])->send(); Cacher::getInstance()->getDefaultCacher()->set('cms_home_support_email', NOW); App::add('Message sent to developers'); Messages::sendGreenAlert('Message sent to developers'); back();
/** * @param bool $skip_objects_creation - true if no need to create objects * @param bool $skip_changed_fields - skip update of changed fields * @return $this */ protected function collectObjects($skip_objects_creation = false, $skip_changed_fields = false) { $sql = $this->getSelectSql(); if ($this->last_used_sql && $sql === $this->last_used_sql) { // Skip queries - nothing changed return $this; } $this->last_used_sql = $sql; // Check cache for this exact collection if ($this->use_cache) { //Check cached values, set local properties $data = Cacher::getInstance()->getDefaultCacher()->get($this->getCacheKey($sql)); if ($data && is_array($data) && isset($data['collected_objects_data'], $data['collected_objects'])) { // Set local data $this->collected_objects_data = $data['collected_objects_data']; $this->collected_objects = $data['collected_objects']; // No further actions return $this; } } // Use Iterator in DB query if ($this->use_iterator) { $this->collected_objects_data = SQL::q_assoc_iterator($sql, false); } else { $this->collected_objects_data = SQL::q_assoc($sql, false); } if ($this->require_to_count_total_rows) { $this->total_count_rows = q_value('SELECT FOUND_ROWS();'); } $this->collected_objects = []; // Reset objects if (!$skip_objects_creation) { // Need to create objects from array data foreach ($this->collected_objects_data as $v) { $class = $this->getObjectClass(); /** @var Entity $obj */ $obj = new $class(); // Prevent auto-query db, skip tables with no id field $id = $v['id']; unset($v['id']); // Set object data $obj->loadDataFromArray($v, $skip_changed_fields); // Set current ID $obj->setId($id, false); // Save in returning array ob objects $this->collected_objects[] = $obj; } } if ($this->use_cache) { // Save all collected data to Cache $data = ['collected_objects_data' => $this->collected_objects_data, 'collected_objects' => $this->collected_objects]; Cacher::getInstance()->getDefaultCacher()->set($this->getCacheKey($sql), $data, $this->cache_ttl); } return $this; }
/** * Removes setting by prefix, e.g. m_gallery_... * @param string $prefix * @param bool $skip_modules * @return \PDOStatement */ public function clear($prefix = '', $skip_modules = false) { // Delete from database $settings_collection = new SettingEntityRepository(); if ($prefix) { $settings_collection->setWherePrefix($prefix); } if ($skip_modules) { $settings_collection->setSkipModules(); } $settings_collection->deleteObjectCollection(); // Clear cache Cacher::getInstance()->getDefaultCacher()->delete(self::CACHE_KEY); return true; }