Выбор первых картинок из контента
Вариант с использованием properties. Используется в плейсхолдере например так
<img src="[[+properties.first_img_src.0]]" >
Плагин нужно выставить для события OnBeforeDocFormSave
Плагин перезаписывает последнюю актуальную картинку на момент сохранения ресурса, под словом актуальную я имею в виду то, что делается проверка на корректность файла, и если он действительно существует, то только тогда произойдет действие.
Если картинки не найдено — то будет записан null
{"first_img_src":null}
если контент вообще пустой -то ничего не произойдет вообще.
Код можно как угодно доработать, зависит от логики реализации.
Код плагина:
<?php
if ($modx->event->name == 'OnBeforeDocFormSave') {
//get current content for resource
$content = $resource->getContent();
if (!empty($content)){
//get first image in content
$doc = new DOMDocument();
$doc->loadHTML($content);
$xml = simplexml_import_dom($doc);
$images = $xml->xpath('//img');
foreach ($images as $img) {
//also avaliable in array $img['alt'] и $img['title]
$file_headers = @get_headers($img['src']);
if ($file_headers[0] != 'HTTP/1.1 404 Not Found') {
$first_img_src = $img['src'];
break;
}
}
//get properties
$properties = $resource->get('properties');
//here you can check for empty $first_img_src and set default noImage photo
//save or override first_img_src
$properties['first_img_src'] = $first_img_src;
$resource->set('properties', $properties);
}
}
В комментариях предлагается использовать так же парсер MODX http://bezumkin.ru/sections/tips\_and\_tricks/2192/#comment-17960
0
👍
👎
❤️
🔥
😮
😢
😀
😡
2 968
22.11.2013, 16:31:14
23 комментария
Сергей
22.11.2013, 22:44:54
Если выбирается только 1 элемент, то зачем цикл? Если уж объявили переменную $file, то надо использовать до последнего =) Почините код чанка.
По моему лучше такие операции делать при создании материала, занеся адрес в отдельное поле.
Василий Наумкин
22.11.2013, 22:56:10
Зачем так сложно? Почему бы просто не использовать preg_match?
Например, вот:
Clean
22.11.2013, 23:49:53
Если ты по поводу парсинга то тут каждому свое. Просто xpath заточен именно на это,и он стандартизирован W3C которому и я стараюсь придерживаться. По скорости разницы ты не заметишь, хотя можно протестировать =)
Ну а дополнительная проверка доступности изображения делается на случай, когда выводится пользовательский контент и пользователь например загрузил ссылку на изображение на сторонний ресурс,который сейчас не доступен. В итоге получим отсутствия изображения с ошибкой, что не эстетично. Тоже самое касается если файл просто удалится с хостинга - лучше не вывести ничего, чем бяку в виду не существующей ссылки на картинку, не так ли ? :)
Василий Наумкин
23.11.2013, 00:09:03
Одна регулярка отработает быстрее, чем преобразование документа и поиск по DOM.
Ну и отсутствующая картинка что в превью, что в контенте - одинаково плохо. Или ты предлагаешь и при загрузке тикета так все картинки проверять и прятать?
Ну и подумай о том, что при выводе списка тиектов каждая картинка будет запрашиваться минимум дважды - сначала твой скрипт отработает, а потом юзер загрузит.
В общем, интересный велосипед, но на мой взгляд ценность очень сомнительна. Лучше уж логи проверять на предмет 404.
Clean
23.11.2013, 00:19:53
Можно использовать как угодно. По поводу скорости - проведу замер интересно тоже стало.
У меня это используется не везде конечно, а только на главной для вывода ТОП-5 новостей по определенным параметрам..Поэтому главную портить точно нет смысла. А подстраховаться можно,мало ли..
Clean
22.11.2013, 23:56:04
p.s вообще парсинг xml/xhtml/html код регулярками это как-то не красиво. Вот кажется эта статья на хабре http://habrahabr.ru/post/114772/ описывает что лучше отказаться от регулярок в пользу xpath Запросов =)
Василий Наумкин
23.11.2013, 00:19:11
Поиск первой картинки через преобразование всего документа - вот что некрасиво.
Твой код, 100 итераций - 0.47 сек
Мой код, 100 итераций - 0.28 сек
Мой выбор очевиден.
Clean
23.11.2013, 00:36:11
скрипты без изменений,кроме ID страницы у меня отработали
0.20023822784424 -твой 0.22262501716614 -мой
странно..Притом контент был большой
И кстати - у тебя возвращается тег целиком,а у меня адрес. Т.е тебе нужно еще парсить $img для того чтобы достать адрес картинки,а это доп. действия и возможно доп. нагрузка. =)
p.s ну я и не пытаюсь его позиционировать как более совершенное решение.Зависит от цели, но на мой взгляд если например потребуется выбрать все картинки с страницы, то мое решение уже будет в плюсе,т.к самое сложное уже позади. по идее
Василий Наумкин
23.11.2013, 00:59:36
Видимо, зависит от сложности форматирования. preg_match то пофиг - он не анализирует документ.
Вот гляди: http://s4327.modx-test.com/pcre.html - 0.22 сек http://s4327.modx-test.com/xpath.html - 0.51 сек
http://s4327.modx-test.com/manager/ Логин s4327 Пароль SufmusRqoRnJ
Алексей Карташов
24.11.2013, 02:13:58
Идея правильная. Только есть ещё один вариант.
Вот как можно сделать по-другому (просто времени реализовать такое у меня не было): Пишем плагин на событие сохранения документа, который берёт контент этого документа, парсит его modx-парсером, вытаскивает из контента картинку, и вот здесь простой финт - записывает эту картинку в tvшку.
Потом собрать пакет, который автоматом создаст нужную tvшку, и при установке пробежится по уже существующим документам и сделает свою работу. Плагин будет сохранять картинку в tv независимо от того - привязана эта tv-шка к шаблону текущего ресурса или нет (просто создаёт запись в таблице site_tmplvars_content_values (по-моему как-то так она называется)). А уж потом эту tvшку можно привязывать к любому шаблону - превьюшки уже будут на месте.
Но здесь есть один минус - если в контенте документа используются какие-либо сниппеты, благодаря которым выводимый контент динамически меняется независимо от того, сохранялся доумент или нет, то такой способ может не подойти.
Ваша идея - картинка всегда вытягивается из актуального (на момент загрузки страницы с этим сниппетом) контента документа, но работа делается каждый раз при обращении к этой странице (со сниппетом). Моя - делать работу один раз, сохраняя картинку по событию, и везде, где только можно, использовать эту tvшку штатными modx-средствами. Но при наличии страниц с динамичным контентом этот метод может не подойти.
Выбирайте :-)
Clean
24.11.2013, 04:01:54
Не плохое решение +) Тут зависит уже от нужд. Но коли речь зашла о плагинах и TV я бы предпочел вместо TV использовать свойство properties и запихивать уже туда код первой картинки в ресурс.Это и дает существенный прирост в скорости, и вообще выглядит куда красивее, =) Возможно реализую, если появится свободное время. =)
Abu
24.11.2013, 04:29:49
Тоже реализовал это через плагин к твшкам.
Abu
24.11.2013, 04:49:31
сорри так, без scriptProperties не работает =) идея сохранять в properties интересная, надо будет попробовать
Clean
25.11.2013, 05:15:45
Вот вариант с properties. Используется в плейсхолдере например так
Плагин нужно выставить для события OnBeforeDocFormSave
Плагин перезаписывает последнюю актуальную картинку на момент сохранения ресурса. Если картинки не найдено - то будет записан null
Код можно как угодно доработать, зависит от логики реализации.
Я думаю это самый практичный из приведенных выше вариантов работы,в плане скорости,т.к мы не тратим ничего на выходе.
Николай
26.11.2013, 13:13:37
Скрипт конечно полезный,только он не дает сохранить пустой ресурс *2168705 FastCGI sent in stderr: "PHP message: PHP Fatal error: Call to a member function xpath() on a non-object in www/core/cache/includes/elements/modplugin/6.include.cache.php on line 15"
Clean
26.11.2013, 14:39:48
Спасибо за наводку, не подумал об этом. Вот фикс:
Алексей Карташов
27.11.2013, 05:36:15
Забыли пропарсить контент modx-парсером:
Clean
27.11.2013, 14:09:14
Да, согласен, это полезно т.к действительно в контенте могут быть сниппеты и чанки в которых может выводиться изображение. Но я не стал это добавлять,т.к в моих страницах не предполагается использовать ModX теги в контенте, поскольку он редактируется с фронта, и важно выводить лишь то,что заполнил ручками пользователь. Добавлю в шапку сноску на Ваш пост.
Николай
24.12.2013, 19:46:07
Подскажите пожалуйста, что нужно изменить,чтобы этот плагин с Tickets начал работать из frontend? Я почему-то был уверен, что он и без изменений заработает,но к сожалению нет.
Николай
26.12.2013, 17:07:21
up! Если создавать тикет из бэкенда,то плагин записывает в базу строку
, что позволяет потом обернуть ее например в phptrumbon и делать превью. Если же создавать тикет из фронтенда,то плагин записывает в базу строку
и phptrumbon воспринимает изображение как лежащее на внешнем сервере и отдает заглушку. Посоветуйте как быть с превью...
Clean
27.11.2013, 03:40:26
Василий, хотел бы твое мнение услышать, и мне кажется есть смысл перенести в Тонкости и трюки, т.к на мой взгляд штука очень полезная
Василий Наумкин
27.11.2013, 03:55:52
У меня доступ в админку закрыт по ip и было лень включать.
Перенес.
Clean
27.11.2013, 04:08:43
А я в свою очередь поправил шапку под последнее актуальное состояние, чтобы не путать людей.
bezumkin.ru
Личный сайт Василия Наумкина
Прямой эфир
Василий Наумкин
01.07.2024, 11:56:41
Да, верно, именно так.
А в контроллере, скорее всего, ловить данные методом post.
Василий Наумкин
26.06.2024, 09:38:15
О, точно, вылезает если не залогинен.
Спасибо, исправил!
Василий Наумкин
09.04.2024, 04:45:01
> Ошибка 500
Это не похоже на ошибку Nginx, это скорее всего ошибка PHP - надо смотреть его логи.
...
russel gal
09.03.2024, 20:17:18
> А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал...
Александр Наумов
27.01.2024, 03:06:18
Василий, спасибо!
Извини, тупанул.