Плагин dharmashop/imageresize входит в общий пакет. Настройки находятся в Настройки магазина → Изображения → Размеры изображений по контекстам. Используется нативная повторяемая таблица Joomla, без своего JS/CSS. Загрузчик, его папки, имена файлов и прежняя конвертация WebP сохранены.
Настройки
- Обрабатывать изображения — общий выключатель. Также можно выключить сам плагин; тогда возвращается исходный URL.
- Папка кеша — отдельная папка внутри
images, по умолчаниюimages/dharmashop/cache/resized. - Выбор контекста — штатный список Joomla с поиском по названию, в повторяемых строках размеров и в команде подготовки.
- Контексты и размеры — каждый контекст добавляется один раз. Удаление строки отключает обработку в этом месте. Явно пустой список отключает все контексты. До первого сохранения используются стандартные строки.
- Ширина/высота: целые числа 0–2400. 0 = авто. Например,
0 × 400ограничивает высоту и рассчитывает ширину по пропорциям. При одной нулевой стороне применяется вписывание независимо от режима; обрезки и искажения нет.0 × 0возвращает оригинал без конвертации. Автоматически рассчитанная сторона также ограничена 2400 px. - Вписать — сохранить пропорции внутри указанных границ; Обрезать — заполнить прямоугольник и обрезать по центру; Растянуть — точные пропорции прямоугольника. Маленькие оригиналы не увеличиваются.
- Формат — по общей настройке WebP, WebP, JPEG, PNG, формат оригинала.
- Качество JPEG/WebP — одно общее поле рядом с переключателем конвертации WebP; 20–100, по умолчанию 82. Его используют загрузчик, команда миграции и плагин размеров. Отдельных качеств в строках контекстов нет, прежние значения строк игнорируются. PNG сжимается без потерь. Смена качества не перекодирует сохранённые исходники; производные получают новый ключ и обновляются при обращении.
Совместимость с WebP
Загрузчик конвертирует новые файлы при включённом image_convert_webp; существующая команда миграции обрабатывает старые загрузки. Плагин размеров не заменяет эти механизмы: он читает выбранный файл и создаёт отдельную производную.
Формат «По общей настройке WebP» использует WebP при включённой общей настройке, иначе сохраняет формат исходника. Явный формат строки имеет приоритет. Переключение формата/качества/размера создаёт другой ключ кеша. Повторного перекодирования кешированной копии нет: каждая производная строится непосредственно из выбранного исходника.
Для email.product и email.logo используются JPEG/PNG, даже если выбраны WebP/формат оригинала. PNG стоит по умолчанию; JPEG удобнее для фотографий, когда важен небольшой вес. Прозрачность при JPEG заменяется белым фоном. Это правило не меняет изображения на сайте.
Реестр контекстов
Стандартные строки используют вписывание и формат по общей настройке WebP; для email — PNG. Качество берётся из общего image_quality (по умолчанию 82).
| Контекст | Место | Размер по умолчанию |
|---|---|---|
product.category.grid | Товары категории, бренда, бейджа: сетка | 600 × 600 |
product.category.list | Те же товары: список | 320 × 320 |
product.category.table | Те же товары: таблица | 112 × 112 |
product.related.grid | Связанные товары: сетка | 600 × 600 |
product.related.list | Связанные товары: список | 320 × 320 |
product.main | Большое фото в галерее товара | 1000 × 1000 |
product.brand | Логотип бренда на странице товара | 240 × 120 |
product.thumb | Миниатюры галереи | 160 × 160 |
product.lightbox | Фото, открываемое из галереи | 1800 × 1800 |
category.card, brand.card, badge.card | Карточки разделов | 600 × 400 |
category.header, brand.header, badge.header | Изображение текущего раздела | 1200 × 600 |
landing.header | Картинка посадочной страницы (com_dharmashop_landing) | 1200 × 600 |
landing.card | Карточка посадочной страницы в списке страниц | 600 × 400 |
shipping.option | Изображение способа доставки на странице оформления | 96 × 96 |
payment.option | Изображение способа оплаты на странице оформления | 96 × 96 |
cart.module | Модуль/боковая корзина | 144 × 144 |
cart.page | Страница корзины | 192 × 192 |
cart.toast | Уведомление об успешном добавлении | 128 × 128 |
favorites.item | Не используется с 2026-10-13: карточки избранного берут пресеты каталога (product.category.grid/list/table), чтобы выглядеть как в каталоге | — |
search.module | Картинка в подсказках поиска | 112 × 112 |
search.grid | Результаты поиска: сетка | 600 × 600 |
search.list | Результаты поиска: список | 320 × 320 |
search.table | Результаты поиска: таблица | 112 × 112 |
module.products.grid | Модуль товаров: сетка | 600 × 600 |
module.products.list | Модуль товаров: список | 320 × 320 |
module.products.slider | Модуль товаров: слайдер | 600 × 600 |
module.categories.grid | Модуль категорий: сетка | 600 × 400 |
module.categories.accordion | Модуль категорий: аккордеон | 600 × 400 |
module.categories.slider | Модуль категорий: слайдер | 600 × 400 |
field.option | Картинки вариантов дополнительных полей | 96 × 96 |
field.color.admin | Цвет: радиокнопки в админке | 96 × 96 |
field.color.filter | Цвет: радиокнопки в фильтре | 96 × 96 |
field.color.card | Цвет: образец в списке товаров | 96 × 96 |
field.color.page | Цвет: образец на полной странице | 96 × 96 |
field.video.poster | Обложки видеогалерей | 640 × 360 |
admin.product, admin.group, admin.category | Миниатюры списков админки | 96 × 96 |
email.product | Фото товара в письме (вывод 64 px) | 128 × 128 |
email.logo | Логотип магазина в письме | 320 × 160 |
seo.social | Open Graph / Twitter и изображение Product JSON-LD | 1200 × 630 |
Контексты карточек модуля товаров выбираются по его макету и используют тот же плагин размеров и кеш, что остальные страницы витрины. Больший размер email относительно вывода даёт запас для экранов с высокой плотностью пикселей.
Хранение кеша
admin.group — обложка группы в административном списке, вывод 48×48. Автоматически дополняет сохранённые наборы пресетов; явно заданные настройки сохраняются. Предварительная подготовка включена для галерей групп в ImageInventory.
images/dharmashop/cache/resized/
v2/
ab/
cd/
600x400-contain-q82-<хеш-источника>-<хеш-варианта>.webp
Сначала версия алгоритма, затем два уровня по двум hex-символам хеша источника. Это до 65 536 корзин; папки создаются только по мере необходимости. Все размеры одного источника остаются в одной корзине.
Общий кеш между контекстами: контекст выбирает настройки, но не входит в путь или ключ файла. Один исходник + одинаковые ширина/высота, режим, итоговый формат и качество = одна копия, один URL и одна блокировка, даже при одновременном обращении разных контекстов. Например, cart.module и search.module с 0 × 80, вписыванием и WebP будут использовать один файл. Другой исходник, формат или режим даёт отдельный вариант. Одинаковые файлы по разным исходным путям не сравниваются по содержимому.
В ключ входят параметры в фиксированном порядке после определения реального формата: «формат исходника» для JPEG и явный JPEG совпадают, как и fallback WebP → PNG при отсутствии кодировщика. Для PNG используется постоянное сжатие без потерь; общее качество JPEG/WebP не создаёт дополнительных PNG-копий.
В начале имени — заданные границы размера, режим и качество (lossless для PNG). Нулевая сторона обозначается auto, например autox400-contain-q82-…webp. При вписывании фактический размер может быть меньше указанных границ. Хеши в конце сохраняют уникальность. Старые файлы из v1/<контекст>/… автоматически не переименовываются и не удаляются; новые обращения используют общий v2. Настройки контекстов сохраняются.
Ключ варианта учитывает время изменения и размер исходного файла, размеры, режим, формат и качество. Обновление исходника или настроек создаёт новый файл, старые ссылки не перезаписываются. При внешней замене файла с сохранением и времени, и длины нужно обновить его mtime (touch) либо путь. Запись защищена flock, временный файл переименовывается атомарно. Соседний .lock остаётся для согласования параллельных запросов.
Ненужные старые производные автоматически не удаляются. Очистка запускается вручную через «Товары → Команды», после просмотра количества и объёма; исходники и загрузки не затрагиваются. Смена папки кеша также не удаляет прежнюю. Папку кеша исключать из резервных копий можно: при следующем обращении производные восстанавливаются, если сохранились исходники. Доступ к оригиналам должен оставаться ограничен теми же правилами, что до обработки.
Подготовка и очистка
В Товары → Команды добавлены два пункта; оба открывают отдельный нативный экран. Доступ — core.manage, изменяющие действия — только POST с CSRF-токеном. Открытие страницы не запускает генерацию или удаление.
- Подготовить изображения: выбрать один действующий контекст или все, нажать «Начать подготовку». Действующие настройки и сам плагин используются через
ImageUrl, отдельной конвертации нет. Обложки/галерея товаров, категории/бренды/бейджи, варианты полей, корневые разделы и логотип обходятся по ID без OFFSET; неопубликованные записи включены. Счётчики показывают обращения к вариантам, а не число уникальных новых файлов: уже готовые копии и повторные ссылки учитываются. Неподдерживаемые/внешние/отсутствующие файлы и fallback плагина показаны как оставшиеся оригиналами. - Очистить кеш изображений: сначала «Проверить кеш», посмотреть количество и объём, затем «Подтвердить очистку». Очистка общая, поскольку копия может использоваться несколькими контекстами. Обходятся только известные имена производных в текущей папке, версии v1/v2 и два уровня хеша. Неизвестные файлы, symlink, исходники, файлы кеша, выбранные как исходники в данных магазина, остаются. Ссылки перепроверяются перед началом удаления; это снимок ссылок, поэтому во время очистки не выбирайте файлы кеша как новые исходники. Новые копии после старта проверки пропускаются. На каждый файл берётся неблокирующая общая с генератором блокировка; занятые/недоступные файлы остаются и учитываются в ошибках.
.lockи каталоги сохраняются, чтобы не создавать гонки блокировок. Прежние папки при смене настройки кеша не очищаются.
На POST — до 400 шагов с бюджетом 3,5 секунды между операциями (одна GD-операция может длиться дольше); курсор хранится в сессии администратора. Для большой коллекции нажимать «Продолжить обработку» до завершения. «Сбросить обработку» очищает только курсор: уже подготовленные/удалённые копии не откатываются. Изменение настроек требует сброса; после очистки копии создаются при обращении либо новой подготовкой. Ограничения защиты: до 20 000 записей в одном каталоге кеша и до 5 000 ссылок на кеш как источник, при превышении — остановка, не удаление.
Реализация: ImageInventory (источники/контексты), ImageMaintenance (порции), ImageCache (обход/защищённое удаление), ImagecommandsController и нативная Form/view. При добавлении нового вида изображений дополнить ImageInventory, чтобы предварительная подготовка знала источник и очистка защищала его ссылки. Контексты товаров по стандартным префиксам подключаются автоматически.
Ограничения и письма
Обрабатываются только читаемые локальные JPEG/PNG/WebP/AVIF своего сайта. SVG и GIF остаются исходными (анимация сохраняется). Внешние URL не скачиваются. При отсутствии GD, неподдерживаемом формате, ошибке или превышении ограничений возвращается оригинал. Защитные пределы: исходный файл до 32 МБ, до 24 млн пикселей, проверка доступной памяти до декодирования. Кеш не выходит за реальную папку сайта.
Email-плагин сначала получает производную, затем встраивает её как CID. Ограничения вложений: 256 КиБ на файл, 2 МиБ суммарно. Тяжёлый оригинал при недоступном ресайзе не прикрепляется, остаётся ссылка на изображение; внешние файлы также не скачиваются. Лимиты не гарантируют загрузку внешней картинки почтовым клиентом. Для меньшего письма выберите JPEG у фото, PNG у логотипа.
Как добавить контекст
- Добавить стабильный ID и стандартные размеры в
Administrator\Image\ImageContexts::SIZES. Использовать латиницу, цифры, точки/подчёркивания/дефисы, до 80 символов; не переименовывать действующие ID. - Добавить RU/EN ключ
COM_DHARMASHOP_IMAGE_CONTEXT_<ID В ВЕРХНЕМ РЕГИСТРЕ, ТОЧКИ ЗАМЕНЕНЫ НА _>. - В нужном макете получать URL через общий помощник; HTML обязательно экранировать:
use Dharma\Component\DharmaShop\Administrator\Image\ImageUrl;
$url = ImageUrl::resolve((string) $item->cover, 'module.products.grid');
?>
<img src="<?= htmlspecialchars($url, ENT_QUOTES, 'UTF-8') ?>" alt="">
- Обновить этот реестр и
LAYOUTS.md. Если настройки уже сохранены, администратор добавляет новую строку кнопкой+; обновление не переписывает выбранные им размеры и удалённые контексты.
Общая карточка product-card/default.php принимает $displayData['imageContext']. Модуль товаров передаёт module.products.grid, .list или .slider; без контекста карточка выбирает product.category.<вид>, а на странице поиска — search.<вид>. В переопределении шаблона нужно сохранить вызов помощника, иначе оно продолжит выводить исходники.
Событие и файлы
ImageUrl::resolve($source, $context) отправляет Joomla Event onDharmaShopImagePrepare, группа dharmashop. Аргументы: request: ImageRequest (readonly source/context, изменяемый url) и settings: Registry (копия настроек компонента). Подписчик меняет $request->url. Без обработчика остаётся безопасный абсолютный URL. Результаты повторных обращений к паре источник/контекст кешируются внутри запроса; отдельных SQL-запросов каталога на картинку нет.
- Ядро:
com_dharmashop/admin/src/Image/{ImageUrl,ImageRequest,ImageContexts}.php. - Нативная форма:
admin/forms/image_preset.xml,Field/{Imagesizes,Imagecontext}Field.php,Rule/ImagepresetsRule.php. Таблица размеров содержит десятки строк, поэтому список контекстов в строке не выводится целиком:ImagecontextFieldкладёт в строку только выбранное значение, остальные подставляетmedia/js/image-context.jsпри первом обращении к списку (значения приходят один раз через script options). Страница настроек магазина стала меньше примерно на 0.4 МБ и на несколько тысяч узлов, а экземпляры Choices.js для строк не создаются. - Плагин:
plg_dharmashop_imageresize/src/Extension/ImageResize.php,src/Image/Resizer.php. - Пакет включает плагин; первая установка включает его, обновление сохраняет ручное отключение.
seo.social использует общий механизм размеров, WebP и дедупликации. При уже сохранённом списке пресетов новую строку добавляют в настройках «Изображения»; без строки доступен исходный безопасный URL. Вписывание по умолчанию сохраняет товар целиком. При построении только крошек изображения предков не подготавливаются.
ImageInventory включает seo.social для обложек товаров, изображений/SEO-изображений разделов, SEO-изображений товаров и общего SEO-изображения; команда «Подготовить изображения» может подготовить их заранее.
Дополнительная галерея полей (2026-10-09)
Тип поля gallery регистрирует контексты field.gallery.card (240×180), field.gallery.page (600×450) и field.gallery.lightbox (1800×1800). Макет витрины вызывает ImageUrl::resolve для превью и увеличенного изображения. ImageInventory включает строки field_media с field_id > 0 и mime IS NULL, а также category_field_media с mime IS NULL, во все три контекста; основная галерея товара с field_id=0 сохраняет прежние продуктовые контексты. Файлы документов с MIME не обрабатываются.
Тип video использует контекст field.video.poster (640×360) для сохранённых API-обложек роликов. Обложки лежат в field_media.alt, получаются только из разрешённых API и хранятся локально под field-video-posters; общий ImageUploader применяет общие ограничения и WebP. ImageInventory выбирает только строки с mime LIKE 'application/vnd.dharmashop.video.%' и передаёт путь обложки в общий ресайзер. Локальные видео не попадают в список источников изображений.
Группы товаров (C87, 2026-10-09)
group.choice (96×96) — образец поля выбора исполнения; автоматически дополняет сохранённые наборы пресетов. Фото товара/группы используют прежние продуктовые контексты. ImageInventory включает group_media и образцы field_options; ImageCleaner защищает ссылки галереи группы. Своя галерея сохраняется при наследовании, исключение материализует эффективные фото. Для макетов группы зарегистрированы group.teaser.grid (600×600), group.teaser.list (480×480), group.teaser.table (112×112). Они автоматически дополняют сохранённые наборы пресетов; ImageInventory включает обложки товаров и галереи групп для этих контекстов. Подключение самих единиц групп в запрос списка остаётся этапом фильтра.
Пикер товаров (2026-10-09): admin.picker.field (128×128 для превью 64×64) и admin.picker.modal (96×96 для строки 48×48). Оба дополняют старые сохранённые пресеты, обложки товаров включены в ImageInventory для подготовки. Первичный серверный вывод и данные выбранного товара из диалога используют один ProductPicker::presentation и ImageUrl::resolve; прямых URL оригинала в макетах нет.
Пикер групп товаров (2026-10-09): admin.picker.group (96×96 для фото 48×48 в диалоге productgroups/modal). Дополняет сохранённые пресеты через существующий префикс admin.picker; ImageInventory подготавливает этот контекст для изображений группы из group_media. Вызов ImageUrl::resolve — при пакетной подготовке строк HtmlView, подписи RU/EN.
Участник группы (2026-10-09): admin.picker.member (128×128 для превью 64×64), независимо от admin.picker.field. Поле modal_groupmember и payload диалога используют ProductPicker::presentation/ImageUrl; добавлены RU/EN подписи, пресеты и ImageInventory уже поддерживают префикс admin.picker.
Образец цвета участника группы (2026-10-10): admin.picker.member.choice (64×64 для вывода 24×24), собственный контекст в ImageContexts и RU/EN. Изображение значения разрешается через ImageUrl; инвентаризация значений поля включает этот контекст.
Размеры в разметке и пресеты для новых контекстов (2026-10-13)
widthиheightу изображений. Изображение, выводимое черезImageUrl::resolve(), получает реальные размеры итоговой картинки:ImageUrl::size($source, $context)возвращает[ширина, высота],ImageUrl::attrs($source, $context)— готовые атрибутыwidth="…" height="…"для тегаimg(резерв места под картинку, меньше сдвигов макета при загрузке). Размеры заполняет плагин нарезки (ImageRequest::$width/$height,Resizer::dimensions()читает только заголовок локального файла); для чужих адресов, SVG и при выключенной нарезке размеров нет, атрибуты не выводятся. Атрибуты есть у карточек товаров, групп, категорий, брендов, бейджей, страницы товара (галерея), заголовков разделов, посадочных страниц, модулей товаров, галерей и постеров видео из полей.- Open Graph. Страница отдаёт
og:image:widthиog:image:heightкартинки контекстаseo.social. - Контексты без сохранённого пресета. Если настройки изображений были сохранены до появления контекста (связанные товары,
seo.social, посадочные страницы и т. п.), для него действует размер по умолчанию из реестра, а не оригинал. Строка с размером 0 × 0 в настройках по-прежнему означает «отдавать оригинал». - Вывод в своих макетах:
<img src="<?php echo $escape(ImageUrl::resolve($src, $context)); ?>"<?php echo ImageUrl::attrs($src, $context); ?> …>.