Сергей Карпович
С нами с 29 декабря 2020; Место в рейтинге пользователей: #274amoConnector - наследник компонента amoCRM

Представляю вашему вниманию amoConnector — компонент интеграции сайта на MODX 2 с системой amoCRM. Построен на официальном SDK amoCRM и использует OAuth 2.0 авторизацию.
В компоненте постарался решить все известные проблемы предшественника
- Сложная авторизация и обновление ключей
- Поиск ID для воронок и статусов
- Неудобное сравнение полей форм с AMO полями
Видеогалерея на MIGX. Может кому понадобится (решено)
*Помогите толком разобраться, как редактировать поля title, desc, image, duration, которые находятся внутри json массива у видео в виде отдельных полей, а не кривыми ручками
Видеогалерея на MIGX
Видеогалерея на MIGX
- Устанавливаем VideoGallery
- Создаем tv с именем video тип ввода VideoGallery
- Создаем tv с именем videogallery. Тип ввода migx, конфигурация videogallery, выбираем шаблон для отображения
- Создаем сниппет VideoJsonToPlaceholders
! ВНИМАНИЕ в п.2 удалите пробел между & quot;
<?php // Получаем параметры $json = $modx->getOption('json', $scriptProperties, ''); $prefix = $modx->getOption('prefix', $scriptProperties, 'json.'); // 1. Проверяем наличие данных if (empty($json)) { return 'Ошибка: JSON‑строка пуста'; } // 2. Удаляем все & quot; из строки ! Внимание в следующей строке удалите пробел между & quot; $json = str_replace('& quot;', '', $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. Функция для извлечения корневого адреса (с защитой от повторного объявления) if (!function_exists('getRootUrl')) { function getRootUrl($url) { if (!filter_var($url, FILTER_VALIDATE_URL)) { return null; } $parsed = parse_url($url); if (!$parsed || !isset($parsed['scheme']) || !isset($parsed['host'])) { return null; } $root = $parsed['scheme'] . '://' . $parsed['host']; if (isset($parsed['port'])) { $isDefaultHttp = ($parsed['scheme'] === 'http' && $parsed['port'] === 80); $isDefaultHttps = ($parsed['scheme'] === 'https' && $parsed['port'] === 443); if (!$isDefaultHttp && !$isDefaultHttps) { $root .= ':' . $parsed['port']; } } return $root; } } // 7. Устанавливаем плейсхолдеры с обработкой foreach ($data as $key => $value) { // Приводим строки к UTF‑8 if (is_string($value)) { $value = mb_convert_encoding($value, 'UTF-8', 'UTF-8'); } // Если это поле video и содержит URL — извлекаем корневой адрес if ($key === 'video' && !empty($value)) { $rootUrl = getRootUrl($value); if ($rootUrl) { $modx->setPlaceholder($prefix . 'video_root', $rootUrl); } // Сохраняем исходный URL $modx->setPlaceholder($prefix . 'video', $value); } // Преобразуем 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) { $value = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds); } elseif ($minutes > 0) { $value = sprintf('%02d:%02d', $minutes, $seconds); } else { $value = $seconds . ' с'; } } } // Подставляем значения по умолчанию для критических полей switch ($key) { case 'title': if (empty($value)) { $value = 'Без названия'; } break; case 'desc': if (empty($value)) { $value = 'Описание отсутствует'; } break; } // Устанавливаем плейсхолдер (если он ещё не установлен через парсинг) if (!in_array($key, ['video', 'video_root'])) { $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": "" }
Compare - сравнение товаров miniShop2 и MiniShop3
Привет!
UPD 09.02.2026: для MODX 3 и MiniShop3 выпущена платная обновленная версия дополнения: Compare.
Весь текст ниже относится к связке MODX 2 + miniShop2.
Сегодня выложил в github свою наработку с одного из сайтов — дополнение под названием Compare, которое умеет сравнивать товары.

UPD 09.02.2026: для MODX 3 и MiniShop3 выпущена платная обновленная версия дополнения: Compare.
Весь текст ниже относится к связке MODX 2 + miniShop2.
Сегодня выложил в github свою наработку с одного из сайтов — дополнение под названием Compare, которое умеет сравнивать товары.

pbStudio: Создаём сайт с PageBlocks – настройка и главная страница
В этом уроке мы установим MODX, настроим необходимые компоненты и системные параметры для работы с PageBlocks. Затем создадим главную страницу и добавим на неё два блока. Это часть серии уроков, в которых мы пошагово создадим полноценный сайт для студии с использованием PageBlocks.


Похожие товары в карточке товара (как поиск по яндекс картинкам)
Наконец дошли руки анонсировать первый релиз дополнения — IDImage, которое позволяет находить визуально похожие изображения товаров на сайте.
Определяет, насколько одно изображение похоже на другое, используя векторные представления, полученные через сервис idimage.ru, основанный на обученной нейросети.

Что делает дополнение:
Определяет, насколько одно изображение похоже на другое, используя векторные представления, полученные через сервис idimage.ru, основанный на обученной нейросети.

[HolidaysContent] Вывод контента в определённую дату и/или период времени
Всем привет, поступила банальная на первый взгляд задача, выводить в праздничные дни оформление тематическое… Всё бы ничего, просто написать сниппет который проверяет текущую дату и выводит чанк при совпадении… Но как быть с новым годом? Заказчик просит с 20.12 текущего года, по 10.01 соответственно следующего года показывать снег на сайте, тут уже нужно учитывать период, год начала и конца события.
Тёмная тема для сайтов на MODX
Всем привет!
Сейчас становится всё более актуально создавать сайты не только адаптивными под разные устройства, но также и с акцентом на использование в разное время суток — то есть с возможностью переключения светлой и тёмной темы.
Обратил внимание, что у многих на мобильных устройствах включена тёмная тема на постоянной основе и все приложения открываются в соответствии с системной темой. В данной статье я расскажу, как сделать сайт удобным при любом из сценариев использования тёмной темы на устройствах пользователя.
Сейчас становится всё более актуально создавать сайты не только адаптивными под разные устройства, но также и с акцентом на использование в разное время суток — то есть с возможностью переключения светлой и тёмной темы.
Обратил внимание, что у многих на мобильных устройствах включена тёмная тема на постоянной основе и все приложения открываются в соответствии с системной темой. В данной статье я расскажу, как сделать сайт удобным при любом из сценариев использования тёмной темы на устройствах пользователя.
[easyRedirects] Еще один компонент для управления редиректами
Привет!
easyRedirects — дополнение для управления редиректами (с возможностью выбора кода ответа из 301, 302, 307, 308) в панели управления сайтами.
Для MODX есть несколько компонентов, которые позволяют из админки управлять редиректами со старых url на новые. Из тех, что знаю я — это Redirector (наверное самый первый компонент, ему 10+ лет точно, но надо сказать, его периодически обновляют), и autoRedirector. Кстати, они поддерживают только 301 редирект, а вот 302 или более свежие 307 и 308 — нет.
При попытке применить их на моем сайте выплыли проблемы:
1. Redirector не позволял создать редирект на произвольный url, он обязательно хотел видеть в качестве цели существующий ресурс. А мне так не нужно было, у меня страницы генерируются своим плагином, обрабатывающим событие OnPageNotFound, т.е. целевого ресурса как такового на сайте нет.
2. autoRedirector больше заточен на отслеживание измененных url, ну и у него та же особенность — конечный url редиректа должен принадлежать существующему ресурсу.
В общем в итоге пара вечеров и готова первая версия easyRedirects. По сути это сильно модифицированный и дополненный Redirector.
easyRedirects — дополнение для управления редиректами (с возможностью выбора кода ответа из 301, 302, 307, 308) в панели управления сайтами.
Для MODX есть несколько компонентов, которые позволяют из админки управлять редиректами со старых url на новые. Из тех, что знаю я — это Redirector (наверное самый первый компонент, ему 10+ лет точно, но надо сказать, его периодически обновляют), и autoRedirector. Кстати, они поддерживают только 301 редирект, а вот 302 или более свежие 307 и 308 — нет.
При попытке применить их на моем сайте выплыли проблемы:
1. Redirector не позволял создать редирект на произвольный url, он обязательно хотел видеть в качестве цели существующий ресурс. А мне так не нужно было, у меня страницы генерируются своим плагином, обрабатывающим событие OnPageNotFound, т.е. целевого ресурса как такового на сайте нет.
2. autoRedirector больше заточен на отслеживание измененных url, ну и у него та же особенность — конечный url редиректа должен принадлежать существующему ресурсу.
В общем в итоге пара вечеров и готова первая версия easyRedirects. По сути это сильно модифицированный и дополненный Redirector.
Вывод MIGX галерей из разных ресурсов с пагинацией
Всем привет.
Имеется структура ресурсов:
-Раздел
--Категория 1
--Категория 2
--Категория 3
В Категориях фото загружены через MIGX и выводится сниппетом pdoPage:
Параметр parents игнорируется, и поле gallery тянется только из текущего ресурса.
Параметр docid — принимает только один параметр и тоже не подходит
Пробовал корректировать по этому методу: webstool.ru/pdopage-i-getimagelist-postranichnaya-navigacziya-migx.html
Но в итоге сниппет дублирует элементы, по 2 раза выводит
Имеется структура ресурсов:
-Раздел
--Категория 1
--Категория 2
--Категория 3
В Категориях фото загружены через MIGX и выводится сниппетом pdoPage:
{'!pdoPage' | snippet : [
'element' => 'getImageList',
'limit' => '11',
'tvname' => 'gallery',
'tvPrefix' => '',
'tpl' => 'tpl-gallery',
'includeTVs' => 'gallery',
'processTVs' => 'gallery',
'prepareTVs' => 'gallery',
'includeContent' =>'1',
'toPlaceholder' => 'result',
'sort'=> '[{"sortby":"MIGX_id","sortdir":"DESC"}]'
]}Вопрос, есть ли возможность вывести общую галерею в Разделе, используя Migx галереи из категорий 1,2,3 с пагинацией?Параметр parents игнорируется, и поле gallery тянется только из текущего ресурса.
Параметр docid — принимает только один параметр и тоже не подходит
Пробовал корректировать по этому методу: webstool.ru/pdopage-i-getimagelist-postranichnaya-navigacziya-migx.html
Но в итоге сниппет дублирует элементы, по 2 раза выводит
CKEditor "на максималках", расширение функционала визуального редактора
Всем привет! Решил установить пару плагинов в CKEditor, и меня понесло)
Собрал и перевёл на русский все рабочие плагины для этого компонента.
Обновил сам CKEditor до версии 4.25-LTS (Long Term Support)
Добавил функцию выбора ресурса для ссылок! Спасибо @Дима Касаткин и Степан Гончаров!
Теперь он воспринимает Excel таблицы, умеет генерировать QR коды изображением, создавать диаграммы, оформлять контент в Bootstrap «сетке», создавать Bootstrap вкладки, подсвечивать исходный код, считать кол-во слов и параграфов и многое другое…
Так же, теперь он выглядит как редактор MS Word!
UPD. Обновление самой библиотеки CKEditor + новый плагин autogrow.
UPD. 01.11.24 Новые плагины — вставка изображений со внешних источников и красивые уведомления: uploadfile, uploadwidget, notificationaggregator, filetools.

Собрал и перевёл на русский все рабочие плагины для этого компонента.
Обновил сам CKEditor до версии 4.25-LTS (Long Term Support)
Добавил функцию выбора ресурса для ссылок! Спасибо @Дима Касаткин и Степан Гончаров!
Теперь он воспринимает Excel таблицы, умеет генерировать QR коды изображением, создавать диаграммы, оформлять контент в Bootstrap «сетке», создавать Bootstrap вкладки, подсвечивать исходный код, считать кол-во слов и параграфов и многое другое…
Так же, теперь он выглядит как редактор MS Word!
UPD. Обновление самой библиотеки CKEditor + новый плагин autogrow.
UPD. 01.11.24 Новые плагины — вставка изображений со внешних источников и красивые уведомления: uploadfile, uploadwidget, notificationaggregator, filetools.
