✅ Новости WEB и WordPress, темы, плагины. Здесь мы делимся советами и лучшими решениями для веб-сайтов.

Изменение контейнеров изображений на стороне сервера в WordPress

50

Всякий раз, когда вы создаете собственные решения для других людей, вы можете столкнуться с нюансами того, как WordPress отображает контент.

Обычно это связано с темой, как минимум одним плагином или их комбинацией. А если вам нужно работать с изображениями по отдельности, это может стать проблемой. Проблема даже с попыткой написать такой пост в том, что сложно даже описать ситуацию, в которой вам может понадобиться что-то подобное.

Тем не менее, я собираюсь сделать все, что в моих силах. То есть я хочу поделиться тем, как изменять контейнеры изображений на стороне сервера перед их рендерингом на стороне клиента и делать это с помощью библиотеки PHP DOMDocument.

Звучит как много? Надеюсь, я смогу сломать это достаточно легко.

Прежде чем приступить к коду, предположим, что у вас есть объект, который отображает изображения в одном элементе абзаца (или любом типе элемента блочного уровня), и вам нужно обернуть каждый элемент в некоторый тип класса, чтобы вы могли получить доступ через CSS или JavaScript.

Где мы

Итак, для начала предположим, что изображения визуализируются следующим образом:

И вам нужно сделать их так:

Теперь вам может понадобиться или не понадобиться пространство между ними. На самом деле это не имеет значения, потому что вы можете контролировать это через CSS. Но у вас есть контроль над тем, как это отправляется по сети на сторону клиента.

Для этого вам понадобится несколько вещей:

  • Доступ к библиотеке PHP DOMDocument,
  • Понимание того, как манипулировать контентом с помощью хука WordPress the_content ,
  • Стратегия того, как вы хотите обернуть изображения.

Я пройдусь по каждому из них в коде, но достаточно сказать, что я собираюсь обернуть каждое изображение элементом абзаца. Очевидно, вы можете делать все, что захотите.

Как это сделать

Во-первых, убедитесь, что вы объявили, что используете содержимое документа DOM над своим классом :

<?php

namespace Acme;

use DOMDocument;

class AcmeContentSubscriber
{
  // ...
}

Затем создайте хук для the_content. Как вы это сделаете, будет зависеть от того, как вы организовали свой код (будь то ООП или нет). В этом примере я покажу очень простой пример того , как это сделать :

<?php

public function contentSubscriber()
{
  add_action( 'the_content', [$this, 'addImageAttributes']);
}

После этого вам нужно будет немного поработать (все это ниже, но выходит за рамки этого поста). Это включает:

  • преобразование кодировки объектов HTML,
  • создание экземпляра документа DOM,
  • загрузка HTML поста из входящего контента

В коде это должно выглядеть так :

<?php

public function addImageAttributes($content)
{

    $content  = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
    $document = new DOMDocument();

    libxml_use_internal_errors(true);
    $document->loadHTML(utf8_decode($content));

    // ...
}

Затем вам нужно перебрать  элементы img и убедиться, что вы устанавливаете правильный атрибут. Вы можете использовать класс, атрибут данных или что-то другое. Эта часть не имеет значения.

Обратите внимание, что для данного изображения вы захотите проверить, что следующий элемент не является элементом абзаца, поскольку это то, что я решил обернуть изображением. Другими словами, если следующий элемент не является абзацем, мы обернем этот элемент в элемент абзаца.

Для этого скелет функции main должен выглядеть так :

<?php

public function addImageAttributes($content)
{

    $content  = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
    $document = new DOMDocument();

    libxml_use_internal_errors(true);
    $document->loadHTML(utf8_decode($content));

    $images = $document->getElementsByTagName('img');
    foreach ($images as $image) {
        $image->setAttribute('class', 'acme-iamge');
        if ($image->nextSibling->tagName !== 'p') {
            $this->wrapImage($document, $image);
        }
    }

    // ...
}

Тогда функция, отвечающая за перенос элемента в абзац, должна выглядеть так :

<?php

/**
 * This function is used to wrap individual images in a paragraph element.
 *
 * @param $document The DOM Document which is to be rendered.
 * @param $image    The image to wrap with the new paragraph element.
 */
private function wrapImage($document, $image)
{
    if (null === $image) {
        return;
    }
    $wrapper = $document->createElement('p');
    $wrapper->setAttribute('class', 'acme-image');

    $image->parentNode->replaceChild($wrapper, $image);
    if (null !== $image) {
        $wrapper->appendChild($image);
    }
}

Обязательно прочитайте DocBlock кода, чтобы понять, как работает функция. Проще говоря:

  • он принимает экземпляр документа и элемент изображения,
  • создает элемент абзаца,
  • добавляет атрибут класса
  • заменяет исходный элемент изображения абзацем,
  • и добавляет изображение в качестве дочернего элемента

И поскольку мы создали объект документа в методе, нам не нужно ничего возвращать.

Окончательная версия исходной функции должна выглядеть так :

<?php

public function addImageAttributes($content)
{

    $content  = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
    $document = new DOMDocument();

    libxml_use_internal_errors(true);
    $document->loadHTML(utf8_decode($content));

    $images = $document->getElementsByTagName('img');
    foreach ($images as $image) {
        $image->setAttribute('class', 'acme-image');
        if ($image->nextSibling->tagName !== 'p') {
            $this->wrapImage($document, $image);
        }
    }

  return $document->saveHTML();
}

И ваш вывод должен выглядеть как на изображении выше. Однако помните; вам нужно вернуть результаты экземпляра документа в WordPress, чтобы он правильно отображал HTML. Именно это и  делает функция saveHTML в приведенном выше коде.

Источник записи: tommcfarlin.com

Этот веб-сайт использует файлы cookie для улучшения вашего опыта. Мы предполагаем, что вы согласны с этим, но вы можете отказаться, если хотите. Принимаю Подробнее