Книга для разработчиков

Введение

Описание алгоритмов работы CMS, чтобы было понятно как писать код для нее и модифицировать.

В отличии от многих других CMS, использующих различные паттерны типа MVC (Model View Controller), Coffee CMS написана в процедурном стиле, без использования ООП (Объектно-Ориентированного Программирования) и это так и задумано. Чтобы для разработки под нее не требовалось изучать множество разных концепций. Чтобы код был минималистичным, а не разбросанным по тысячам файлов.

Взаимодействие модулей происходит через изменение глобальной переменной $cms. Да, это поругиваемый подход, но он позволяет сильно изменять поведение CMS без изменения кода ядра.

Существует много концепций и паттернов призванных ускорить и упростить доработки CMS, но они хороши для самих разработчиков CMS и плохи для тех кто такую CMS сопровождает. Coffee CMS в первую очередь пытается упростить жизнь сопровождающим. Именно поэтому в ней используются "плохие" практики. Если у вас возникнут предложения по улучшениям, но в рамках именно такого подхода, то оставляйте комментарии на сайте или пишите по любым другим каналам связи указанным на странице поддержки.

Основы работы - Хуки

Вся работа движка Coffee CMS крутится вокруг одного глобального ассоциативного массива $cms.

В нем содержится цепочка хуков в $cms["hooks"]. Хук это некое событие к которому модули прикрепляют свои функции.

Основных событий четыре:

Когда событие происходит, то все функции, прикрепленные к нему, поочередно вызываются. Когда все функции выполнятся, осуществляется переход к следующему хуку, записанному в $cms["hooks"]["query"]["next"]. Т.е. все хуки связаны в цепочку. Это позволяет определять логику поведения CMS, менять ее на лету и отключать ненужные хуки путем установки $cms["hooks"]["query"]["disabled"] = true; что вызовет пропуск хука и переход к следующему. Когда встретится пустой next CMS завершит свою работу.

Функциям при прикреплении можно задавать приоритет выполнения. По умолчанию он равен 10. Чем меньше число, тем раньше выполнится функция. Прикрепленная функция выглядит так:

$cms["hooks"]["query"][5]["cms_base_connect"] = true;

Отдельные функции можно отключать на лету, устанавливая в false.

Кроме того любая функция может сама инициировать запус хука вызовом функции do_hook( "hook_name" );. Так, например, делает модуль карты сайта, давая возможность другим модулям добавить в карту сайта свои ссылки.

Основы работы - Роутинг

Роутинг, или по другому маршрутизация, это тоже важная концепция работы CMS-ок. В зависимости от URL запроса, CMS должна вести себя по разному. Модули могут добавлять в $cms["urls"] регулярные выражения для хвоста URL и хук, который должен запуститься. Например так:

$cms["urls"]["^/admin_url$"] = "admin";
$cms["hooks"]["admin"]["next"] = "template";
$cms["urls"]["^/api_url$"] = "api";
$cms["urls"]["^/cron_url$"] = "cron";

Именно так это и происходит и это дополнительные три хука, для функционирования соответственно админки, выполнения ajax-запросов на сохранение настроек и выполнения периодических задач по таймеру.

Настройки CMS

Все настройки хранятся в файле .cms/config.php который создается при установке. Этот файл содержит экспортированную переменную $cms["config"] при помощи функции var_export(). Настройки каждого модуля хранятся в отдельном подмассиве с именем этого модуля. Такой подход, всмысле использование php-файла, позволяет быстро их загружать, независимо от наличия соединения с базой данных, а так же избавляет от необходимости писать парсеры и экпортеры данных. Встроенных средств php вполне достаточно. Кроме того PHP умеет кешировать opcache.enable=1 в php.ini и файл находится в памяти в откомпилированном виде. При сохранении его на диск вызывается функция opcache_invalidate() которая заставит PHP перечитать файл при следующем его включении в код командой include().

Структура папок

Все файлы CMS хранятся в папке .cms что позволяет в корне сайта размещать что угодно, в том числе и сгенерированные страницы. И последующее к ним обращение из браузера не запускает CMS. Файлы отдаются с диска веб-сервером.

Файлы и папки начинающиеся на точку считаются скрытыми и прямой доступ к ним запрещен. Но веб-сервер, через файл .htaccess, настраивается так, что всегда обращается к файлу .cms/index.php. Если приходит запрос /mytpl/css/style.css, то идет попытка найти файл .cms/mytpl/css/style.css, и если он есть то он копируется в корневую папку по пути указанному в запросе и отдается браузеру. Если на диске уже имеется такой файл, то он не перезаписывается. Единственная тут странность в том, что если файл был на диске, то такого запроса к CMS быть не может. Но на самом деле может, если два запроса поступили почти одновременно и файл еще не успел создаться. Но ничего страшного не произойдет, второй файл перезапишет первый. Создание файлов в корневой папке происходит атомарно и веб сервер не может отдать частично записанный файл.

Меню в шаблоне

В админке можно настроить каждое меню, в какую область его выводить. Список областей и переводы на разные языки задаются в файле template.settings.php лежащем в папке шаблона. Пример того как это делается можно подсмотреть в шаблоне mini в файле .cms/mini/template.settings.php.

Если вы хотите сделать сайт на разных языках, в шаблоне проверять условия и в зависимости от условий выводить меню на русском menu( "header_en" ); или меню на английском menu( "header_en" );, то недостаточно добавить эти строки. Нужно так же описать области в файле template.settings.php. Без этого вы не сможете в админке настроить какое меню куда выводится. Админка просто не будет знать об этих областях.

// Берем имя текущего шаблона
$tpl = $cms["config"]["template.mod.php"]["template"];
// Определяем переводы меню для админки
$cms["lang"][$tpl]["ru_RU.UTF-8"]["Header Ru"] = "Верхнее на русском";
$cms["lang"][$tpl]["ru_RU.UTF-8"]["Header En"] = "Верхнее на английском";
// Описываем области
$cms["menu_areas"]["header_ru"] = __( "Header Ru", $tpl );
$cms["menu_areas"]["header_en"] = __( "Header En", $tpl );