Вход Регистрация
Файл: system/core/core.php
Строк: 1038
<?php

class cmsCore {

    private static 
$instance;

    public 
$uri            = '';
    public 
$uri_before_remap = '';
    public 
$uri_absolute   = '';
    public 
$uri_controller = '';
    public 
$uri_controller_before_remap = '';
    public 
$uri_action     = '';
    public 
$uri_params     = [];
    public 
$uri_query      = [];
    private 
$matched_pages = null;
    private 
$widgets_pages = null;

    private static 
$language = 'ru';
    private static 
$language_href_prefix = '';
    private static 
$core_version = null;
    private static 
$controllers_instance = [];
    private static 
$templates = null;

    public 
$controller = '';
    private 
$defined_controllers = [];

    public 
$link;
    public 
$request;

    public 
$db;

    private static 
$includedFiles = [];

    public static function 
getInstance() {
        if (
self::$instance === null) {
            
self::$instance = new self;
        }
        return 
self::$instance;
    }

    public function 
__construct(){

        
$this->request = new cmsRequest($_REQUEST);

        
self::detectLanguage();

    }

    
/*
     * deprecated, use cmsDebugging
     */
    
private static $start_time;
    public static function 
startTimer() {
        
self::$start_time = microtime(true);
    }
    public static function 
getTime() {
        return 
microtime(true) - self::$start_time;
    }

//============================================================================//
//============================================================================//

    
private static function detectLanguage() {

        
$config = cmsConfig::getInstance();

        
self::$language = $config->language;

        if(!empty(
$_SERVER['REQUEST_URI']) && !empty($config->is_user_change_lang)){

            
$segments = explode('/', mb_substr($_SERVER['REQUEST_URI'], mb_strlen($config->root)));

            
// язык может быть только двухбуквенный, определяем его по первому сегменту
            
if (!empty($segments[0]) && preg_match('/^[a-z]{2}$/i', $segments[0])) {
                if(
is_dir($config->root_path.'system/languages/'.$segments[0].'/')){
                    
// язык по умолчанию без префиксов, дубли нам не нужны
                    
if($segments[0] != $config->language){

                        
// включаем для моделей поддержку
                        
cmsModel::globalLocalizedOn();

                        
self::$language = self::$language_href_prefix = $segments[0]; unset($segments[0]);

                        
$_SERVER['REQUEST_URI'] = $config->root.implode('/', $segments);

                    }
                }
            }

        }

    }

    public static function 
getLanguageHrefPrefix() {
        return 
self::$language_href_prefix;
    }

    public static function 
getLanguageName() {
        return 
self::$language;
    }

    public static function 
changeLanguage($new_lang){
        
self::$language = $new_lang;
    }

//============================================================================//
//============================================================================//

    /**
     * Возвращает информацию о версии CMS
     * в виде строки
     * @param boolean $show_date Показывать дату версии
     * @return string
     */
    
public static function getVersion($show_date = false){

        
$version = self::getVersionArray();

        if (!
$show_date && isset($version['date'])) { unset($version['date']); }

        return 
$version['version'].($show_date ? ' '.LANG_FROM.' '.$version['date'] : '');

    }

    
/**
     * Возвращает информацию о версии CMS
     * в виде массива с ключами:
     *  - date Дата релиза
     *  - version Полная версия CMS
     *  - raw
     *  -- major
     *  -- minor
     *  -- build
     *  -- date
     * @return array
     */
    
public static function getVersionArray(){

        if(
self::$core_version === null){

            
$file = cmsConfig::get('root_path') . 'system/config/version.ini';
            if (!
is_readable($file)){ die('system/config/version.ini not found'); }

            
$version = parse_ini_file($file);

            
self::$core_version = array(
                
'date'    => $version['date'],
                
'version' => $version['major'] .'.'. $version['minor'] .'.'. $version['build'],
                
'raw'     => $version
            
);

        }

        return 
self::$core_version;

    }

//============================================================================//
//============================================================================//

    
public static function isWritable($path, $is_force_mkdir=true) {

        if (
$is_force_mkdir && (!file_exists($path))) { @mkdir($path); }

        return (
is_writable($path));

    }

//============================================================================//
//============================================================================//

    /**
     * Подключает файл
     * @param string $file Путь относительно корня сайта без начального слеша
     * @return mixed
     */
    
public static function includeFile($file) {

        
$file = cmsConfig::get('root_path') . $file;

        if (isset(
self::$includedFiles[$file])) {
            return 
self::$includedFiles[$file];
        }

        if (!
is_readable($file)) {
            
self::$includedFiles[$file] = false;
            return 
false;
        }

        
$result = include_once $file;

        if (
is_null($result)) {
            
$result = true;
        }

        
self::$includedFiles[$file] = $result;

        return 
$result;
    }

    public static function 
requireFile($file) {

        
$file = cmsConfig::get('root_path') . $file;

        if (!
is_readable($file)) {
            return 
false;
        }

        
$result = require $file;

        if (
is_null($result)) {
            
$result = true;
        }

        return 
$result;
    }

    public static function 
includeAndCall($file, $function_name, $params = []) {

        if (!
self::includeFile($file)) {
            return 
false;
        }

        if (!
function_exists($function_name)) {
            return 
false;
        }

        return 
call_user_func_array($function_name, $params);
    }

//============================================================================//
//============================================================================//

    /**
     * Загружает внешнюю библиотеку из папки /system/libs
     *
     * @param string $library Название библиотеки в /system/libs (без расширения)
     * @param string $class Название загружаемого класса (для предотвращения повторной загрузки)
     */
     
public static function loadLib($library, $class=false){

        if (
$class && class_exists($class, false)){ return true; }

        
$lib_file = cmsConfig::get('root_path').'system/libs/'.$library.'.php';

        if (!
is_readable($lib_file)){ self::error(ERR_LIBRARY_NOT_FOUND . ': '. $library); }

        include_once 
$lib_file;

        return 
true;

    }

//============================================================================//
//============================================================================//

    /**
     * Загружает класс ядра из папки /system/core
     * @param string $class
     */
    
public static function loadCoreClass($class){

        
$class_file = cmsConfig::get('root_path') . 'system/core/'.$class.'.class.php';

        if (!
is_readable($class_file)){
            
self::error(ERR_CLASS_NOT_FOUND . ': '. $class);
        }

        include_once 
$class_file;

        return 
true;

    }

//============================================================================//
//============================================================================//

    /**
     * Проверяет существование модели
     * @param str $controller Название контроллера
     * @return bool
     */
    
public static function isModelExists($controller){

        
$model_file = cmsConfig::get('root_path').'system/controllers/'.$controller.'/model.php';

        return 
file_exists($model_file);

    }

    
/**
     * Возвращает объект модели из указанного файла (без расширения)
     * @param string $controller Контроллер модели
     * @param string $delimitter Разделитель слов в названии класса
     */
    
public static function getModel($controller, $delimitter='_'){

        if(
is_array($controller)){
            
$controller = end($controller);
        }

        
$model_class = 'model' . string_to_camel($delimitter, $controller);

        try {
            
$model = new $model_class();
        } catch (
Exception $e) {
            
self::error(ERR_MODEL_NOT_FOUND . ': '.$e->getMessage());
        } finally {
            return isset(
$model) ? $model : null;
        }
    }

    
/**
     * @deprecated
     *
     * С версии 2.14.0 работает в autoLoad
     * Инклюдит файл модели контроллера (контроллеров)
     * @param string $controllers Контроллер модели или массив контроллеров
     * @param boolean $quiet
     * @return boolean
     */
    
public static function includeModel($controllers, $quiet = false) {
        return 
true;
    }


//============================================================================//
//============================================================================//

    /**
     * Проверяет существования контроллера
     * @param string $controller_name
     * @return bool
     */
    
public static function isControllerExists($controller_name){
        return 
is_dir(cmsConfig::get('root_path').'system/controllers/'.$controller_name);
    }

    
/**
     * Создает и возвращает объект контроллера
     * @param string $controller_name
     * @param cmsRequest $request
     * @return controller_class
     */
    
public static function getController($controller_name, $request = null){

        if (!
$request) { $request = new cmsRequest([], cmsRequest::CTX_INTERNAL); }

        
$config = cmsConfig::getInstance();

        
$ctrl_file = $config->root_path . 'system/controllers/'.$controller_name.'/frontend.php';

        if (!
class_exists($controller_name, false)) {
            if(!
is_readable($ctrl_file)){
                if(
$request->isStandard()){
                    return 
self::error404();
                }
                return 
self::error(ERR_COMPONENT_NOT_FOUND . ': '. str_replace($config->root_path, '', $ctrl_file));
            }
            include_once(
$ctrl_file);
        }

        
$custom_file = $config->root_path . 'system/controllers/'.$controller_name.'/custom.php';

        if(!
is_readable($custom_file)){
            
$controller_class = $controller_name;
        } else {
            
$controller_class = $controller_name . '_custom';
            if (!
class_exists($controller_class, false)){
                include_once(
$custom_file);
            }
        }

        if (!
class_exists($controller_class, false)) {
            return 
self::error(ERR_COMPONENT_NOT_FOUND . ': '. str_replace($config->root_path, '', $ctrl_file));
        }

        return new 
$controller_class($request);
    }

    public static function 
getControllerInstance($controller_name, $request=null){

        if(!isset(
self::$controllers_instance[$controller_name])){

            
self::$controllers_instance[$controller_name] = self::getController($controller_name, $request);

        }

        return 
self::$controllers_instance[$controller_name];

    }

    public static function 
getControllerNameByAlias($controller_alias){

        
$config_mapping      = cmsConfig::getControllersMapping();
        
$controllers_mapping = cmsController::getControllersMapping();

        
$mapping = array_merge($controllers_mapping, $config_mapping);
        if (!
$mapping) { return false; }

        foreach(
$mapping as $name=>$alias){
            if (
$alias == $controller_alias) { return $name; }
        }

        return 
false;

    }

    public static function 
getControllerAliasByName($controller_name){

        if(!
$controller_name){ return false; }

        
$mapping = cmsConfig::getControllersMapping();

        if (!empty(
$mapping[$controller_name])){ return $mapping[$controller_name]; }

        
$cmapping = cmsController::getControllersMapping();

        if (!empty(
$cmapping[$controller_name])){ return $cmapping[$controller_name]; }

        return 
false;

    }

    
/**
     * Возвращает массив хуков контроллеров
     * @param boolean $is_debug Если передано true, то массив формируется из файлов манифестов, иначе - из БД
     * @param boolean $is_enabled
     * @return array
     */
    
public static function getControllersManifests($is_debug = false, $is_enabled = true){

        if (
$is_debug){
            return 
self::getManifestsEvents();
        }

        
$events = [];

        
$db = cmsDatabase::getInstance();

        if(!
$db->ready()){
            return 
$events;
        }

        if(
$is_enabled){
            
$controllers_events = $db->getRows('events FORCE INDEX (is_enabled)', '`is_enabled` = 1', '*', 'ordering ASC', true);
        } else {
            
$controllers_events = $db->getRows('events', '1', '*', 'ordering ASC', true);
        }

        if(
$controllers_events){
            foreach(
$controllers_events as $event){
                
// для сохранения сортировки + совместимость
                
if(!isset($events[ $event['listener'] ][$event['ordering']])){
                    
$events[ $event['listener'] ][$event['ordering']] = $event['event'];
                } else {
                    
// если вдруг по какой-то причине порядок одинаковый
                    
$events[ $event['listener'] ][intval($event['ordering'].'00'.$event['id'])] = $event['event'];
                }
            }
        }

        return 
$events;

    }

    
/**
     * Возвращает массив хуков контроллеров
     * из файлов манифестов
     * @return array
     */
    
public static function getManifestsEvents(){

        
$manifests_events = [];

        
$controllers = cmsCore::getDirsList('system/controllers', true);

        
$index = 0;

        foreach(
$controllers as $controller_name){

            
$manifest_file = cmsConfig::get('root_path') . 'system/controllers/' . $controller_name . '/manifest.php';

            if (!
is_readable($manifest_file)){ continue; }

            
$manifest = include $manifest_file;

            if (empty(
$manifest['hooks']) || !is_array($manifest['hooks'])) { continue; }

            foreach (
$manifest['hooks'] as $hook) {

                
$manifests_events[ $controller_name ][$index] = $hook;

                
$index++;

            }

        }

        return 
$manifests_events;

    }

//============================================================================//
//============================================================================//

    
public static function getWidgetPath($widget_name, $controller_name=false){

        if (
$controller_name){
            
$path = "controllers/{$controller_name}/widgets/{$widget_name}";
        } else {
            
$path = "widgets/{$widget_name}";
        }

        return 
$path;

    }

//============================================================================//
//============================================================================//

    /**
     * Подключает указанный языковой файл.
     * Если файл не указан, то подключаются все PHP-файлы из папки текущего языка
     *
     * @param string $file Относительный путь к файлу
     * @param string $default Язык по умолчанию, если в текущем не найдено
     * @return boolean
     */
    
public static function loadLanguage($file = false, $default = 'ru') {

        
$lang_dir = 'system/languages/'. self::$language;

        if (!
$file){

            
// Если файл не указан, то подключаем все php-файлы
            // из папки с текущим языком
            
return self::getFilesList($lang_dir, '*.php', true, true);

        } else {

            
// Если файл указан, то подключаем только его
            
$lang_file = $lang_dir .'/'.$file.'.php';

            
$result = self::includeFile($lang_file);

            if(!
$result && $default !== self::$language){
                
$result = self::includeFile('system/languages/'. $default .'/'.$file.'.php');
            }

            return 
$result;

        }

    }

    
/**
     * Возвращает содержимое текстового файла из папки с текущим языком
     * @param string $file
     * @return string
     */
    
public static function getLanguageTextFile($file){

        
$lang_dir = cmsConfig::get('root_path').'system/languages/'.self::$language;

        
$lang_file = $lang_dir .'/' . $file . '.txt';

        if (!
file_exists($lang_file)) { return false; }

        return 
file_get_contents($lang_file);

    }

    
/**
     * Подключает языковой файл контроллера
     * @param string $controller_name
     * @return bool
     */
    
public static function loadControllerLanguage($controller_name){
        return 
self::loadLanguage("controllers/{$controller_name}/{$controller_name}");
    }

    
/**
     * Подключает языковой файл виджета
     * @param string $widget_name
     * @param string $controller_name
     * @return bool
     */
    
public static function loadWidgetLanguage($widget_name, $controller_name=false){

        
$path = self::getWidgetPath($widget_name, $controller_name);

        return 
self::loadLanguage($path);

    }

    
/**
     * Подключает языковой файл шаблона
     * @param string|array $template_name
     * @return bool
     */
    
public static function loadTemplateLanguage($template_names){
        if(!
is_array($template_names)){
            
$template_names = [$template_names];
        }
        
$result = false;
        foreach (
$template_names as $template_name) {
            
$result = self::loadLanguage("templates/{$template_name}");
            if(
$result){
                break;
            }
        }
        return 
$result;
    }

    
/**
     * Подключает языковые файлы всех контроллеров
     *
     * @param string $file
     * @return bool
     */
    
public static function loadAllControllersLanguages(){

        
$controllers = self::getDirsList('system/controllers');

        foreach(
$controllers as $controller_name){
            
self::loadControllerLanguage($controller_name);
        }

    }

//============================================================================//
//============================================================================//

    /**
     * Определяет контроллер, действие и параметры для запуска по полученному URI
     * @param string $uri
     */
    
public function route($uri){

        
$config = cmsConfig::getInstance();

        
$uri = trim(urldecode($uri));
        
$uri = mb_substr($uri, mb_strlen( $config->root ));

        if (!
$uri) { return; }

        
// если в URL присутствует знак вопроса, значит есть
        // в нем есть GET-параметры которые нужно распарсить
        // и добавить в массив $_REQUEST
        
$pos_que  = mb_strpos($uri, '?');
        if (
$pos_que !== false){

            
// получаем строку запроса
            
$query_data = [];
            
$query_str  = mb_substr($uri, $pos_que+1);

            
// удаляем строку запроса из URL
            
$uri = mb_substr($uri, 0, $pos_que);

            
// парсим строку запроса
            
parse_str($query_str, $query_data);

            
$this->uri_query = $query_data;

            
// добавляем к полученным данным $_REQUEST
            // именно в таком порядке, чтобы POST имел преимущество над GET
            
$_REQUEST = array_merge($query_data, $_REQUEST);

        }

        
$this->uri = $this->uri_before_remap = $uri;
        
$this->uri_absolute = $config->root . $uri;

        
// разбиваем URL на сегменты
        
$segments = explode('/', $uri);

        
// Определяем контроллер из первого сегмента
        
if (isset($segments[0])) { $this->uri_controller = $segments[0]; }

        
// Определяем действие из второго сегмента
        
if (isset($segments[1])) { $this->uri_action = $segments[1]; }

        
// Определяем параметры действия из всех остальных сегментов
        
if (sizeof($segments)>2){
            
$this->uri_params = array_slice($segments, 2);
        }

        return 
true;

    }

    public function 
getUriData() {
        return array(
            
'controller' => $this->uri_controller,
            
'action'     => $this->uri_action,
            
'params'     => $this->uri_params
        
);
    }

//============================================================================//
//============================================================================//

    
public function defineController() {

        
$hash = md5($this->uri_controller.$this->uri_action);

        if(isset(
$this->defined_controllers[$hash])){
            return 
$this;
        }

        
$this->defined_controllers[$hash] = true;

        
$config = cmsConfig::getInstance();

        
// контроллер и экшен по умолчанию
        
if (!$this->uri_controller){ $this->uri_controller = $config->ct_autoload;    }
        if (!
$this->uri_action) { $this->uri_action = 'index'; }

        
// проверяем ремаппинг контроллера
        
$remap_to = self::getControllerNameByAlias($this->uri_controller);
        if (
$remap_to) {
            
// в uri также меняем
            
if($this->uri){
                
$seg = explode('/', $this->uri);
                
$seg[0] = $remap_to;
                
$this->uri = implode('/', $seg);
                
$this->uri_absolute = str_replace($this->uri_before_remap, $this->uri, $this->uri_absolute);
            }
            
$this->uri_controller_before_remap = $this->uri_controller;
            
$this->uri_controller = $remap_to;
        }

        if (!
self::isControllerExists($this->uri_controller)) {
            if(
$this->uri_action !== 'index'){
                
array_unshift($this->uri_params, $this->uri_action);
            }
            
$this->uri_action     = $this->uri_controller;
            
$this->uri_controller = $config->ct_default;
        }

        
$this->controller = $this->uri_controller;

        return 
$this;

    }

    
/**
     * Запускает выбранное действие контроллера
     */
    
public function runController(){

        
$this->defineController();

        if (!
preg_match('/^[a-z]{1}[a-z0-9_]*$/', $this->controller)){
            
self::error404();
        }

        
// загружаем контроллер
        
$controller = self::getController($this->controller, $this->request);

        
// контроллер включен?
        
if(!$controller->isEnabled()){
            return 
self::error404();
        }

        
// редирект 301, если настроен ремап
        
if(!$this->uri_controller_before_remap && $slug = $controller->hasSlug()){

            
// если контроллер запрещает редирект, то 404
            
if($controller->disallow_mapping_redirect){
                return 
self::error404();
            }

            
$controller->redirectTo($slug, ($this->uri_action === 'index' ? '' : $this->uri_action), $this->uri_params, $this->uri_query, 301);
        }

        
// запускаем действие
        
$controller->runAction($this->uri_action, $this->uri_params);

    }

    
/**
     * Определяет и загружает id страниц, которые определены для текущего uri
     * @return cmsCore
     */
    
public function loadMatchedPages() {

        if (
$this->matched_pages !== null) {
            return 
$this;
        }

        if (
$this->widgets_pages === null) {
            
$this->widgets_pages = cmsCore::getModel('widgets')->getPages();
        }

        
$this->matched_pages = $this->detectMatchedWidgetPages($this->widgets_pages);

        return 
$this;
    }

    public function 
getWidgetsPages() {
        return 
$this->widgets_pages;
    }

    public function 
getMatchedPagesIds() {
        return 
$this->matched_pages ? array_keys($this->matched_pages) : [];
    }

    public function 
getMatchedPages() {
        return 
$this->matched_pages;
    }

    public function 
setMatchedPages($matched_pages) {
        
$this->matched_pages = $matched_pages;
        return 
$this;
    }

//============================================================================//
//============================================================================//

    /**
     * Запускает все виджеты, привязанные к текущей странице
     */
    
public function runWidgets() {

        
$template = cmsTemplate::getInstance();

        if (
$template->widgets_rendered) {
            return 
$this;
        }

        
$template->widgets_rendered = true;

        
$controllers_without_widgets = cmsConfig::get('controllers_without_widgets');

        if (
$controllers_without_widgets && in_array($this->controller, $controllers_without_widgets)) {
            return;
        }

        
$matched_pages = $this->loadMatchedPages()->getMatchedPages();
        if (!
$matched_pages) { return; }

        
$widgets_list = cmsCore::getModel('widgets')->getWidgetsForPages(array_keys($matched_pages), $template->getName());

        if (
is_array($widgets_list)) {

            
$device_type = cmsRequest::getDeviceType();
            
$layout = $template->getLayout();
            
$user = cmsUser::getInstance();

            if (
$user->is_admin) {
                
cmsCore::loadControllerLanguage('admin');
            }

            foreach (
$widgets_list as $widget) {

                
// не выводим виджеты контроллеров, которые отключены
                
if (!empty($widget['controller']) && !cmsController::enabled($widget['controller'])) {
                    continue;
                }

                
// проверяем доступ для виджетов
                
if (!$user->isInGroups($widget['groups_view'])) {
                    continue;
                }
                if (!empty(
$widget['groups_hide']) && $user->isInGroups($widget['groups_hide']) && !$user->is_admin) {
                    continue;
                }

                
// проверяем для каких устройств показывать
                
if ($widget['device_types'] && !in_array($device_type, $widget['device_types'])) {
                    continue;
                }

                
// проверяем для каких макетов показывать
                
if ($widget['template_layouts'] && !in_array($layout, $widget['template_layouts'])) {
                    continue;
                }

                
// проверяем для каких языков показывать
                
if ($widget['languages'] && !in_array(cmsCore::getLanguageName(), $widget['languages'])) {
                    continue;
                }

                
cmsDebugging::pointStart('widgets');

                
$this->runWidget($widget);

                
cmsDebugging::pointProcess('widgets', function () use($widget) {
                    return [
                        
'data' => $widget['title'] . ' => /system/' . cmsCore::getWidgetPath($widget['name'], $widget['controller']) . '/widget.php',
                        
'context' => [
                            
'target' => $widget['controller'],
                            
'subject' => $widget['name']
                        ]
                    ];
                }, 
0);
            }
        }

        return 
$this;
    }

    public static function 
getWidgetObject($widget) {

        
$file = 'system/'.cmsCore::getWidgetPath($widget['name'], $widget['controller']).'/widget.php';

        
$class = 'widget' .
                    (
$widget['controller'] ? string_to_camel('_', $widget['controller']) : '') .
                    
string_to_camel('_', $widget['name']);

        if (!
class_exists($class, false)) {
            
cmsCore::includeFile($file);
            
cmsCore::loadWidgetLanguage($widget['name'], $widget['controller']);
        }

        return new 
$class($widget);

    }

    public function 
runWidget($widget){

        
$result = false;

        
$widget_object = cmsCore::getWidgetObject($widget);

        
$cache_key = 'widgets'.$widget['id'];
        
$cache = cmsCache::getInstance();

        if(
$widget_object->isCacheable()){
            
$result = $cache->get($cache_key);
        }

        if (
$result === false){
            
$result = call_user_func_array(array($widget_object, 'run'), []);
            if (
$result !== false){
                
// Отдельно кешируем имя шаблона виджета, заголовок и враппер, поскольку они могли быть
                // изменены внутри виджета, а в кеш у нас попадает только тот массив
                // который возвращается кодом виджета (без самих свойств $widget_object)
                
$result['_wd_template'] = $widget_object->getTemplate();
                
$result['_wd_title']    = $widget_object->title;
                
$result['_wd_wrapper']  = $widget_object->getWrapper();
            }
            if(
$widget_object->isCacheable()){
                
$cache->set($cache_key, $result);
            }
        }

        if (
$result === false) { return false; }

        if (isset(
$result['_wd_template'])) { $widget_object->setTemplate($result['_wd_template']); }
        if (isset(
$result['_wd_title'])) { $widget_object->title = $result['_wd_title']; }
        if (isset(
$result['_wd_wrapper'])) { $widget_object->setWrapper($result['_wd_wrapper']); }

        return 
cmsTemplate::getInstance()->renderWidget($widget_object, $result);

    }

    
/**
     * Определяет какие из списка страниц виджетов
     * совпадают по маске с текущей страницей
     *
     * @param array $pages
     * @param string $uri
     * @return array
     */
    
public function detectMatchedWidgetPages($pages, $uri = null) {

        if(
$uri === null){
            
$uri = $this->uri;
            
$uri_query = $this->uri_query;
        }

        if (
$uri === '') {
            return [
0, 1];
        }

        
$matched_pages = [];

        
$_full_uri = $uri . (!empty($uri_query) ? '?' . http_build_query($uri_query) : '');

        
//
        // Перебираем все точки привязок и проверяем совпадение
        // маски URL с текущим URL
        //
        
foreach ($pages as $page) {

            if (empty(
$page['url_mask']) && !empty($page['id'])) {
                continue;
            }

            
$is_mask_match = empty($page['id']);
            
$is_stop_match = false;

            if (!empty(
$page['url_mask'])) {
                foreach (
$page['url_mask'] as $mask) {
                    
$regular       = string_mask_to_regular($mask);
                    
$regular       = "/^{$regular}$/iu";
                    
$is_mask_match = $is_mask_match || preg_match($regular, $uri);
                }
            }

            if (!empty(
$page['url_mask_not'])) {
                foreach (
$page['url_mask_not'] as $mask) {
                    
$regular       = string_mask_to_regular($mask);
                    
$regular       = "/^{$regular}$/iu";
                    
$is_stop_match = $is_stop_match || preg_match($regular, $_full_uri);
                }
            }

            if (
$is_mask_match && !$is_stop_match) {
                
$matched_pages[$page['id']] = $page;
            }
        }

        return 
$matched_pages;
    }

//============================================================================//
//============================================================================//

    /**
     * Показывает сообщение об ошибке и завершает работу
     * @param string $message
     * @param string $details
     */
    
public static function error($message, $details = '') {

        if(
ob_get_length()) { ob_end_clean(); }

        
http_response_code(503);

        
$is_debug = cmsConfig::get('debug');

        if(!
$is_debug){
            
$message = LANG_ERROR_503;
            
$details = LANG_ERROR_503_HINT;
        }

        
ob_start();

        
cmsTemplate::getInstance()->renderAsset('errors/error', [
            
'is_debug' => $is_debug,
            
'message'  => $message,
            
'details'  => $details
        
], self::getInstance()->request);

        
$html = ob_get_clean();

        die(
cmsConfig::get('min_html') ? html_minify($html) : $html);
    }

    
/**
     * Показывает сообщение об ошибке 403 и завершает работу
     * @param string $message Текстовое сообщение к ошибке
     * @param boolean $show_login_link Показывать ссылку на авторизацию
     * @return die
     */
    
public static function errorForbidden($message = '', $show_login_link = false){

        
$result = cmsEventsManager::hook('error_403', self::getInstance()->uri);

        if(
$result === true){ return false; }

        if(
ob_get_length()) { ob_end_clean(); }

        
http_response_code(403);

        
ob_start();

        
cmsTemplate::getInstance()->renderAsset('errors/forbidden', [
            
'message'         => $message,
            
'show_login_link' => $show_login_link
        
]);

        
$html = ob_get_clean();

        die(
cmsConfig::get('min_html') ? html_minify($html) : $html);
    }

    
/**
     * Показывает сообщение об ошибке 404 и завершает работу
     */
    
public static function error404(){

        
$result = cmsEventsManager::hook('error_404', self::getInstance()->uri);

        if(
$result === true){ return false; }

        if(
ob_get_length()) { ob_end_clean(); }

        
http_response_code(404);

        
ob_start();

        
cmsTemplate::getInstance()->renderAsset('errors/notfound');

        
$html = ob_get_clean();

        die(
cmsConfig::get('min_html') ? html_minify($html) : $html);
    }

    
/**
     * Показывает сообщение о том что сайт отключен и завершает работу
     */
    
public static function errorMaintenance(){

        if(
ob_get_length()) { ob_end_clean(); }

        
http_response_code(503);

        
ob_start();

        
cmsTemplate::getInstance()->renderAsset('errors/offline', [
            
'reason' => cmsConfig::get('off_reason')
        ]);

        
$html = ob_get_clean();

        die(
cmsConfig::get('min_html') ? html_minify($html) : $html);
    }

    public static function 
respondIfModifiedSince($lastmod) {

        
$last_modified_unix = strtotime($lastmod);

        
$last_modified = gmdate("D, d M Y H:i:s GMT", $last_modified_unix);

        
$if_modified_since = false;

        if (isset(
$_ENV['HTTP_IF_MODIFIED_SINCE'])) {
            
$if_modified_since = strtotime(substr($_ENV['HTTP_IF_MODIFIED_SINCE'], 5));
        }

        if (isset(
$_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
            
$if_modified_since = strtotime(substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 5));
        }

        if (
$if_modified_since && $if_modified_since >= $last_modified_unix) {

            if (
ob_get_length()) {
                
ob_end_clean();
            }

            
http_response_code(304);

            die();

        }

        
header('Last-Modified: ' . $last_modified);

    }

//============================================================================//
//============================================================================//

    /**
     * Возвращает массив со списком всех шаблонов
     * @return array
     */
    
public static function getTemplates(){

        if(
self::$templates !== null){
            return 
self::$templates;
        }

        if(
cmsTemplate::TEMPLATE_BASE_PATH){
            return 
self::$templates = self::getDirsList(cmsTemplate::TEMPLATE_BASE_PATH);
        }

        
$root_path = cmsConfig::get('root_path');
        
$all_dirs = self::getDirsList('');
        
$result = [];

        foreach(
$all_dirs as $dir){
            
// В папке шаблона в обязательном порядке должны быть как минимум эти файлы
            
if(file_exists($root_path.$dir.'/main.tpl.php') && (file_exists($root_path.$dir.'/scheme.html') || file_exists($root_path.$dir.'/scheme.php'))){
                
$result[] = $dir;
            }
        }

        return 
self::$templates = $result;

    }

    
/**
     * Возвращает массив со списком всех языков
     * @return array
     */
    
public static function getLanguages(){

        
$default_lang = cmsConfig::get('language');

        
$langs = self::getDirsList('system/languages', true);

        
$current_lang_key = array_search(self::$language, $langs);

        if(
$current_lang_key !== 0){

            list(
$langs[0], $langs[$current_lang_key]) = [$langs[$current_lang_key], $langs[0]];

        }

        if(
$default_lang !== self::$language){

            
$default_lang_key = array_search($default_lang, $langs);

            if(
$default_lang_key !== 1){

                list(
$langs[1], $langs[$default_lang_key]) = [$langs[$default_lang_key], $langs[1]];

            }

        }

        return 
$langs;

    }

    
/**
     * Возвращает массив со списком всех визуальных редакторов
     * @return array
     */
    
public static function getWysiwygs(){

        return 
self::getDirsList('wysiwyg');

    }

//============================================================================//
//============================================================================//

    /**
     * Возвращает список директорий внутри указанной
     * @param string $root_dir
     * @param bool $asc_sort Сортировать по алфавиту, по умолчанию false
     * @return array
     */
    
public static function getDirsList($root_dir, $asc_sort=false){

        
$dir = cmsConfig::get('root_path') . $root_dir;
        
$dir_context = opendir($dir);

        
$list = [];

        while (
$next = readdir($dir_context)){

            if (
in_array($next, array('.', '..'))){ continue; }
            if (
strpos($next, '.') === 0){ continue; }
            if (!
is_dir($dir.'/'.$next)) { continue; }

            
$list[] = $next;

        }

        if(
$asc_sort){
            
sort($list);
        }

        return 
$list;

    }

    
/**
     * Возвращает список файлов из указанной директории по нужной маске
     * @param string $root_dir Директория
     * @param string $pattern Маска файлов
     * @param bool $is_strip_ext Отрезать расширения?
     * @param bool $is_include Подключать каждый файл?
     * @return array
     */
    
public static function getFilesList($root_dir, $pattern='*.*', $is_strip_ext=false, $is_include=false){

        
$config = cmsConfig::getInstance();

        
$directory = $config->root_path . $root_dir;
        
$pattern = $directory . '/' . $pattern;

        
$list = [];

        
$files = @glob($pattern);

        if (!
$files) { return $list; }

        foreach (
$files as $file) {

            if (
$is_include && !isset(self::$includedFiles[$file])) {
                include_once 
$file;
                
self::$includedFiles[$file] = true;
            }

            
$file = basename($file);

            if (
$is_strip_ext){ $file = pathinfo($file, PATHINFO_FILENAME); }

            
$list[] = $file;

        }

        return 
$list;

    }

//============================================================================//
//============================================================================//

    /**
     * Устанавливает соединение с БД
     *
     */
    
public function connectDB(){
        
$this->db = cmsDatabase::getInstance();
    }

//============================================================================//
//============================================================================//

    
public static function getTimeZones(){
        
self::loadLib('timezones');
        
$_zones = getTimeZones();
        
$zones = [];
        foreach(
$_zones as $zone){
            
$zones[ $zone ] = $zone;
        }
        return 
$zones;
    }

}

/**
 * В случае, если отладка отключена, не загружаем файл класса
 */
if(!class_exists('cmsDebugging', false)){
    class 
cmsDebugging {
        public static function 
__callStatic($name, $arguments) {}
    }
}
Онлайн: 2
Реклама