Кей, я действительно застрял на этом: /
Пробовал 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 выше, и все работает как положено, но эти два (или более) возвращают дубликаты.
проблема, это меняет порядок сортировки, поэтому изображение 130×100 будет первым.
Я знаю, что готовлюсь, но я не знаю, как это изменить. Пытался поместить все изображения в переменную, чтобы они оставались в порядке, но тогда я не знаю, как добавить его к абзацу.
и на самом деле более важная проблема — это дубликаты, странная вещь, это то, что он правильно подготавливает все изображения, но он удаляет только первое 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, похожий на данные теста выше в другой статье что приводит к упомянутому дублированию .. Так что я сократил код, чтобы увидеть, откуда возникла проблема, не повезло … вот почему я просто добавил этот простой код в вопрос, потому что я думал, что как только это сработает, другой тоже будет работать 😉
Надеюсь, теперь все понятно?
Так вот основной код, который делает работу, как под сомнение
// 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/
Обновленный пример 🙂
<?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);
?>
Возможно, это можно сделать за одно регулярное выражение, но вот мое решение. И вам придется иметь некоторую идентификацию на этих изображениях для второго запуска.