StaticFilesPlus — автоматическое создание статических элементов с поддержкой категорий
Плагин для MODX 3, который автоматически сохраняет чанки, шаблоны, сниппеты и плагины в статические файлы при их сохранении в админке.
Зачем это нужно?
При разработке на MODX удобно работать с элементами через IDE (PhpStorm, VS Code и др.), используя Git для версионирования. Плагин автоматизирует создание статических файлов и правильно организует их по категориям с транслитерацией русских названий.
Возможности
Установка
Если хотите изменить базовый путь сохранения файлов, поправьте системную настройку: pdotools_elements_path
Плагин создаёт следующую структуру:
Код плагина
После установки рекомендуется отключить кеширование для корректной работы:
Вопросы, критика и предложения приветствуются!
Зачем это нужно?
При разработке на MODX удобно работать с элементами через IDE (PhpStorm, VS Code и др.), используя Git для версионирования. Плагин автоматизирует создание статических файлов и правильно организует их по категориям с транслитерацией русских названий.
Возможности
- Автоматическое создание файлов — сохраняете элемент в админке, файл создаётся автоматически
- Поддержка категорий — файлы размещаются в папках по категориям с учётом иерархии
- Транслитерация — русские названия категорий преобразуются в латиницу (например: «Дизайн сайта» → «dizayn_sayta»)
- Использует настройку pdotools_elements_path — не нужно хардкодить пути
Установка
- Создайте новый плагин в админке: Элементы → Плагины → Создать плагин
- Скопируйте код плагина (см. ниже)
- Привяжите к событиям:
- OnChunkFormSave — для чанков;
- OnTempFormSave — для шаблонов;
- OnSnipFormSave — для сниппетов;
- OnPluginFormSave — для плагинов;
- Сохраните.
Если хотите изменить базовый путь сохранения файлов, поправьте системную настройку: pdotools_elements_path
По умолчанию файлы сохраняются в core/elements/Структура файлов
Плагин создаёт следующую структуру:
core/elements/
├── chunks/
│ ├── header/
│ │ └── mainMenu.tpl
│ └── dizayn_sayta/
│ └── colors.tpl
├── templates/
│ └── osnovnye/
│ └── base.tpl
├── snippets/
│ └── helpers/
│ └── getPrice.php
└── plugins/
└── custom/
└── myPlugin.phpПримеры транслитерации категорий- Дизайн → dizayn
- Дизайн сайта → dizayn_sayta
- Header & Footer → header_footer
- API Helpers → api_helpers
Код плагина
<?php
/**
* StaticFilesPlus
*
* @events OnChunkFormSave,OnTempFormSave,OnSnipFormSave,OnPluginFormSave
*/
$eventName = $modx->event->name;
$events = [
'OnChunkFormSave' => ['type' => 'chunks', 'extension' => 'tpl'],
'OnTempFormSave' => ['type' => 'templates', 'extension' => 'tpl'],
'OnSnipFormSave' => ['type' => 'snippets', 'extension' => 'php'],
'OnPluginFormSave' => ['type' => 'plugins', 'extension' => 'php']
];
if (!isset($events[$eventName])) {
return;
}
$config = $events[$eventName];
// Получаем элемент
$element = null;
switch ($eventName) {
case 'OnChunkFormSave':
$element = isset($chunk) ? $chunk : null;
break;
case 'OnTempFormSave':
$element = isset($template) ? $template : null;
break;
case 'OnSnipFormSave':
$element = isset($snippet) ? $snippet : null;
break;
case 'OnPluginFormSave':
$element = isset($plugin) ? $plugin : null;
break;
}
if (!$element) {
return;
}
// Получаем базовый путь
$basePath = $modx->getOption('pdotools_elements_path', null, '');
if (empty($basePath)) {
$basePath = MODX_CORE_PATH . 'elements/';
} else {
if (strpos($basePath, '/') !== 0 && strpos($basePath, ':') === false) {
$basePath = MODX_BASE_PATH . $basePath;
}
}
$basePath = rtrim($basePath, '/') . '/';
$typePath = $basePath . $config['type'] . '/';
// Получаем путь категории с транслитерацией через MODX API
$categoryPath = '';
$categoryId = (int) $element->get('category');
if ($categoryId > 0) {
$path = [];
$category = $modx->getObject('modCategory', $categoryId);
if ($category) {
$maxDepth = 10;
$depth = 0;
while ($category && $depth < $maxDepth) {
$categoryName = (string) $category->get('category');
if (!empty($categoryName)) {
// Используем встроенный метод MODX для транслитерации
$categoryName = $modx->filterPathSegment($categoryName);
// Заменяем пробелы на подчёркивания
$categoryName = str_replace([' ', '-'], '_', $categoryName);
// Приводим к нижнему регистру
$categoryName = strtolower($categoryName);
if (!empty($categoryName)) {
array_unshift($path, $categoryName);
}
}
$parentId = (int) $category->get('parent');
if ($parentId > 0) {
$category = $modx->getObject('modCategory', $parentId);
} else {
break;
}
$depth++;
}
}
if (!empty($path)) {
$categoryPath = implode('/', $path) . '/';
}
}
$fullPath = $typePath . $categoryPath;
// Создаём директорию
if (!file_exists($fullPath)) {
if (!mkdir($fullPath, 0755, true) && !is_dir($fullPath)) {
return;
}
}
// Формируем имя файла
$elementName = $element->get('name');
if (empty($elementName)) {
return;
}
$fileName = $elementName . '.' . $config['extension'];
$filePath = $fullPath . $fileName;
// Получаем содержимое
$content = (string) $element->get('content');
if ($config['extension'] === 'php' && strpos($content, '<?php') !== 0) {
$content = "<?php\n" . $content;
}
// Сохраняем файл
if (file_put_contents($filePath, $content) === false) {
return;
}
// Обновляем элемент
$relativePath = str_replace($basePath, '', $filePath);
$mediaSourceId = 1;
$staticMediaSource = $modx->getObject('sources.modMediaSource', ['class_key' => 'sources.modFileMediaSource']);
if ($staticMediaSource) {
$mediaSourceId = (int) $staticMediaSource->get('id');
}
$element->set('static', true);
$element->set('static_file', $relativePath);
$element->set('source', $mediaSourceId);
$element->save();Преимущества перед аналогом StaticFiles:- Использует настройку pdotools_elements_path вместо жёстко заданного пути
- Создаёт подпапки по категориям
- Поддерживает вложенные категории
- Транслитерирует русские названия
- Работает с MODX 3
- MODX Revolution 3.x
- PHP 8.0+
После установки рекомендуется отключить кеширование для корректной работы:
- cache_default → false
- cache_resource → false
- Плагин автоматически добавляет <?php в начало PHP-файлов, если его нет.
- Если категория не задана, файл сохраняется в корень папки типа элемента.
- Работает только с событиями сохранения формы (OnFormSave), не с прямым сохранением объектов.
Вопросы, критика и предложения приветствуются!
Комментарии: 4
Если хотите изменить базовый путь сохранения файлов, поправьте системную настройку: pdotools_elements_pathТ.е. pdoTools установлен, зачем же тогда создавать статические чанки, шаблоны и сниппеты?
Статические элементы нужны для работы с Git, версионирования и командной разработки. Удобно создавать элементы быстро в админке, а затем дорабатывать их в IDE с подсветкой синтаксиса, автодополнением и всеми инструментами современного редактора. Также это позволяет синхронизировать элементы между окружениями (локальная → тестовая → продакшн) через систему контроля версий, что критично для командной работы.
Спрошу по-другому, почему просто не использовать файловые элементы, не создавая их в админке?
Ну я к примеру очень часто использую плагин PageBlocks (free версию — он не поддерживает файловые чанки (которых нет в админке) в своих вызовах — ну или я что то не знаю). В общем я создаю в нем нужные конфиги блоков, создаю для них чанки — этим чанкам после сохранения, ставится галка статический и создается файловый чанк, в котором я уже потом пишу код (как то так)
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.