Простой вики-парсер и автоопределение ссылок - PullRequest
1 голос
/ 12 марта 2011

Я использую следующие функции:

function MakeLinks($source){
 return preg_replace('!(((f|ht){1}tp://)[-a-zA-Zа-яА-Я()0-9@:%_+.~#?&;//=]+)!i', '<a href="/1">$1</a>', $source);
}

function simpleWiki($text){
 $text = preg_replace('/\[\[Image:(.*)\]\]/', '<a href="$1"><img src="$1" /></a>', $text);
 return $text;
}

Первая преобразует http://example.com в http://example.com ссылку.

Вторая функция превращает строки как [[Image:http://example.com/logo.png]] в изображение.

Теперь, если у меня есть текст

$text = 'this is my image [[Image:http://example.com/logo.png]]';

и преобразовать его следующим образом simpleWiki(makeLinks($text)), он выдаст что-то похожее на:

this is my image <a href="url"><img src="<a href="url">url</a>"/></a>

Какя могу предотвратить это?Как проверить, что URL не является частью [[Image:URL]] конструкции?

Ответы [ 2 ]

1 голос
/ 12 марта 2011

Ваша непосредственная проблема может быть решена путем объединения двух выражений в одно (с двумя альтернативами), а затем с помощью функции не так хорошо известна, но очень мощна : preg_replace_callback(), которая обрабатывает каждый случай отдельно за один проход через целевую строку следующим образом:

<?php // test.php 20110312_1200
$data = "[[Image:http://example.com/logo1.png]]\n".
        "http://example1.com\n".
        "[[Image:http://example.com/logo2.png]]\n".
        "http://example2.com\n";

$re = '!# Capture WikiImage URLs in $1 and other URLs in $2.
      # Either $1: WikiImage URL
      \[\[Image:(.*?)\]\]
    | # Or $2: Non-WikiImage URL.
      (((f|ht){1}tp://)[-a-zA-Zа-яА-Я()0-9@:%_+.~#?&;//=]+)
      !ixu';

$data = preg_replace_callback($re, '_my_callback', $data);

// The callback function is called once for each
// match found and is passed one parameter: $matches.
function _my_callback($matches)
{ // Either $1 or $2 matched, but never both.
    if ($matches[1]) {  // $1: WikiImage URL
        return '<a href="'. $matches[1] .
            '"><img src="'. $matches[1] .'" /></a>';
    }
    else {              // $2: Non-WikiImage URL.
        return '<a href="'. $matches[2] .
            '">'. $matches[2] .'</a>';
    }
}
echo($data);
?>

Этот скрипт реализует два ваших регулярных выражения и выполняет то, что вы просите. Обратите внимание, что я изменил жадную (.*) на (.*?) ленивую версию, потому что жадная версия не работает правильно (она не может обрабатывать несколько WikiImages). Я также добавил модификатор 'u' в регулярное выражение (это необходимо, когда шаблон содержит символы Юникода). Как видите, функция обратного вызова preg очень мощная. (Эту технику можно использовать для выполнения довольно сложных задач по обработке текста.)

Однако учтите, что регулярное выражение, которое вы используете для выбора URL-адресов, может быть значительно улучшено. Посетите следующие ресурсы для получения дополнительной информации об URL-ссылках «Ссылка» (Подсказка: есть куча «ошибок»):
Проблема с URL
Улучшенный шаблон точных регулярных выражений для сопоставления URL-адресов
URL-ссылка (HTTP / FTP)

1 голос
/ 12 марта 2011

В вашем MakeLinks добавьте это [^:"]{1}, см. Ниже:

function MakeLinks($source){
    return preg_replace('![^:"]{1}(((f|ht){1}tp://)[-a-zA-Zа-яА-Я()0-9@:%_+.~#?&;//=]+)!i', '<a href="/1">$1</a>', $source);
}

Тогда будет преобразована только ссылка без ":" перед (как в Image :).И используйте $text = simpleWiki(MakeLinks($text));.

РЕДАКТИРОВАТЬ: Вы можете изменить с помощью этого: preg_replace('![[:space:]](((f|ht){1}tp://)[-a-zA-Zа-яА-Я()0-9@:%_+.~#?&;//=]+)[[:space:]]!i', '<a href="$1">$1</a>', $source);

...