Переместите img перед родительским абзацем, используя simple-html-dom

Кей, я действительно застрял на этом: /
Пробовал SimpleHTMLDom, как уже упоминалось в заголовке и DOMDocument.
$ Html будет получен из CKEditor на моей странице, управляемой Processwire, я создал текстовый формат для автоматической пост-обработки вывода.

Так что это тестовые данные

<?php
$html = <<<_DATA
<p><img src="http://placehold.it/100x100"><img src="http://placehold.it/130x100">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam</p>
_DATA;

Так вот мой SimpleHTMLDom попробуйте

<?php
$dom = str_get_html($html);
$imgs = $dom->find('img');

foreach ($imgs as $img) {
$i = $img->outertext;
$img->outertext = '';
$img->parent()->outertext = $i . $img->parent()->outertext;
}
echo $dom->save();
$dom->clear();

Наличие только одного img в $ html выше, и все работает как положено, но эти два (или более) возвращают дубликаты.

  1. проблема, это меняет порядок сортировки, поэтому изображение 130×100 будет первым.
    Я знаю, что готовлюсь, но я не знаю, как это изменить. Пытался поместить все изображения в переменную, чтобы они оставались в порядке, но тогда я не знаю, как добавить его к абзацу.

  2. и на самом деле более важная проблема — это дубликаты, странная вещь, это то, что он правильно подготавливает все изображения, но он удаляет только первое img в абзаце, и это верно для любого дополнительного изображения, поэтому с 3 он сохранит последние два (как я сказал , 1 будет работать нормально)

Что я делаю неправильно?

Вероятно, это было бы лучше в отдельном вопросе, но я хотел показать, что я также пробовал DOMDocument, но не мог заставить insertBefore работать (вообще)
Я пробовал разные варианты (без комментариев в приведенном ниже коде)

<?php
include_once "./classes/SmartDOMDocument.class.php";
$dom = new SmartDOMDocument();
$dom->loadHTML($html);

$imgs = $dom->getElementsByTagName('img');

foreach ($imgs as $img) {
$i = $dom->createElement('img');
$i->src = $img->getAttribute('src');
$img->parentNode->insertBefore($i, $img->parentNode);
// $img->insertBefore($i, $img->parentNode);
// $dom->insertBefore($i, $img->parentNode);
$img->parentNode->removeChild($img);
}

echo $dom->saveHTMLExact();

Если что-то недостаточно хорошо задокументировано или задано, пожалуйста, не стесняйтесь комментировать, и я постараюсь объяснить лучше 🙂

Редактировать: HTML (из wysiwyg, как упоминалось выше) иногда будет содержать изображения в середине или конце абзаца, может содержать одно или несколько изображений (неопределенное число), и в этом HTML будет более одного абзаца

РЕДАКТИРОВАТЬ: Должен был включить, как я хочу, чтобы вывод был

Так что это вход

<p>
<img src="http://placehold.it/100x100">
<img src="http://placehold.it/130x100">
<img src="http://placehold.it/160x100">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
</p>

И это должно быть результатом

<div class="inlineGallery">
<figure><img src="http://placehold.it/100x100"></figure>
<figure><img src="http://placehold.it/130x100"></figure>
<figure><img src="http://placehold.it/160x100"></figure>
</div>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
</p>

Извините, что не упомянул, что эти изображения должны быть обернуты в цифры, а затем в контейнер … отдельное изображение не потребует дополнительного контейнера, но это на самом деле не важно ..
Я проверил с полным кодом … оборачивая изображения на рисунке, добавляя figcaption, где это применимо, и оборачивая несколько рисунков в div, все работает над статьей только с одним изображением, затем я наткнулся на HTML, похожий на данные теста выше в другой статье что приводит к упомянутому дублированию .. Так что я сократил код, чтобы увидеть, откуда возникла проблема, не повезло … вот почему я просто добавил этот простой код в вопрос, потому что я думал, что как только это сработает, другой тоже будет работать 😉

Надеюсь, теперь все понятно?

0

Решение

Так вот основной код, который делает работу, как под сомнение

// turn double linebreaks into paragraphs <br><br> to </p><p>
$value = preg_replace('#(?:<br\s*/?>\s*?){2,}#', '</p><p>', $value);

$dom = str_get_html($value);

/* first getting all <p> */
$paragraphs = $dom->find('p');

foreach ($paragraphs as $p) {
$imgs = $p->find('img');

/* init gallery container */
$gallery = "<div class='gallery'>";
foreach  ($imgs as $img) {
/* get the current image */
$i = $img->outertext;
/* wrap in link */
$i = "<a href='Link'>$i</a>";
/* append to gallery */
$gallery .= $i;
/* remove original image from paragraph */
$img->outertext = '';
}
/* close new gallery */
$gallery .= "</div>";
/* remove unnecessary <br> */
$newParagraph = trim(preg_replace( '#^\s*(?:<br\s?\/?>)*\s*|(?:<br\s?\/?>)*\s*$#', '', trim($p->innertext)));
/* wrap tidied text into <p> */
$newParagraph = "<p>$newParagraph</p>";
/* replace old paragraph by gallery and new paragraph */
$p->outertext = $gallery . $newParagraph;
}
// save dom to $value
$value = $dom->save();
// clear dom
$dom->clear();

Но кто заинтересован в полном плане, для которого я использую это, должен взглянуть на форумы Processwire https://processwire.com/talk/topic/13471-better-ckeditor-image-insertion-at-least-for-me/

0

Другие решения

Обновленный пример 🙂

<?php
$html = "asdasd <p><img class=\"wrap\" src=\"http://placehold.it/100x100\">    <img class=\"wrap\" src=\"http://placehold.it/130x100\">  <img class=\"wrap\" src=\"http://placehold.it/160x100\">    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam</p> asdasd    ";

$pattern = '/(<p>)((<img [^>]+>\s*)+)(.+?)(<\/p>)/i';

$replacement = '<div class="inlineGallery">${2}</div> ${1} ${4}${5}';
$html2 = preg_replace($pattern, $replacement, $html);

$pattern2 = '/(<img class=\"wrap\" [^>]+>)/i';
$replacement2 = '<figure>${1}</figure>';
echo preg_replace($pattern2, $replacement2, $html2);
?>

Возможно, это можно сделать за одно регулярное выражение, но вот мое решение. И вам придется иметь некоторую идентификацию на этих изображениях для второго запуска.

-1

По вопросам рекламы [email protected]