WordPress: Делаем автоматические подписи под картинками в постах

Проекту исполнилось 15 лет! Поддержать проект материально, проспонсировать проекты Автора или сделать ему подарок можно на этой странице: "Донаты и Спонсорство, Список Желаний".

Число просмотров: 4 935 

Подписи изображений, автоматически добавленные в пост

Подписи изображений, автоматически добавленные в пост

Никто не заметил новой фишки? Она появилась только что на всех постах блога! =) Это — автоматические подписи под фотками! Ключевое слово — автоматические!

Я написал скрипт, который на стороне сервера (PHP, а не сраный JavaScipt в браузере) парсит текст поста и автоматически вставляет подписи под картинками, которые берёт из тэга title (можно alt на выбор; я щас накрутил скрипт так, что он пытается найти из title, а если не находит — то пытается найти из alt).

Сейчас всё расскажу и покажу код, потому что я искал такое решение в сети и ни хрена не нашёл, хотя оно опять же пишется за два часа (это если не знать регулярные выражения).

Ставим задачу! Почему мне захотелось генерировать подписи картинок автоматически? Ведь WordPress имеет свои поля для подписи картинок. Вот прям в редакторе есть:

Стандартное поле для подписи изображения

Стандартное поле для подписи изображения

Набиваешь подпись — и когда ты вставляешь картинку в пост, то эта подпись автоматом вставляется под ней:

WordPress вставляет изображение с подписью, по позволяет её редактировать (виден курсор)

WordPress вставляет изображение с подписью, по позволяет её редактировать (виден курсор)

Но меня это ВЫБЕСИЛО! Неспроста прям в тексте подписи у меня на скриншоте стоит курсор. Эта подпись в текстовом редакторе выглядит так же, как и обычный текст. И поэтому когда ты работаешь с текстом поста, ты начинаешь путаться. И вообще текст подписи изображения мешается и путает: за ним надо следить — как бы случайно не потереть или не поменять.

Я поставил задачу так: у изображения в WordPress должен быть только один атрибут, который задаётся в редакторе как «Атрибут alt». Всё! Остальная хреновина должна браться из этого атрибута автоматически (у меня стоит плагин «Title Like Alt», который ещё и тэг «title» подставляет, чтобы над изображениембыла всплывающая подсказка).

Если ты тыркнул на изображение, поменял там Alt в редакторе — то все подписи автоматически должны поменяться. А в тексте редактора их быть не должно — там должен быть только текст поста. Как там это правильно зовётся? Бритва Оккама и не плодите сущности!

Вот так (картинка из поста про то, как я готовлю фотки на посты на блог):

Все фотки вставлены в черновик поста и можно писать текст

Все фотки вставлены в черновик поста и можно писать текст

Суть задачи: автоматически вытащить из каждого изображения текста поста атрибут «title» или «alt», взять оттуда текст и захерачить его под этим изображением.

Как её можно решить? Самое простое решение для хипстоты напрашивается через браузер: мы знаем HTML-вёрстку темы. Значит можем взять JavaScript, обратиться к контейнеру DIV-тэга текста поста, потом перебрать там все подчинённые элементы IMG и стащить их атрибут. А потом всякий там «outerHTML = » — дозаменить HTML-код на лету.

Это решение я отмёл сразу же нахер, потому что я не хочу работать на стороне браузера и зависеть от вёрстки моей темы. Нахрена удалять гланды через задницу и ещё и трахаться с выполнением JS-кода на разных платформах (вдруг глюки будут), если у нас лежит готовый HTML-код поста в самом WordPress в чистом виде (его не надо выдирать из вёрстки темы).

Поэтому я решил заморочиться с PHP так, чтобы HTML-код поста WordPress изменялся на стороне сервера на лету, а потом уже отдавался в браузер. Так техничнее, потому что в этом случае мы получаем готовый HTML, который ещё и поисковиком будет индексироваться.

Я поискал решения для этого в сети. И не нашёл, что странно. Везде какие-то пространственные рассуждения типа «ну это надо парсить HTML, использовать XML, обработчики, это сложно и нахер нужно». А мне — НУЖНО! Щча я расскажу о том, какие фишки я использовал. Готовый код выложу в текстовом файле, так как моя текущая тема искажает его вёрстку и я не знаю, как это поправить.

Первое. У WordPress есть штатные хуки (hook) на разные события внутри движка. Ими часто пользуются, чтобы навесить на стандартные функции свои фишки. Например, есть хук выдачи поста в RSS — и туда можно добавить свой текст типа «цопирайт такой-то, полная версия статьи будет на сайте».

Нас интересует хук «the_content». Это прям именно то, что нам надо — текст поста в HTML так, как он забит в редакторе в режиме «Текст». Этот текст возвращается в виде переменной. И мы его можем менять, а потом передавать дальше в движок WordPress.

Делаем функцию перехвата этого хука:
add_filter('the_content', 'cs_content_imageprocess'); function cs_content_imageprocess( $content ) { //тут обработка return $content;   //Вертаем обработанное назад в WordPress }
Ну и в этой функции мы можем взять $content и сделать с ним всё, что хотим.

А что мы будем делать? Гммм.. сначала будет смотреть на то, как наши изображения к постам выглядят в HTML-коде поста:

Структура HTML-тэгов изображения, которое WordPress вставляет в пост

Структура HTML-тэгов изображения, которое WordPress вставляет в пост

Каждое изображение обёрнуто в ссылку. У ссылки есть атрибут «title», и у изображения есть атрибуты «title» и «alt». Значится нам надо пройтись по всем таким конструкциям и выковырять сначала <a href =>…</a>, чтобы поэтом это заменить на тот же текст, но с добавленным <p> подписи. А потом надо выковырять из вложенного <img> сами атрибуты «title» и «alt».

Тут нам на помощь приходят регулярные выражения. Я выражаю ОЧЕНЬ большое спасибо вот этим ребятам по двум ссылкам (раз — «Php получить текст между тегами» и два — «Извлечение данных с помощью регулярных выражений PHP»)! Я никогда не связывался с регулярными выражениями, а щас заморочился и нашёл искомое.

Сначала извлекаем все тэги <a href=>…</a>:
preg_match_all('/&lt;a.*?&gt;(.*?)&lt;\/a&gt;/i', $content, $postImageHrefs);
В этом месте нам попадутся ВСЕ ссылки в посте. И даже обычные текстовые. Это не страшно, мы потом отсеем лишнее. Все ссылки будут в виде массива, по которому надо будет пройти циклом. В цикле я получаю полный текст тэга ($postImageHrefs[0]) для того, чтобы потом весь этот текст менять на «текст + подпись».

Теперь в тексте каждой ссылки найдём <img src =…>, чтобы откинуть ссылки, в которых нет картинок:
preg_match_all('#&lt;img (.+?)&gt;#is', $hrefTagText, $postImageTags);
В $postImageTags теперь у нас будет HTML-код вложенной в тэг «A» картинки или пустое значение, если в после картинок нет. Что ж? Теперь настало время вытащить из HTML-кода картинки атрибуты «title» или «alt». Фигачим такие регулярные выражения:
preg_match_all('#title ?= ?"(.+?)"#is', $postImageTags[0][0], $imgTagTitles); preg_match_all('#alt ?= ?"(.+?)"#is', $postImageTags[0][0], $imgTagTitles);
Я привёл сразу два. В моём коде сначала выдирается одно и, если оно не нашлось, выдирается второе.

Теперь, если все-все-все условия сошлись: мы нашли тэг «A» и внутри него точно есть тэг «IMG», а внутри этого тэга есть «title» или «alt» — то надо отформатировать наше название как нам надо. Я пока что ставлю <P>:
$imgTagTitle = "&lt;p class = \"cs-post-image-title\"&gt;" . html_entity_decode($imgTagTitles[1][0]) . "&lt;/p&gt;";
Функция «html_entity_decode» нужна тут из-за того, что я обожаю втыкать в названия картинок кавычки, которые WordPress переделывает во всякие «&quo;». Эта функция превращает их назад в нужные знаки.

И последнее, что осталось — сделать замену куска <a href=»..»><img src =»..»></a> на такой же кусок, но с добавленным в конце <p>заголовок</p>. Делаем:
$content = str_replace($hrefTagText, $hrefTagText . " " . $imgTagTitle, $content);
И НЕ забываем вернуть поменянный $content назад в WordPress, иначе получим пустой пост вообще:
return $content;
Вот и весь концепт получился. И самое забавное — он реально РАБОТАЕТ. Причём на всех постах, даже ранних! Правда самые ранние посты у меня имели мелкие превьюшки 150х150 точек. Вот там-то всё собьётся, но я давно собираюсь такие посты переделать в новый формат фоток. Так что всё норм.

Что можно накрутить на эту функцию? Можно сделать так, чтобы в ленте постов (блоге) подписи не показывались, чтобы не путать людей. У меня щас так и сделано. Можно придумать какой-нибудь параметр поста типа «DisableAutoImageTitles» и сделать его проверку (речь идёт о Произвольных полях; вот хорошая статья на Хабре: 10 приемов использования пользовательских полей в WordPress) — и отключать эту фишку для некоторых постов.

На этом — всё. Исходный код выложил в текстовом файле на хостинг вот сюда: WP-Auto-Image-Titles.txt.

Проекту исполнилось 15 лет! Поддержать проект материально, проспонсировать проекты Автора или сделать ему подарок можно на этой странице: "Донаты и Спонсорство, Список Желаний".

8 Отзывов на “WordPress: Делаем автоматические подписи под картинками в постах”


  • 1 a_b  [Московская область, Истринский район]

    Этим подписям ещё бы в стили добавить «speak: none;»
    А то всякие скринридеры и так прочитают alt/title картинки, и потом, получается, второй раз повторят ту же самую фразу.
    Оно понятно, что вряд ли у твоего блога много читателей с проблемами со зрением, которые скринридеры используют, но кому-то может быть актуально.

  • 2 CS  [Москва]

    a_b Сделал! Отпишись, помогло или нет!

  • 3 a_b  [Московская область, Истринский район]

    CS, а это такая штука, которую я сам и проверить не могу, т.к. не использую :)
    Просто сам стараюсь всем этим accessibility guidelines следовать, вот и посоветовал. Сделать несложно, а если хоть одному человеку, который не видит нихрена, но при этом находит в себе силы что-то вот так читать в сети, это чуть жизнь облегчит, — ну, будем надеяться, нам зачтётся.

  • 4 CS  [Москва]

    a_b Понял! Подправил, пускай будет.
    Кстати, вчера ещё и баг нашёл в коде: когда я там проверял, найдено ли чего по title/alt, то не те границы массива проверял — и код всегда считал что всё найдено.
    Ща работает верно. В исходнике по ссылке тоже обновил.

    Дальше надо будет сделать скриншот блога и начать оперировать его ебучее верхнее меню. Потому что мне ща надо добавить туда побольше пунктов, а оно на следующую строку не переносится ни хера =)

  • 5 profeMaster  [Одесса]

    хочешь, попробуй сразу получить title и alt такой регуляркой.

  • 6 CS  [Москва]

    profeMaster Я в них не силён. Расскажи, как она работает и чего будет возвращать?

  • 7 profeMaster  [Одесса]

    будет искать ссылки, внутри которых есть тег img. Вернет массив, в котором по индексу 0 лежат найденные ссылки, по индексу 1 — title=»что-то в тайтле» или alt=»что-то в альте», по индексу 2 — что-то в тайтле или что-то в альте.

    Регулярка старается найти сначала что-то в тайтле, а если тайтла нет, то что-то в альте.

    если в WordPress вывод var_dump не отображается, то должно быть что-то другое, чтобы увидеть значение переменной.

  • 8 CS  [Москва]

    Понял! Пасибо!
    Я у себя свой код оставлю. А кому-то может и сгодится и эта регулярка!

Оставить отзыв

Вы должны войти на блог, чтобы оставить комментарий.