Визуальное сравнение текстов через Bitrix\Main\Text\Diff
При работе с инфоблоками в режиме документооборота накапливается история версий элементов. Стандартный интерфейс Битрикс показывает список версий, но не позволяет увидеть конкретные изменения между ними. Класс Bitrix\Main\Text\Diff решает эту задачу.
Класс реализует алгоритм Майерса и предоставляет метод getDiffHtml(), который принимает две версии текста и возвращает HTML с подсветкой: удалённые фрагменты выделены красным перечёркнутым текстом, добавленные — зелёным жирным.
Сравнение версий элемента инфоблока
use Bitrix\Main\Text\Diff;
/**
* Получает историю версий элемента через скомпилированный ORM класс
*/
function getElementHistory(int $elementId)
{
return \Bitrix\Iblock\Elements\ElementNewsTable::getList([
'select' => [
'ID',
'NAME',
'PREVIEW_TEXT',
'DETAIL_TEXT',
'TIMESTAMP_X',
'WF_COMMENTS',
'WF_STATUS_ID',
'WF_PARENT_ELEMENT_ID',
'MODIFIER_' => 'MODIFIED_BY_USER',
],
'filter' => [
'WF_PARENT_ELEMENT_ID' => $elementId,
],
'order' => ['ID' => 'ASC'],
])->fetchCollection();
}
$elementId = 37; // ID элемента в режиме документооборота
$history = getElementHistory($elementId);
if ($history->count() >= 2) {
$items = $history->getAll();
$prev = $items[count($items) - 2];
$curr = $items[count($items) - 1];
$diff = new Diff();
echo '<div class="version-diff">';
echo '<p>Версия #' . $curr->getId() . ' от ' . $curr->getTimestampX() . '</p>';
echo '<p>Автор: ' . $curr->getModifiedByUser()->getLogin() . '</p>';
if ($curr->getWfComments()) {
echo '<p>Комментарий: ' . htmlspecialchars($curr->getWfComments()) . '</p>';
}
echo '<h4>Название:</h4>';
echo $diff->getDiffHtml($prev->getName(), $curr->getName());
echo '<h4>Описание:</h4>';
echo $diff->getDiffHtml(
$prev->getDetailText() ?? '',
$curr->getDetailText() ?? ''
);
echo '</div>';
}

Вывод diff для всей истории элемента
// Формируем полную историю изменений с diff
$history = getElementHistory($elementId);
$diff = new Diff();
$items = $history->getAll();
echo '<div class="history-timeline">';
for ($i = 1; $i < count($items); $i++) {
$prev = $items[$i - 1];
$curr = $items[$i];
printf(
'<div class="history-item">
<div class="meta">%s | %s | Статус: %d</div>
<div class="comment">%s</div>
<div class="changes">%s</div>
</div>',
$curr->getTimestampX()->format('d.m.Y H:i'),
$curr->getModifiedByUser()?->getLogin() ?? 'N/A',
$curr->getWfStatusId(),
htmlspecialchars($curr->getWfComments() ?? ''),
$diff->getDiffHtml(
$prev->getDetailText() ?? '',
$curr->getDetailText() ?? ''
)
);
}
echo '</div>';
Для программного анализа используйте метод getDiffScript(), который возвращает массив операций с ключами startA, startB, deletedA, insertedB.
Похожие советы