Замена слова на ссылку с учетом существующих ссылок и тегов

Замена слова на ссылку с учетом существующих ссылок и тегов

Требуется заменить некое слово в тексте на ссылку, например:

Как сообщал Интерфакс

на:

Как сообщал <a href="http://www.interfax.ru">Интерфакс</a>

Вроде все просто реализуется на PHP с помощью регулярного выражения:

$text = 'Как сообщал Интерфакс';
$word = 'интерфакс';
$text = preg_replace('/(' . $word . ')/iu', '<a href="/news.html">$0</a>', $text);

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

$text = 'Любой текст с html или без него <a href="/">содержащий</a> <span data-text="слово">cлово</span>';
$word = 'Слово';
// Нечетные элементы массива $split будут
// содержать html теги, а четные текс
$split = preg_split('/(<.*?>)/s', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
// По умолчанию замена слов на ссылки разрешена
$flag = true;
for ($i = 0; $i < count($split); $i++) {
    if ($i & 1) {
        // Если обнаружен открывающий тег a, то замена слов на ссылку запрещается
        if (preg_match('/(<a.*?>)/i', $split[$i])) $flag = false;
        // Если обнаружен закрывающий тег a, то замена слов на ссылку разрешается
        if (preg_match('/(<\/a>)/i', $split[$i])) $flag = true;
    } else {
        if ($flag) $split[$i] = preg_replace('/(' . $word . ')/iu', '<a href="/news.html">$0</a>', $split[$i]);
    }
}
$text = implode('', $split);
echo $text;

Комментарии ()

Вы можете авторизоваться на сайте через:
YandexVkontakte
  1. Лена 31 августа 2008, 11:23 # 0
    Спасибо за полезный пост!
    1. tvolf 27 ноября 2013, 10:17 # 0
      У вас, похоже, неверный комментарий в функции. В самом начале написано:
      ==
      // Нечетные элементы массива $split будут
      // содержать текс, а четные html теги
      ==
      А на самом деле текст будут содержать четные элементы массива (индексы 0, 2, 4 и т.д.), а в нечетных элементах массива $split будут лежать теги.
      В самой функции же все отрабатывает правильно, то есть, теги ищутся в нечетных элементах, то есть. неверный только комментарий.
      1. Сергей Зотиков 27 ноября 2013, 12:31 # 1 0
        Радует когда код не просто копируют, а вникают в него! Спасибо, ошибку исправил.