Видеогалерея на MIGX. Может кому понадобится (решено)
*Помогите толком разобраться как это все привести в божеский вид на fenom
Видеогалерея на MIGX
Видеогалерея на MIGX
- Устанавливаем VideoGallery
- Создаем tv с именем video тип ввода VideoGallery
- Создаем tv с именем videogallery. Тип ввода migx, конфигурация videogallery, выбираем шаблон для отображения
- Создаем сниппет VideoJsonToPlaceholders
<?php // Получаем параметры $json = $modx->getOption('json', $scriptProperties, ''); $prefix = $modx->getOption('prefix', $scriptProperties, 'json.'); // 1. Проверяем наличие данных if (empty($json)) { return 'Ошибка: JSON‑строка пуста'; } // 2. Декодируем HTML‑экранирование $json = htmlspecialchars_decode($json); // 3. Исправляем экранированные слеши $json = str_replace('\\/', '/', $json); // 4. Парсим JSON $data = json_decode($json, true); if (json_last_error() !== JSON_ERROR_NONE) { return 'Ошибка JSON: ' . json_last_error_msg() . ' (строка: ' . htmlspecialchars($json) . ')'; } // 5. Проверяем, что результат — массив if (!is_array($data)) { return 'Ошибка: JSON не содержит массив'; } // 6. Устанавливаем плейсхолдеры с обработкой foreach ($data as $key => $value) { // Приводим строки к UTF‑8 if (is_string($value)) { $value = mb_convert_encoding($value, 'UTF-8', 'UTF-8'); } // Преобразуем videoDuration из PT... в оптимальный формат if ($key === 'videoDuration') { if (empty($value) || !is_string($value)) { $value = '0 с'; // или '' — на ваш выбор } else { // Извлекаем часы, минуты, секунды preg_match( '/PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?/', $value, $matches ); $hours = isset($matches[1]) ? (int)$matches[1] : 0; $minutes = isset($matches[2]) ? (int)$matches[2] : 0; $seconds = isset($matches[3]) ? (int)$matches[3] : 0; // Формируем строку в зависимости от наличия компонентов if ($hours > 0) { // Есть часы: выводим HH:MM:SS $value = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds); } elseif ($minutes > 0) { // Нет часов, но есть минуты: выводим MM:SS $value = sprintf('%02d:%02d', $minutes, $seconds); } else { // Только секунды: выводим SS с $value = $seconds . ' с'; } } } // Подставляем значения по умолчанию для критических полей switch ($key) { case 'title': if (empty($value)) { $value = 'Без названия'; } break; case 'desc': if (empty($value)) { $value = 'Описание отсутствует'; } break; } // Устанавливаем плейсхолдер $modx->setPlaceholder($prefix . $key, $value); } return ''; - Создаем новое MIGx поле videogallery
- Экспортируем туда конфиг
{ "formtabs": [ { "caption": "Видеогалерея", "print_before_tabs": "0", "fields": [ { "field": "video", "caption": "Видео", "inputTV": "video" } ], "pos": 1 } ], "contextmenus": "", "actionbuttons": "", "columnbuttons": "", "filters": "", "extended": { "actionbuttonsperrow": 4, "gridload_mode": 1, "has_jointable": "yes" }, "permissions": {}, "fieldpermissions": "", "columns": [ { "header": "Рендер", "dataIndex": "render", "width": 1, "sortable": "false", "show_in_grid": 0, "renderer": "this.renderChunk", "renderchunktpl": "[[!VideoJsonToPlaceholders? &json=`[[+video]]` &prefix=`video.`]]" }, { "header": "Название", "dataIndex": "video_title", "sortable": "false", "show_in_grid": 1, "renderer": "this.renderChunk", "renderchunktpl": "[[+video.title]]" }, { "header": "Видео", "dataIndex": "video_video", "sortable": "false", "show_in_grid": 1, "renderer": "this.renderChunk", "renderchunktpl": "<iframe src=\"[[+video.video]]\" width=\"160\" height=\"90\" frameborder=\"0\"></iframe>" }, { "header": "Превью", "dataIndex": "video_image", "sortable": "false", "show_in_grid": 1, "renderer": "this.renderChunk", "renderchunktpl": "<img src=\"[[+video.image]]\" width=\"160\">" }, { "header": "Время", "dataIndex": "video_duration", "width": 100, "sortable": "false", "show_in_grid": 1, "renderer": "this.renderChunk", "renderchunktpl": "[[+video.videoDuration]]" }, { "header": "videoId", "dataIndex": "video_videoId", "sortable": "false", "show_in_grid": "0", "renderer": "this.renderChunk", "renderchunktpl": "[[+video.videoId]]" }, { "header": "Описание", "dataIndex": "video_description", "sortable": "false", "show_in_grid": 1, "renderer": "this.renderChunk", "renderchunktpl": "[[+video.desc]]" } ], "category": "" }
minishop3 - не сохраняется в карточке товара "Остаток на складе"
Добрый день!
Поставила minishop3.
В админке, в свойстве товара есть стандартный параметр «Остаток на складе» (stock). Ввожу количество, сохраняю. При обновлении поле остаётся пустое.
Что нужно поправить?
Поставила minishop3.
В админке, в свойстве товара есть стандартный параметр «Остаток на складе» (stock). Ввожу количество, сохраняю. При обновлении поле остаётся пустое.
Что нужно поправить?
mFilter 1.1.0 - большое обновление
- Улучшено построение фильтров на основе TV
- Улучшено построение фильтров на базе опций
- Новые полезные сниппеты
- SEO улучшения
- И просто ряд исправлений
mSync и moysklad.ru
Подскажите, mSync отправляет заказы в MoySklad?
Компонент не обновлялся с 2023 года. Работает ли все сейчас на текущих версиях склада и ModX 2.8.8?
Компонент не обновлялся с 2023 года. Работает ли все сейчас на текущих версиях склада и ModX 2.8.8?
ms3DemoData - компонент для быстрой генерации демо-данных MiniShop3

Генератор демо-данных MiniShop3: производителей, категорий, товаров, клиентов и заказов. Незаменим для тестирования магазина, демонстрации клиентам и разработки. Доступен для бесплатного использования в modstore.pro
Как удалить с сайта счетчик Google Analytics?
Доброго времени суток. Столкнулся с тем что не могу удалить счетчик Google Analytics,.т.к. не понимаю где он может находится. Если открыть код главной страницы сайта в браузере то показывает что счетчик под футером. Посмотрел в админке шаблоны, чанки но ничего не нашел. Где ещё может находится счетчик?
CustomExtra 3.0.0-beta для MODX3
Визуальный конструктор xPDO-объектов для MODX3. Создавайте кастомные таблицы, поля и связи через интерфейс админки без написания XML-схем вручную.

— Визуальный конструктор объектов — создание классов и таблиц через UI
— Настраиваемые поля — все типы данных MySQL (varchar, int, text, datetime и др.)
— Связи между объектами — Composite и Aggregate с настройкой cardinality
— Автогенерация — PHP-классы и таблицы создаются автоматически
— Динамические пункты меню — быстрый доступ к данным из админки
— CRUD-интерфейс — управление записями без написания кода
— Интеграция с pdoTools — вывод данных на сайте

Возможности
— Визуальный конструктор объектов — создание классов и таблиц через UI
— Настраиваемые поля — все типы данных MySQL (varchar, int, text, datetime и др.)
— Связи между объектами — Composite и Aggregate с настройкой cardinality
— Автогенерация — PHP-классы и таблицы создаются автоматически
— Динамические пункты меню — быстрый доступ к данным из админки
— CRUD-интерфейс — управление записями без написания кода
— Интеграция с pdoTools — вывод данных на сайте
MiniShop3 1.2.0 - 1.3.0 Самое интересное
Друзья, взял за правило, выпускать еженедельные релизы с исправлениями багов, которые вы старательно присылаете, а также с поэтапными улучшениями системы, основанными на ваших же вопросах и предложениях.
Мне не хватает времени и желания описывать каждый релиз отдельно, потому сегодня обзор самого интересного за месяц в честь выхода версии 1.3.0
Мне не хватает времени и желания описывать каждый релиз отдельно, потому сегодня обзор самого интересного за месяц в честь выхода версии 1.3.0
Fenom.js: шаблонизатор в стиле Fenom.php для JavaScript и Vite

Привет!
Это моя первая статья на modx.pro — и первый полноценный асинхронный шаблонизатор Fenom.js
Попытка перенести привычный синтаксис Fenom.php в мир JavaScript и современных сборщиков.
Сниппет getPageBlockContent для вывода блоков PageBlocks (Free версия) с других страниц в MODX
В бесплатной версии PageBlocks нет встроенного инструмента для вывода блоков с другой страницы. Этот сниппет решает задачу через xPDO-запрос к таблице pbBlockValue. Он позволяет выводить указанные блоки с любого ресурса, с опциями сортировки, лимита и обёртки.