Как правильно: Cot::$usr['theme'] или Cot::$cfg['defaulttheme']?
Содержание
- Введение
- Назначение файла .rc.php в архитектуре Cotonti
- Переменные $usr['theme'] и $cfg['defaulttheme']
- Механизм подключения .rc.php движком
- Взаимосвязь и приоритет переменных
- Практические сценарии эксплуатации
- Правила оформления файла .rc.php
- Справочник по классу Resources
- Типичные ошибки и способы их устранения
- Диагностика и отладка
- Заключение
1. Введение
При разработке темы для Cotonti CMF разработчик сталкивается с необходимостью подключения CSS и JavaScript ресурсов в файле .rc.php. Возникает закономерный вопрос: какую переменную использовать для построения путей к ресурсам темы — Cot::$usr['theme'] или Cot::$cfg['defaulttheme']?
На первый взгляд, разница между этими переменными минимальна, и многие готовые темы используют Cot::$cfg['defaulttheme']. Однако такой подход работает лишь в ограниченном наборе конфигураций. В общем случае он приводит к поломке путей, исключениям в Resources::addFile() и падению фронтальной части сайта.
Настоящая статья систематизирует знания о механизмах темизации Cotonti и даёт однозначный ответ на поставленный вопрос. Материал рассчитан как на начинающих разработчиков, так и на опытных специалистов, знакомых с внутренним устройством CMF.
2. Назначение файла .rc.php в архитектуре Cotonti
2.1. Определение
Файл .rc.php (от англ. resource control) — это вспомогательный файл темы Cotonti, который регистрирует CSS и JavaScript ресурсы в статическом реестре класса Resources. Движок затем выводит эти ресурсы в <head> страницы и в футер.
Файл не является ни плагином, ни модулем, ни самостоятельной темой. Он относится к категории вспомогательных файлов темы наряду с {theme}.php (файл переопределения языковых и ресурсных строк) и {theme}.tpl (шаблоны).
2.2. Место в архитектуре CMF
Регистрация и вывод ресурсов выполняются классом Resources, который расположен в файле system/resources.php. Класс хранит следующие статические структуры:
$registry— реестр ресурсов<head>при включённой консолидации;$headerRc— реестр ресурсов<head>без консолидации;$footerRc— реестр ресурсов футера;$addedFiles— карта уже добавленных файлов (для дедупликации);$alias— карта предопределённых алиасов (@jQuery,@bootstrap,@select2и другие);- флаги
$cacheOn,$consolidate,$minify,$isAdmin,$headerComplete,$htmlCleanupEnabled.
Инициализация класса выполняется методом Resources::__init(), который вызывается в конце файла resources.php. Метод читает настройки из массива $cfg:
cache— глобальный флаг кэширования;headrc_consolidate— флаг консолидации ресурсов;headrc_minify— флаг минификации;html_cleanup— флаг очистки HTML от лишних пробелов;cache_dir— директория кэша;dir_perms— права на создаваемые директории.
Флаг $isAdmin устанавливается по значению константы COT_ADMIN. Для фронтальной части сайта $isAdmin === false, что разрешает работу консолидации и минификации при условии, что они включены в конфигурации.
2.3. Подключение файла движком
Файл .rc.php подключается движком в секции Head Resources файла system/common.php:
if (!defined('COT_ADMIN')) {
if (file_exists("{$cfg['themes_dir']}/{$usr['theme']}/{$usr['theme']}.rc.php")) {
include "{$cfg['themes_dir']}/{$usr['theme']}/{$usr['theme']}.rc.php";
}
}Анализ этого фрагмента даёт три ключевых факта:
- Проверяется существование файла по пути
themes/{$usr['theme']}/{$usr['theme']}.rc.php. - Если файл существует — он подключается оператором
include. - Имя темы берётся из переменной
$usr['theme'], а не из$cfg['defaulttheme'].
Из этого следует фундаментальный вывод: в момент выполнения файла .rc.php переменная $usr['theme'] гарантированно равна имени текущей темы. Если бы это было не так, файл не был бы подключён.
2.4. Условия подключения
Файл .rc.php подключается при соблюдении следующих условий:
- константа
COT_ADMINне определена (фронтальная часть сайта); - файл физически существует по пути
themes/{$usr['theme']}/{$usr['theme']}.rc.php; - метод
Resources::__init()уже выполнен; - функция
cot_rc_add_standard()уже подключила стандартные ресурсы (jQuery,js/base.js,js/ajax_on.js).
2.5. Позиция в последовательности выполнения
Файл .rc.php выполняется в следующей последовательности common.php:
- Инициализация окружения (загрузка конфигурации, подключение к БД,
Cot::init()). - Загрузка конфигурации из базы данных.
- Определение пользователя и вычисление
$usr['theme']. - Проверка существования
themes/{$usr['theme']}/header.tplс fallback на$cfg['defaulttheme']. - Вызов
cot_rc_add_standard(). - Выполнение хука
rc. - Подключение
.rc.phpтемы.
3. Переменные $usr['theme'] и $cfg['defaulttheme']
3.1. Переменная $cfg['defaulttheme']
$cfg['defaulttheme'] — это глобальная настройка сайта, определяющая тему оформления по умолчанию. Значение загружается из таблицы конфигурации базы данных при инициализации движка и не зависит от того, какой пользователь обратился к сайту.
Характеристики переменной:
- Тип значения: строка, содержащая код темы (например,
index36). - Источник: таблица
cot_config, параметрdefaulttheme. - Область видимости: глобальная для всего сайта.
- Роль в вычислениях: входная величина.
3.2. Переменная $usr['theme']
$usr['theme'] — это тема, применяемая к текущему пользователю. Значение вычисляется в common.php на основе нескольких параметров.
Для авторизованного пользователя:
$usr['theme'] = $cfg['forcedefaulttheme'] ? $cfg['defaulttheme'] : $row['user_theme'];Для гостя используется значение по умолчанию из инициализации массива $usr:
'theme' => $cfg['defaulttheme'],После вычисления выполняется проверка на существование шаблона:
$mtheme = "{$cfg['themes_dir']}/{$usr['theme']}/header.tpl";
if (!file_exists($mtheme)) {
$usr['theme'] = $cfg['defaulttheme'];
$mtheme = "{$cfg['themes_dir']}/{$usr['theme']}/header.tpl";
if (!file_exists($mtheme)) {
cot_diefatal($L['com_defthemefail']);
}
}Характеристики переменной:
- Тип значения: строка, содержащая код темы.
- Источник: результат вычисления на основе
$cfg['forcedefaulttheme']и$row['user_theme']. - Область видимости: текущий пользователь (в рамках запроса).
- Роль в вычислениях: результат.
3.3. Возможные значения $usr['theme']
Переменная может принимать одно из следующих значений:
$cfg['defaulttheme']— если флагforcedefaultthemeвключён, или если пользователь сам выбрал дефолтную тему;$row['user_theme']— если флагforcedefaultthemeвыключен, и пользователь выбрал собственную тему;$cfg['defaulttheme']— как fallback, если папка выбранной темы отсутствует.
3.4. Связь между переменными
Переменная $usr['theme'] вычисляется на основе $cfg['defaulttheme'], но обратной зависимости не существует. Это означает:
$cfg['defaulttheme']— входная величина;$usr['theme']— выходная (результирующая) величина.
Для файла .rc.php корректной является результирующая величина, поскольку файл физически подключён из папки именно этой темы.
4. Механизм подключения .rc.php движком
4.1. Пошаговый разбор
Рассмотрим последовательность действий движка более детально.
Шаг 1. Инициализация конфигурации.
Движок загружает $cfg из базы данных и файла datas/config.php. На этом этапе становятся доступны значения defaulttheme, forcedefaulttheme, themes_dir и другие.
Шаг 2. Определение пользователя.
Выполняется запрос к таблице cot_users для получения данных текущего пользователя. Если пользователь авторизован, в массив $usr попадают значения из $row.
Шаг 3. Вычисление $usr['theme'].
На основе $cfg['forcedefaulttheme'] и $row['user_theme'] вычисляется значение $usr['theme'].
Шаг 4. Проверка существования шаблона.
Движок проверяет наличие файла themes/{$usr['theme']}/header.tpl. Если файл отсутствует, значение $usr['theme'] принудительно меняется на $cfg['defaulttheme'].
Шаг 5. Инициализация ресурсов.
Вызывается cot_rc_add_standard(), который регистрирует стандартные ресурсы: jQuery (при включённой опции), js/jqModal.min.js, js/base.min.js, js/ajax_on.js (при включённом AJAX).
Шаг 6. Выполнение хука rc.
Плагины, зарегистрированные на хук rc, имеют возможность добавить свои ресурсы.
Шаг 7. Подключение .rc.php темы.
При соблюдении условий (см. раздел 2.4) движок выполняет:
include "{$cfg['themes_dir']}/{$usr['theme']}/{$usr['theme']}.rc.php";4.2. Что доступно внутри .rc.php
К моменту выполнения файла .rc.php доступны следующие переменные и объекты:
Cot::$cfg— полный массив конфигурации;Cot::$usr— данные текущего пользователя, включаяtheme;Cot::$sys— системные переменные (abs_url,site_uri,scheme,now);Cot::$db— объект базы данных;$L— языковые строки;$R— ресурсные строки;$theme— не определена (назначается позже в блоке Theme / color scheme).
4.3. Что гарантировано
В момент выполнения .rc.php гарантировано следующее:
$usr['theme']содержит имя текущей темы;- файл
themes/{$usr['theme']}/header.tplсуществует; Resources::__init()выполнен, классResourcesготов к использованию;- стандартные ресурсы уже зарегистрированы.
5. Взаимосвязь и приоритет переменных
5.1. Отсутствие приоритета
Формулировка «приоритет переменных» некорректна. $usr['theme'] и $cfg['defaulttheme'] — это величины разной природы, решающие разные задачи.
| Переменная | Роль | Тип |
|---|---|---|
$cfg['defaulttheme'] | Тема сайта по умолчанию | Вход |
$usr['theme'] | Тема, применяемая к пользователю | Результат |
5.2. Правило выбора
Для файла .rc.php правильной величиной является результат ($usr['theme']), поскольку файл физически подключён из папки этой темы.
5.3. Обоснование
Файл .rc.php подключается движком по пути themes/{$usr['theme']}/{$usr['theme']}.rc.php. Это означает, что все ресурсы, регистрируемые внутри файла, относятся именно к этой папке. Использование $cfg['defaulttheme'] для склейки путей внутри файла допустимо только в том случае, если $cfg['defaulttheme'] совпадает с $usr['theme'], что не является общим случаем.
5.4. Официальная позиция Cotonti
В официальных руководствах по разработке тем Cotonti и в обсуждениях на форуме разработчиков рекомендуется использовать $usr['theme'] для ссылок на ресурсы темы. Это подтверждается архитектурой движка: .rc.php подключается из папки пользовательской темы, и все ресурсы внутри файла должны относиться к этой же теме.
6. Практические сценарии эксплуатации
6.1. Сценарий A. Единственная тема, форсирование включено
Параметры:
defaulttheme = index36forcedefaulttheme = true
Поведение: $usr['theme'] всегда равен index36. Оба варианта ($usr['theme'] и $cfg['defaulttheme']) дают идентичный путь. Приложение работает корректно.
Вывод: сценарий не показателен для анализа.
6.2. Сценарий B. Единственная тема, форсирование выключено
Параметры:
defaulttheme = index36forcedefaulttheme = false- Все пользователи имеют
user_theme = index36
Поведение: $usr['theme'] равен index36. Оба варианта дают идентичный путь. Приложение работает корректно.
Вывод: сценарий также не показателен.
6.3. Сценарий C. Несколько тем, пользовательские предпочтения
Параметры:
defaulttheme = index36forcedefaulttheme = false- Пользователь имеет
user_theme = mytheme
Поведение: движок подключает themes/mytheme/mytheme.rc.php. Внутри файла:
- при использовании
$usr['theme']путь формируется какthemes/mytheme/assets/...— корректно; - при использовании
$cfg['defaulttheme']путь формируется какthemes/index36/assets/...— некорректно.
Файлы по второму пути отсутствуют. Resources::addFile() бросает Exception. Фронтальная часть сайта падает.
Вывод: использование $cfg['defaulttheme'] приводит к критической ошибке.
6.4. Сценарий D. Изменение defaulttheme
Параметры:
defaulttheme = newtheme(изменён администратором)forcedefaulttheme = false- Пользователь имеет
user_theme = index36
Поведение: движок подключает themes/index36/index36.rc.php. Внутри файла:
- при использовании
$usr['theme']путь формируется какthemes/index36/assets/...— корректно; - при использовании
$cfg['defaulttheme']путь формируется какthemes/newtheme/assets/...— некорректно.
Файлы отсутствуют. Exception. Фронт падает.
Вывод: изменение defaulttheme без выключения пользовательских тем ломает работу тем, использующих $cfg['defaulttheme'] в .rc.php.
6.5. Сценарий E. Тема-заглушка (fallback)
Параметры:
defaulttheme = broken- Папка
themes/broken/отсутствует forcedefaulttheme = true
Поведение: движок обнаруживает отсутствие themes/broken/header.tpl и выполняет проверку fallback. Если папка отсутствует и fallback не помогает, вызывается cot_diefatal($L['com_defthemefail']). Файл .rc.php не подключается.
Вывод: сценарий аварийный, .rc.php не выполняется.
6.6. Сводная таблица сценариев
| Сценарий | defaulttheme | forcedefaulttheme | user_theme | Результат |
|---|---|---|---|---|
| A | index36 | true | — | Работает |
| B | index36 | false | index36 | Работает |
| C | index36 | false | mytheme | Ломается |
| D | newtheme | false | index36 | Ломается |
| E | broken | true | — | Аварийный |
7. Правила оформления файла .rc.php
7.1. Общие требования
Файл начинается с обязательной конструкции:
<?php defined('COT_CODE') or die('Wrong URL.');- Запрещён любой вывод в стандартный поток вывода (
echo,print,var_dump). Файл подключается в момент, когда часть заголовков уже отправлена. - Использовать исключительно публичные статические методы класса
Resources. Прямой доступ к защищённым и приватным полям класса недопустим. - Локальные файлы указываются путём от корня сайта без ведущего слэша. Класс
Resourcesвыполняет проверкуfile_exists()и бросаетExceptionпри отсутствии файла. - Внешние ресурсы указываются полным URL (
http://,https://,//). Для них проверкаfile_exists()не выполняется. - CSS-файлы размещаются в
<head>черезResources::addFile()илиResources::linkFile(). - JavaScript-файлы размещаются в футере через
Resources::linkFileFooter(), за исключением критичных для рендера скриптов. - Порядок
$orderзадаётся явно для всех файлов, кроме дефолтного значения 50. - Запрещён ручной вызов
Resources::render()иResources::renderFooter(). Эти методы вызываются движком. - Запрещено использование устаревших обёрток
cot_rc_add_file(),cot_rc_add_embed(),cot_rc_link_file(). Они помечены как deprecated. - Файл должен быть идемпотентным: повторное выполнение не должно изменять конфигурацию реестра.
- Обращение к базе данных недопустимо:
.rc.phpвыполняется при каждом запросе. - Переопределение
$Lи$Rзапрещено — для этого предназначен файл{theme}.php.
7.2. Рекомендации по структуре
Рекомендуется определить переменную для корневого пути темы:
$themeDir = Cot::$cfg['themes_dir'] . '/' . Cot::$usr['theme'];Это обеспечивает единообразие и снижает риск опечаток.
7.3. Рекомендации по порядку ресурсов
Порядок подключения ресурсов (значения $order):
- 10–20 — базовые библиотеки (jQuery);
- 20–40 — фреймворки (Bootstrap);
- 40–70 — плагины (Select2, Fancybox, Perfect Scrollbar);
- 100–150 — скрипты темы;
- 800–900 — оверрайды темы.
7.4. Рекомендации по размещению
CSS-ресурсы:
- базовые библиотеки — в
<head>; - плагины — в
<head>; - стили темы — в
<head>; - оверрайды — в
<head>с высоким$order.
JavaScript-ресурсы:
- jQuery — в
<head>; - Bootstrap bundle — в
<head>(при консолидации) или в футере; - плагины — в футере;
- скрипты темы — в футере;
- скрипты инициализации — в футере с максимальным
$order.
7.5. Шаблон файла
<?php
/**
* Theme resource loader
*
* @package {theme}
* @version {version}
* @author {author}
* @copyright {copyright}
* @license {license}
*/
defined('COT_CODE') or die('Wrong URL.');
$themeDir = Cot::$cfg['themes_dir'] . '/' . Cot::$usr['theme'];
// CSS — <head>
Resources::addFile('lib/bootstrap/css/bootstrap.min.css', 'css', 10);
Resources::addFile($themeDir . '/css/theme.css', 'css', 800);
// JS — <head> (критичные)
Resources::addFile($themeDir . '/js/header.first.js', 'js', 40);
// JS — футер
Resources::linkFileFooter('lib/bootstrap/js/bootstrap.bundle.min.js', 'js', 30);
Resources::linkFileFooter($themeDir . '/js/theme.js', 'js', 100);8. Справочник по классу Resources
8.1. Публичные методы
Resources::addFile($path, $type = '', $order = 50, $scope = 'global')
Регистрирует файл в реестре <head>. При включённой консолидации файл может быть склеен с другими в общий asset.
Параметры:
$path— путь к файлу, полный URL или алиас;$type—'js'или'css'; при пустом значении определяется по расширению;$order— порядок вывода (по умолчанию 50);$scope— область видимости (global,guest,user,group_{id}).
Возвращает true при успехе, false при дублировании файла. Бросает Exception, если локальный файл не найден.
Resources::linkFile($path, $type = '', $order = 50)
Добавляет файл в <head> без консолидации. HTML формируется немедленно.
Resources::linkFileFooter($path, $type = '', $order = 50)
Добавляет файл в футер. HTML формируется немедленно.
Resources::addEmbed($code, $type = 'js', $order = 50, $scope = 'global', $identifier = '')
Регистрирует встроенный код в <head>. При включённой консолидации и минификации код сохраняется в файл в директории cache_dir/assets/.
Resources::embed($code, $type = 'js', $order = 50, $attr = '')
Немедленная вставка кода в <head>.
Resources::embedFooter($code, $type = 'js', $order = 50, $attr = '')
Немедленная вставка кода в футер.
Resources::setAlias($alias, $path, $canReWrite = false)
Регистрирует или переопределяет алиас. По умолчанию перезапись запрещена.
Resources::getAlias($alias)
Возвращает путь по алиасу или null.
Resources::isFileAdded($fileName)
Проверяет, добавлялся ли ранее указанный файл или алиас.
Resources::minify($code, $type)
Выполняет минификацию JavaScript (через lib/jsmin.php) или CSS (через lib/cssmin.php).
8.2. Предопределённые алиасы
Класс Resources содержит следующие предопределённые алиасы:
@jQuery→js/jquery.min.js@ckeditor→plugins/ckeditor/lib/ckeditor.js@ckeditorPreset.js→plugins/ckeditor/presets/ckeditor.default.set.js@bootstrap→lib/bootstrap/js/bootstrap.bundle.min.js@bootstrap.css→lib/bootstrap/css/bootstrap.min.css@select2→lib/select2/js/select2.full.min.js@select2.css→lib/select2/css/select2.min.css
Константы класса:
Resources::JQUERYResources::BOOTSTRAPResources::CKEDITORResources::SELECT2
8.3. Механизм scope
Параметр $scope определяет область видимости ресурса:
global— ресурс подключается всегда;guest— только для гостей ($usr['id'] === 0);user— только для авторизованных пользователей ($usr['id'] > 0);group_{id}— только для пользователей сmaingrp, равным{id}.
Область видимости применяется при выводе в Resources::render().
8.4. Механизм order
Параметр $order определяет порядок вывода. Меньшее значение соответствует более раннему выводу. По умолчанию — 50.
8.5. Консолидация и минификация
При условии $cfg['cache'] && $cfg['headrc_consolidate'] && !$isAdmin класс Resources выполняет консолидацию ресурсов одного типа и области видимости в единый файл:
cache_dir/assets/{scope}.{theme}.{type}— итоговый файл;cache_dir/assets/{scope}.{theme}.{type}.idx— индекс файлов;cache_dir/assets/{scope}.{theme}.{type}.gz— gzip-версия.
Консолидированный файл отдаётся через URL rc.php?rc={scope}.{theme}.{type}&nc={mtime}.
9. Типичные ошибки и способы их устранения
9.1. Использование $cfg['defaulttheme'] для путей к ресурсам темы
Симптом: при смене темы по умолчанию или при наличии нескольких тем фронтальная часть падает с ошибкой Exception.
Причина: внутри .rc.php формируется путь через Cot::$cfg['themes_dir'] . '/' . Cot::$cfg['defaulttheme'], что не соответствует папке, из которой подключён файл.
Решение: использовать Cot::$usr['theme'].
9.2. Использование переменной $theme
Симптом: предупреждение Undefined variable $theme или некорректный путь.
Причина: переменная $theme назначается в common.php позже, в блоке Theme / color scheme.
Решение: использовать Cot::$usr['theme'].
9.3. Дублирование ресурсов
Симптом: в исходном HTML присутствуют дублирующие теги <script> и <link> для jQuery, Bootstrap или других библиотек.
Причина: повторная регистрация ресурсов, уже подключённых через cot_rc_add_standard().
Решение: не добавлять jQuery, jqModal, base.js, ajax_on.js повторно.
9.4. Размещение CSS в футере
Симптом: тег <link rel="stylesheet"> располагается в конце <body>.
Причина: использование Resources::linkFileFooter() для CSS-файлов.
Решение: CSS-файлы размещать в <head> через Resources::addFile() или Resources::linkFile().
9.5. Размещение всех JS в head
Симптом: медленная загрузка страницы, блокировка парсинга HTML.
Причина: все JS-файлы регистрируются через Resources::addFile() в <head>.
Решение: разместить не критичные JS в футере через Resources::linkFileFooter(). В <head> оставить только jQuery и скрипты, критичные для первичного рендера.
9.6. Игнорирование исключения addFile
Симптом: фронтальная часть падает при отсутствии файла.
Причина: Resources::addFile() бросает Exception, если локальный файл не найден.
Решение: проверять существование файла через file_exists() перед регистрацией, если файл может отсутствовать.
9.7. Изменение $theme_reload
Симптом: переопределения $L и $R не работают или работают некорректно.
Причина: ручное вмешательство в массив $theme_reload.
Решение: не изменять $theme_reload вручную. Переопределения выполняются через $L и $R в файле {theme}.php.
9.8. Использование устаревших обёрток
Симптом: предупреждение deprecated в логах.
Причина: использование cot_rc_add_file(), cot_rc_add_embed(), cot_rc_link_file().
Решение: использовать методы класса Resources.
9.9. Некорректный order
Симптом: стили темы перекрываются стилями плагинов или библиотек.
Причина: недостаточно высокое значение $order для стилей темы.
Решение: устанавливать $order для стилей темы в диапазоне 800–900.
9.10. Обращение к базе данных
Симптом: замедление загрузки страниц.
Причина: выполнение SQL-запросов внутри .rc.php.
Решение: перенести логику в контроллер или модуль.
10. Диагностика и отладка
10.1. Проверка значения переменных
Для диагностики можно временно добавить в начало .rc.php:
error_log('usr theme: ' . Cot::$usr['theme']);
error_log('default theme: ' . Cot::$cfg['defaulttheme']);
error_log('themes dir: ' . Cot::$cfg['themes_dir']);Записи попадут в лог ошибок веб-сервера.
10.2. Проверка подключения файла
Для проверки факта подключения .rc.php:
error_log('rc.php loaded from: ' . __FILE__);10.3. Проверка реестра ресурсов
Для просмотра зарегистрированных ресурсов:
error_log('headerRc: ' . print_r(Resources::$headerRc ?? null, true));Обращение к защищённым полям класса требует осторожности и применяется только в отладочных целях.
10.4. Проверка консолидации
Для проверки факта консолидации:
error_log('consolidate: ' . (int) Cot::$cfg['headrc_consolidate']);
error_log('cache: ' . (int) Cot::$cfg['cache']);10.5. Проверка исключений
Оборачивание вызовов Resources::addFile() в try/catch:
try {
Resources::addFile($themeDir . '/css/theme.css', 'css', 800);
} catch (Exception $e) {
error_log('Resource error: ' . $e->getMessage());
}Такой подход позволяет изолировать проблему и не обрушить страницу.
10.6. Включение режима отладки
При значении Cot::$cfg['debug_mode'] === true движок выводит дополнительные сведения. Проверку можно выполнить через:
error_log('debug_mode: ' . (int) Cot::$cfg['debug_mode']);11. Заключение
Выбор между Cot::$usr['theme'] и Cot::$cfg['defaulttheme'] в файле .rc.php определяется архитектурой движка Cotonti.
Файл .rc.php подключается движком из папки themes/{$usr['theme']}/. Это означает, что переменная $usr['theme'] в момент выполнения файла гарантированно содержит имя текущей темы. Все ресурсы, регистрируемые внутри файла, относятся именно к этой папке.
Переменная $cfg['defaulttheme'] содержит настройку сайта по умолчанию. Она совпадает с $usr['theme'] только при соблюдении ряда условий:
- включён флаг
forcedefaulttheme; - у всех пользователей
user_themeсовпадает сdefaulttheme; defaultthemeне был изменён.
В общем случае совпадения нет, и использование $cfg['defaulttheme'] приводит к формированию неверных путей. Класс Resources бросает Exception, и фронтальная часть сайта падает.
Правило: для построения путей к ресурсам темы внутри .rc.php использовать Cot::$usr['theme'].
Обоснование: файл подключён из папки themes/{$usr['theme']}/, поэтому ресурсы принадлежат именно этой теме. Использование $cfg['defaulttheme'] нарушает это соответствие.
Данное правило распространяется на все ресурсы темы: CSS, JavaScript, изображения, шрифты и любые другие файлы, расположенные внутри папки темы.
Справочная таблица: когда использовать $cfg['defaulttheme'], а когда Cot::$usr['theme']
Ниже — таблица, построенная исключительно на основе анализа исходного кода Cotonti (system/common.php, system/functions.php, system/resources.php, system/admin/admin.functions.php). Каждая строка — реальный случай использования, взятый из движка.
Таблица 1. Легитимные случаи использования $cfg['defaulttheme']
| № | Файл / место в коде | Задача | Почему именно $cfg['defaulttheme'] | Пример из исходника |
|---|---|---|---|---|
| 1 | system/common.php, инициализация массива $usr | Задать значение по умолчанию до того, как пользователь определён | На момент создания массива данных пользователя ещё нет. Нужно какое-то стартовое значение. Для гостя это и есть тема сайта по умолчанию | 'theme' => $cfg['defaulttheme'], |
| 2 | system/common.php, вычисление $usr['theme'] для авторизованного | Форсировать тему для всех пользователей | Если администратор включил forcedefaulttheme, движок обязан взять глобальную тему, а не личные предпочтения пользователя | $usr['theme'] = $cfg['forcedefaulttheme'] ? $cfg['defaulttheme'] : $row['user_theme']; |
| 3 | system/common.php, проверка существования шапки | Подменить отсутствующую тему на дефолтную | Пользовательская тема физически отсутствует. Единственный разумный fallback — тема сайта по умолчанию | $usr['theme'] = $cfg['defaulttheme']; (после if (!file_exists($mtheme))) |
| 4 | system/common.php, финальная ошибка fallback | Признать полный отказ темизации | Даже тема по умолчанию недоступна. Дальше только аварийное завершение | if (!file_exists($mtheme)) { cot_diefatal($L['com_defthemefail']); } |
| 5 | system/functions.php, функция cot_schemeFile() | Вернуть путь к CSS-файлу цветовой схемы | Функция может быть вызвана до инициализации $usr. Если $usr['theme'] ещё не задан — берётся значение по умолчанию | $theme = isset($usr['theme']) ? $usr['theme'] : $cfg['defaulttheme']; |
Вывод по таблице 1: $cfg['defaulttheme'] применяется только в трёх ролях:
- стартовое значение (инициализация);
- форсированное значение (
forcedefaulttheme = true); - аварийный fallback (тема недоступна).
Во всех остальных случаях — это не тот источник.
Таблица 2. Места, где $cfg['defaulttheme'] использовать нельзя, а нужно Cot::$usr['theme']
| № | Файл / место в коде | Задача | Почему Cot::$usr['theme'] | Пример из исходника |
|---|---|---|---|---|
| 1 | system/common.php, подключение .rc.php темы | Найти файл ресурсов текущей темы | Файл физически подключён из папки {$usr['theme']}. Значит, и внутри файла $usr['theme'] = имя этой темы | include "{$cfg['themes_dir']}/{$usr['theme']}/{$usr['theme']}.rc.php"; |
| 2 | system/common.php, подключение {theme}.php | Файл переопределения $L/$R | Привязан к папке текущей темы, а не к глобальной настройке | $sys['theme_resources'] = "{$cfg['themes_dir']}/{$usr['theme']}/{$usr['theme']}.php"; |
| 3 | system/common.php, языковой файл темы | Загрузить переводы текущей темы | Тема пользователя может отличаться от defaulttheme | $usr['theme_lang'] = "{$cfg['themes_dir']}/{$usr['theme']}/{$usr['theme']}.{$usr['lang']}.lang.php"; |
| 4 | system/common.php, шаблон шапки | Найти header.tpl | Привязан к папке текущей темы | $mtheme = "{$cfg['themes_dir']}/{$usr['theme']}/header.tpl"; |
| 5 | system/functions.php, cot_tplfile() | Найти любой .tpl текущей темы | Все шаблоны фронта лежат в папке $usr['theme'] | $theme = !empty($usr['theme']) ? $usr['theme'] : ''; |
| 6 | system/common.php, .rc.php темы (внутренняя логика) | Пути к ассетам темы | Файл подключён из папки именно этой темы | $themeDir = Cot::$cfg['themes_dir'] . '/' . Cot::$usr['theme']; |
| 7 | system/resources.php, additionalFiles() для @select2 | Поиск i18n-файла Select2 под язык пользователя | Привязан к языку, а тема тут ни при чём — но пример показывает, что тематические ресурсы привязаны к контексту пользователя | $select2i18n = 'lib/select2/js/i18n/' . Cot::$usr['lang'] . '.js'; |
Вывод по таблице 2: всё, что относится к файлам внутри папки темы (CSS, JS, шаблоны, языки, .rc.php, .php), обязано использовать Cot::$usr['theme'].
Таблица 3. Админский контекст: где $cfg['defaulttheme'] и $usr['theme']не работают и нужен третий источник
| № | Файл / место в коде | Задача | Какую переменную использовать | Пример из исходника |
|---|---|---|---|---|
| 1 | system/common.php, языковой файл админ-темы | Загрузить переводы админ-темы | $cfg['admintheme'] | $usr['def_theme_lang'] = "{$cfg['themes_dir']}/admin/{$cfg['admintheme']}/{$cfg['admintheme']}.en.lang.php"; |
| 2 | system/common.php, файл ресурсов админ-темы | Подключить {admintheme}.php | $cfg['admintheme'] | $sys['theme_resources'] = "{$cfg['themes_dir']}/admin/{$cfg['admintheme']}/{$cfg['admintheme']}.php"; |
| 3 | system/common.php, путь к шаблонам админки | Найти .tpl админ-темы | $cfg['admintheme'] | Используется в cot_tplfile() через переменную $adminTheme |
| 4 | system/admin/admin.functions.php | Подключение ресурсов | Cot::$cfg['admintheme'] | Resources::addFile(Cot::$cfg['themes_dir'] . '/admin/' . Cot::$cfg['admintheme'] . '/assets/...'); |
| 5 | system/common.php, иконпак | Иконки для интерфейса | $cfg['defaulticons'] (fallback), $usr['icons'] (основное) | if (empty($usr['icons'])) { $usr['icons'] = $cfg['defaulticons']; } |
Вывод по таблице 3: в админском контексте используется третья переменная — $cfg['admintheme']. Ни defaulttheme, ни usr['theme'] для админских шаблонов не подходят.
Таблица 4. Сводная матрица: какой переменной пользоваться в каком контексте
| Контекст | Правильная переменная | Обоснование |
|---|---|---|
| Пути к CSS/JS темы фронта | Cot::$usr['theme'] | Файлы физически лежат в themes/{usr['theme']}/ |
Пути к .tpl темы фронта | Cot::$usr['theme'] | Все шаблоны фронта привязаны к папке темы пользователя |
Пути к .php темы фронта (.rc.php, {theme}.php, {theme}.lang.php) | Cot::$usr['theme'] | Эти файлы подключаются именно из папки usr['theme'] |
| Аварийный fallback при отсутствии темы | $cfg['defaulttheme'] | Единственный разумный источник при отказе |
Инициализация массива $usr до определения пользователя | $cfg['defaulttheme'] | Стартовое значение |
Форсированная тема (forcedefaulttheme = true) | $cfg['defaulttheme'] | Прямое назначение флага |
| Пути к CSS/JS админ-темы | $cfg['admintheme'] | Админка использует отдельную тему |
Пути к .tpl админ-темы | $cfg['admintheme'] | Аналогично |
| Языковые файлы админ-темы | $cfg['admintheme'] | Аналогично |
| Аварийное завершение при отсутствии темы по умолчанию | $cfg['defaulttheme'] | Только для проверки cot_diefatal() |
Таблица 5. Практические подстановки: что писать в конкретном файле
| Файл | Что писать | Почему |
|---|---|---|
themes/{theme}/{theme}.rc.php | Cot::$cfg['themes_dir'] . '/' . Cot::$usr['theme'] . '/...' | Файл подключён движком из папки текущей темы |
themes/{theme}/{theme}.php | $L[...], $R[...] (без путей) | Переопределения строк, не привязаны к папке |
themes/admin/{admintheme}/{admintheme}.rc.php | Cot::$cfg['themes_dir'] . '/admin/' . Cot::$cfg['admintheme'] . '/...' | Админ-тема задаётся отдельно |
themes/admin/{admintheme}/{admintheme}.php | $L[...], $R[...] (без путей) | Переопределения строк админки |
system/functions.php, хелперы | $usr['theme'] ?? $cfg['defaulttheme'] | Fallback на случай отсутствия $usr['theme'] |
system/common.php, начальная инициализация | $cfg['defaulttheme'] | Пользователь ещё не определён |
system/common.php, вычисление $usr['theme'] | $cfg['forcedefaulttheme'] ? $cfg['defaulttheme'] : $row['user_theme'] | Форсирование или личный выбор |
system/common.php, fallback | $cfg['defaulttheme'] | Единственный разумный источник при отказе |
Таблица 6. Антипаттерны: где $cfg['defaulttheme'] использовать нельзя и почему
| № | Что пишут ошибочно | Почему это ошибка | Что должно быть |
|---|---|---|---|
| 1 | Внутри {theme}.rc.php: Cot::$cfg['themes_dir'] . '/' . Cot::$cfg['defaulttheme'] . '/assets/...' | Файл подключён из папки usr['theme']. Путь уводит в другую папку при расхождении | Cot::$cfg['themes_dir'] . '/' . Cot::$usr['theme'] . '/assets/...' |
| 2 | Внутри {theme}.rc.php: Cot::$cfg['themes_dir'] . '/' . Cot::$cfg['defaulttheme'] . '/js/...' | Аналогично | Cot::$cfg['themes_dir'] . '/' . Cot::$usr['theme'] . '/js/...' |
| 3 | Внутри {theme}.php: ссылки на файлы темы через defaulttheme | Файл относится к текущей теме, а не к глобальной настройке | $usr['theme'] |
| 4 | В шаблонах темы: {PHP.cfg.defaulttheme} для путей к ассетам | В шаблоне можно использовать {PHP.usr.theme} — тогда путь всегда корректен | {PHP.usr.theme} |
| 5 | В админ-теме: Cot::$cfg['defaulttheme'] для путей к админ-ассетам | Админка использует отдельную тему, заданную в $cfg['admintheme'] | Cot::$cfg['admintheme'] |
| 6 | В админ-теме: Cot::$usr['theme'] для путей к админ-ассетам | Пользовательская тема фронта не имеет отношения к админ-интерфейсу | Cot::$cfg['admintheme'] |
Таблица 7. Быстрая шпаргалка «что взять в данной ситуации»
| Ситуация | Источник |
|---|---|
Файл .rc.php темы фронта подключается движком | Cot::$usr['theme'] |
Файл .php темы фронта (переопределения $L/$R) | Без путей — только $L/$R |
Файл .rc.php админ-темы подключается движком | Cot::$cfg['admintheme'] |
Файл .php админ-темы (переопределения $L/$R) | Без путей — только $L/$R |
Глобальная функция, которая может быть вызвана до $usr | $usr['theme'] ?? $cfg['defaulttheme'] |
Инициализация $usr для гостя | $cfg['defaulttheme'] |
| Форсирование темы для всех пользователей | $cfg['defaulttheme'] |
| Аварийный fallback при отсутствии темы | $cfg['defaulttheme'] |
Пути к шаблонам фронта (cot_tplfile()) | Cot::$usr['theme'] |
Пути к шаблонам админки (cot_tplfile()) | Cot::$cfg['admintheme'] |
Ключевые правила по итогам таблиц
$cfg['defaulttheme']— только три роли: инициализация, форсирование, аварийный fallback.Cot::$usr['theme']— все пути к файлам внутри папки текущей темы фронта.$cfg['admintheme']— все пути к файлам внутри папки админ-темы.$usr['theme'] ?? $cfg['defaulttheme']— компромисс для глобальных функций с неопределённым контекстом.- Ни в
.rc.php, ни в{theme}.php, ни в шаблонах фронта нельзя подставлять$cfg['defaulttheme']для путей к ассетам текущей темы.