1 плагин - 3 лайвхака
Всем привет, порой работа менеджеров в админке modx — сущий ад. Сегодня поступил заказ с просьбой решить несколько проблем.
Проблема №1:
В tinyMCE все изображения которые вставляются имеют атрибуты width и height, и не имеют нужных классов
Проблема №2:
При загрузки файлов в каталог, где уже есть такое имя, файлы переписывают друг друга, необходимо было сделать добавление префикса для файлов с одинаковым именем
Проблема №3:
Иногда менеджеры грузят неприлично большие изображения, что непосредственно влияет и на скорость загрузки страницы и на общий размер файлов
Что делает плагин:
Создаем плагин с любым именем и даем ему 3 события:
Радуемся!
Всем спасибо за внимание :)
Проблема №1:
В tinyMCE все изображения которые вставляются имеют атрибуты width и height, и не имеют нужных классов
Проблема №2:
При загрузки файлов в каталог, где уже есть такое имя, файлы переписывают друг друга, необходимо было сделать добавление префикса для файлов с одинаковым именем
Проблема №3:
Иногда менеджеры грузят неприлично большие изображения, что непосредственно влияет и на скорость загрузки страницы и на общий размер файлов
Что делает плагин:
- Транслитерация файлов при загрузке, добавление префикса если файл дублируется
- Уменьшает загружаемое изображение до 1200px по ширине
- Из поля content достает все img, вырезает у них атрибуты width и height, вместо них подставляет класс img-thumbnail
Установка
Создаем плагин с любым именем и даем ему 3 события:
- OnFileManagerBeforeUpload
- OnFileManagerUpload
- OnLoadWebDocument
<?php
switch ($modx->event->name) {
//Работа с контентом
case 'OnLoadWebDocument':
$content = $modx->resource->content;
$content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'); //исправляем ошибки кодировки
$dom = new DOMDocument;
$dom->loadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$imgs = $dom->getElementsByTagName('img'); //ищем все изображения
foreach ($imgs as $img) {
//убираем атрибуты width и height, добавляем класс
$img->removeAttribute('width');
$img->removeAttribute('height');
$img->setAttribute('class', 'img-thumbnail');
}
//компилируем html и устанавливаем
$html = $dom->saveHTML();
$modx->resource->set('content', $html);
break;
case 'OnFileManagerBeforeUpload':
setlocale(LC_ALL, 'ru_RU.utf8'); //фикс для неправильных серверов, иначе не будет работать patchinfo с кириллицей
$fullPath = $source->getBases()['pathAbsolute'].$directory; //получаем абсолютную дирректорию
$dir = scandir($fullPath);
foreach ($files as $key => $file) {
$info = pathinfo($file['name']);
$name = $info['filename'];
$name = modResource::filterPathSegment($modx, $name); //транслитерация
$extension = $info['extension'];
$fullname = $name.'.'.$extension;
//ищем файлы с таким же названием в этой директории
if (!in_array($fullname, $dir)) {
$newFullName = $fullname;
} else {
$newFullName = $name.'_'.rand(1,999999).'.'.$extension;
}
$file['name'] = $newFullName;
$modx->event->params['file'] = $file; //отдаем изменненную переменную file
$files[$key] = $file;
}
$modx->event->params['files'] = $files; //отдаем изменненную переменную files
break;
case 'OnFileManagerUpload':
$fullPath = $source->getBases()['pathAbsolute'].$directory;
foreach ($files as $file) {
if(strripos($file['type'], 'image') === false) { //если не изображение, не запускаем phpThumb
return ;
}
$name = $file['name'];
$pathToImage = $fullPath.$name;
//Массив параметров для phpThumb
$params = array(
'w' => 1200 ,
);
$phpThumb = $modx->getService('modphpthumb','modPhpThumb', MODX_CORE_PATH . 'model/phpthumb/', array()); //Подключаем класс phpThumb
$phpThumb->setSourceFilename($pathToImage);
foreach ($params as $k => $v) {
$phpThumb->setParameter($k, $v);
}
if ($phpThumb->GenerateThumbnail()) {
if (!$phpThumb->renderToFile($pathToImage)) {
$modx->log(1, 'Ошибка сохранения изображения в ['.$pathToImage.']');
}
}
else {
$modx->log(1, print_r($phpThumb->debugmessages, 1));
}
}
break;
}
gist.github.com/pavel-one/17db1b5cff8c2713f28976439e05f945Радуемся!
Всем спасибо за внимание :)
Поблагодарить автора
Отправить деньги
Комментарии: 23
Круто! Я в RTE почти всегда забиваю классы для изображений и пользователь может выбирать их. А тут получается как альтернативный вариант, без визивига. Могу дополнить пост, в закромах лежал плагин транслитерации папок.
Работает как с translit, как с yTranslit, так с и любым другим компонентом транслитерации.
Работает как с translit, как с yTranslit, так с и любым другим компонентом транслитерации.
switch($modx->event->name) {
case 'OnFileManagerDirCreate':
case 'OnFileManagerDirRename':
$basePath = $source->getBasePath();
$dirName = basename($directory);
$name = array_pop(array_filter(explode(DIRECTORY_SEPARATOR, $directory)));
$tmpDoc = $modx->newObject('modResource');
$newName = $tmpDoc->cleanAlias($name);
if(strcmp($name, $newName) === 0) {
return;
}
$oldPath = str_replace(realpath($basePath), '', $directory);
$bases = $source->getBases($oldPath);
$oldPath = $bases['pathAbsolute'].$oldPath;
$oldDirectory = $source->fileHandler->make($oldPath);
if (!($oldDirectory instanceof modDirectory)) {
return false;
}
if (!$oldDirectory->isReadable() || !$oldDirectory->isWritable()) {
return false;
}
$newPath = $source->fileHandler->sanitizePath($newName);
$newPath = $source->fileHandler->postfixSlash($newPath);
$newPath = dirname($oldPath).'/'.$newPath;
/* Транслитерация папки */
if (!$oldDirectory->rename($newPath)) {
$modx->log(modX::LOG_LEVEL_ERROR, 'Ошибка транслитерации папки!');
return false;
}
break;
}
Круто) Спасибо, полезно)
Вообще со стороны tinyMCE это делать конечно более рационально, т.к. не нужно каждый раз при генерации страницы тратить время на лишнюю обработку дома, но как показали тесты, времени это добавляет не много, да и для уже заполненных сайтов удобнее)
Вообще со стороны tinyMCE это делать конечно более рационально, т.к. не нужно каждый раз при генерации страницы тратить время на лишнюю обработку дома, но как показали тесты, времени это добавляет не много, да и для уже заполненных сайтов удобнее)
Павел, а как допустим сделать так, чтобы изображения резались в определенной папке и, к примеру, во всех вложенных папках? Например, у меня есть папка img и в ней несколько папок-дочек, папок-внучек и т.д. и во всех них мне при загрузке изображения нужно отслеживать ширину и обрезать по заданным размерам.
И еще вопрос. Как из одного изображения в тексте статьи нарезать несколько уменьшенных для использования с scrset?
Спасибо.
И еще вопрос. Как из одного изображения в тексте статьи нарезать несколько уменьшенных для использования с scrset?
Спасибо.
Павел, а как допустим сделать так, чтобы изображения резались в определенной папке и, к примеру, во всех вложенных папкахПросто вот тут: gist.github.com/pavel-one/17db1b5cff8c2713f28976439e05f945#file-plugin-php-L29 необходимо добавить свои проверки директории. К примеру текущий путь через explode разбить на массив и проверять есть ли в пути папки которые вам нужны
Как из одного изображения в тексте статьи нарезать несколько уменьшенных для использования с scrset?Тут все немного сложнее, необходимо понять на каком этапе вам нужно резать их, при сохранении ресурса/рендеринге страницы/etc. Но принцип один, вам нужно загнать все содержимое в PHPDomDocument пройтись по всем изображениям, забрать все пути, ну а дальше уже дело техники.
Спасибо.
Код за вас я писать не буду, простите :)
Код за вас я писать не буду, простите :)Сложновато пока для меня все это, учитывая мой теперешний уровень знаний. Но за подсказки все равно спасибо!
Павел, а как допустим сделать так, чтобы изображения резались в определенной папке и, к примеру, во всех вложенных папках?Я хоть и не Павел ?, но добавлю к подсказке:
if(strripos($file['type'], 'image') === false) { //если не изображение, не запускаем phpThumb
return ;
}
Вот тут производится проверка расширения файла, идёте и смотрите документацию и увидите, что в событие приходит как раз directory в которой будет хранится путь.Ваша задача к данной проверке добавить еще и свою логику.
directory — это директория относительно источника файлов, так что тут не совсем верно, я выше дал ссылку на строку где определяется абсолютная директория
А такой плагин замены img в контенте не сильно нагружает загрузку страницы? Не лучше ли пробежаться по старым ресурсам одним циклом для замены, а для новых ресурсов поставить плагин на сохранение ресурса?
Без плагина:
С плагином
Я думаю ответ очевиден)
С плагином
Я думаю ответ очевиден)
круто, спасибо))
Отлично! Спасибо.
Транслитерацию папок тоже добавил
Транслитерацию папок тоже добавил
Вопрос.
По логике, правильнее добавлять class, а не зарезать существующие…
foreach ($imgs as $img) {Код
//убираем атрибуты width и height, добавляем класс
$img->removeAttribute('width');
$img->removeAttribute('height');
$img->setAttribute('class', 'img-thumbnail');
}
$img->setAttribute('class', 'img-thumbnail');заменяет любой уже присвоенный class.
По логике, правильнее добавлять class, а не зарезать существующие…
Да. В моих реалиях контент менеджеры не проставляют вообще никакие классы изображениям, я выложил код для моих реалий, если бы это было оформлено в компонент и продавалось бы за деньги, я бы подумал о кейсах использования. Если вы считаете что-то в коде нелогичным — выкладывайте свою реализацию, заодно поможете людям с кейсом использования как у вас
Спасибо большое, как раз нужно было ресайз изображений делать при загрузке :)
Страное дело. Журнал ошибок пишет:
[2019-02-02 20:52:36] (ERROR @ *******/core/cache/includes/elements/modplugin/27.include.cache.php : 14) PHP warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 3
[2019-02-02 20:52:36] (ERROR @ *******/core/cache/includes/elements/modplugin/27.include.cache.php : 14) PHP warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 4
[2019-02-02 20:52:36] (ERROR @ *******/core/cache/includes/elements/modplugin/27.include.cache.php : 14) PHP warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 5
[2019-02-02 20:52:36] (ERROR @ *******/core/cache/includes/elements/modplugin/27.include.cache.php : 14) PHP warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 6
[2019-02-02 20:52:36] (ERROR @ *******/core/cache/includes/elements/modplugin/27.include.cache.php : 14) PHP warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 7
[2019-02-02 20:52:36] (ERROR @ *******/core/cache/includes/elements/modplugin/27.include.cache.php : 14) PHP warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 8
[2019-02-02 20:52:36] (ERROR @ *******/core/cache/includes/elements/modplugin/27.include.cache.php : 14) PHP warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 9
[2019-02-02 20:52:36] (ERROR @ *******/core/cache/includes/elements/modplugin/27.include.cache.php : 14) PHP warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 10
[2019-02-02 20:52:36] (ERROR @ *******/core/cache/includes/elements/modplugin/27.include.cache.php : 14) PHP warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 11
[2019-02-02 20:52:36] (ERROR @ *******/core/cache/includes/elements/modplugin/27.include.cache.php : 14) PHP warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 12
[2019-02-02 20:52:38] (ERROR @ *******/core/cache/includes/elements/modplugin/27.include.cache.php : 14) PHP warning: DOMDocument::loadHTML(): Unexpected end tag : p in Entity, line: 30
[2019-02-02 20:52:39] (ERROR @ *******/core/cache/includes/elements/modplugin/27.include.cache.php : 14) PHP warning: DOMDocument::loadHTML(): Unexpected end tag : p in Entity, line: 30
Файл 27.include.cache.php<?php
// modx.pro/development/16940
switch ($modx->event->name) {
//Работа с контентом
case 'OnLoadWebDocument':
$content = $modx->resource->content;
$content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'); //исправляем ошибки кодировки
$dom = new DOMDocument;
$dom->loadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$imgs = $dom->getElementsByTagName('img'); //ищем все изображения
foreach ($imgs as $img) {
//убираем атрибуты width и height, добавляем класс
$img->removeAttribute('width');
$img->removeAttribute('height');
// $img->setAttribute('className', 'img-responsive');
// kalina ***
$class = $img->getAttribute( 'class' );
$img->setAttribute('class', $class . ' img-fluid' );
}
//компилируем html и устанавливаем
$html = $dom->saveHTML();
$modx->resource->set('content', $html);
break;
Что это может быть?
Столкнулся с необычным поведением DOMDocument.
есть код в content
Перемещается окончание заголовка h2 в самый конец. Вот вывод в логи переменной $html
Подскажите, что нужно прописать, что бы не ломало верстку и лишние теги не добавлялись?
есть код в content
<h2>Назначение стационарных углекислотных резервуаров</h2>
<ul>
<li>Длительное хранение (неограниченный срок) жидкой углекислоты с минимальными потерями продукта. </li>
<li>Подача углекислоты на линию потребления. </li>
<li>Заправка любых емкостей жидкой углекислотой. </li>
</ul>
<p> </p>
<h2>Выгодные особенности углекислотных резервуаров</h2>
после использования loadHTML и saveHTML для обработки content, достаточно только загрузить данные и сохранить$content = $modx->resource->content;
$content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'); //исправляем ошибки кодировки
libxml_use_internal_errors(true);
$dom = new DOMDocument;
if ($dom->loadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD)){
//компилируем html и устанавливаем
$html = $dom->saveHTML($dom->documentElement);
$modx->resource->set('content', $html);
}
break;
получаю поломанную верстку.Перемещается окончание заголовка h2 в самый конец. Вот вывод в логи переменной $html
<h2>Назначение стационарных углекислотных резервуаров<ul>
<li>Длительное хранение (неограниченный срок) жидкой углекислоты с минимальными потерями продукта. </li>
<li>Подача углекислоты на линию потребления. </li>
<li>Заправка любых емкостей жидкой углекислотой. </li>
</ul>
<p> </p>
<h2>Выгодные особенности углекислотных резервуаров</h2></h2>
если при загрузке content убрать ключ — LIBXML_HTML_NOIMPLIED, то все будет корректно, но добавятся теги <html><body>
Подскажите, что нужно прописать, что бы не ломало верстку и лишние теги не добавлялись?
Попробуй обернуть все это в какой-нибудь div, сохранится ли ошибка?
В content поле ни кто дополнительно div блоки прописывать не будет, а значит придется принудительно прописывать лишние элементы. Проще тогда теги body и html удалить.
LibXML требует корневой элемент, поэтому если стоит LIBXML_HTML_NOIMPLIED, то он считает корневым тегом первый попавшийся. Соответственно он ругается на то, что этот тег закрыт не там где надо и оборачивает в этот тег весь входящий html.
Поэтому нужно либо убирать LIBXML_HTML_NOIMPLIED, но после манипуляций вырезать теги head и body, либо передавать html как-нибудь так
Поэтому нужно либо убирать LIBXML_HTML_NOIMPLIED, но после манипуляций вырезать теги head и body, либо передавать html как-нибудь так
$dom->loadHTML("<div>$content</div>", ...);
Но тогда придется вырезать этот див.
Решено
Ломает ссылки, который указаны как [[~1]]
Первй лайфхак 'OnLoadWebDocument' делает ощибки:
1) глючит Феном в ресурсах
2) ломает кару сайта
Если переправить на onDocFormSave — тогда сохранение ресурса происходит вечно
1) глючит Феном в ресурсах
2) ломает кару сайта
Если переправить на onDocFormSave — тогда сохранение ресурса происходит вечно
Проблема №1:А в чём, собственно, проблема?) Наоборот последнее время сам добавляю изображениям эти атрибуты, чтоб страница не прыгала после загрузки изображений. Добавляю всем картинкам max-width: 100%; height: auto и всё) И зачем им классы какие-то?
В tinyMCE все изображения которые вставляются имеют атрибуты width и height, и не имеют нужных классов
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.