Удаление вложенного bbcode (кавычек) в PHP
Я пытаюсь удалить вложенные цитаты из моей доски объявлений, но у меня есть некоторые проблемы.
Пример ввода:
[quote author=personX link=topic=12.msg1910#msg1910 date=1282745641]
[quote author=PersonY link=topic=12.msg1795#msg1795 date=1282727068] The message in the original quote [/quote]
Второе сообщение, цитирующее первое
[/ Цитата]
[цитата автора = ссылка на PersonZ =topic=1.msg1#msg1 date=1282533805]
Случайная третья цитата
[/ Цитата]
Пример вывода
[quote author=personX link=topic=12.msg1910#msg1910 date=1282745641]
Сообщение во второй цитате
[/ Цитата]
[цитата автора = ссылка на PersonZ =topic=1.msg1#msg1 date=1282533805]
Случайная третья цитата
[/ Цитата]
Как видите, вложенная цитата (Исходное сообщение) удаляется вместе с тегами цитаты.
Я не могу понять это.
Когда я пытаюсь
$toRemove = '(\\[)(quote)(.*?)(\\])';
$string = $txt;
$found = 0; echo preg_replace("/($toRemove)/e", '$found++ ? \'\' : \'$1\'', $string);
Он удаляет все вхождения тега цитаты, кроме первого,
Но когда я расширяю код до:
$toRemove = '(\\[)(quote)(.*?)(\\])(.*?)(\\[\\/quote\\])';
$string = $txt;
$found = 0; echo preg_replace("/($toRemove)/e", '$found++ ? \'\' : \'$1\'', $string);
Он вообще ничего не делает.
Есть идеи по этому поводу?
Редактировать:
Спасибо за вашу помощь, Хагги.
Я продолжаю прибегать к неприятностям, хотя.
В то время как цикл вокруг
while ( $input = preg_replace_callback( '~\[quoute.*?\[/quote\]~i', 'replace_callback', $input ) ) {
// replace every occurence
}
заставляет страницу зацикливаться бесконечно, при удалении (вместе с лишним u в квоте) страница ничего не делает.
Я определил, что причина в том,
когда изменился на
$input = preg_replace_callback( '/\[quote(.*?)/i', 'replace_callback', $input );
код начинает работать, но при изменении на
$input = preg_replace_callback( '/\[quote(.*?)\[\/quote\]/i', 'replace_callback', $input );
Это перестает делать что-либо снова.
Кроме того, существует проблема с функцией undo_replace, поскольку она никогда не находит сохраненный хеш, а только выдает предупреждения о необнаруженных индексах. Полагаю, регулярное выражение, соответствующее sha1, работает неправильно.
Полный код, как у меня сейчас:
$cache = array();
$input = $txt;
function replace_callback( $matches ) {
global $cache;
$hash = sha1( $matches[0] );
$cache["hash"] = $matches[0];
return "REPLACE:$hash";
}
// replace all quotes with placeholders
$input = preg_replace_callback( '/\[quote(.*?)\[quote\]/i', 'replace_callback', $input );
function undo_replace( $matches ) {
global $cache;
return $cache[$matches[1]];
}
// restore the outer most quotes
$input = preg_replace_callback( '~REPLACE:[a-f0-9]{40}~i', 'undo_replace', $input );
// remove the references to the inner quotes
$input = preg_replace( '~REPLACE:[a-f0-9]{40}~i', '', $input );
echo $input;
Еще раз спасибо за любые идеи, ребята:)
2 ответа
Что первый остается единственным, довольно легко выяснить:
'$found++ ? \'\' : \'$1\''
При запуске $found не определено и имеет значение false, поэтому возвращается $1. Затем $found увеличивается до 1 ( undefined + 1 = 1), поэтому он больше нуля, и каждый раз, когда он вызывается, он увеличивается. Поскольку все, что отличается от нуля, оценивается как истинное, после этого вы всегда возвращаете ''.
То, что вы хотите сделать, это что-то вроде этого
$cache = array();
function replace_callback( $matches ) {
global $cache;
$hash = sha1sum( $matches[0] );
$cache[$hash] = $matches[0];
return "REPLACE:$hash";
}
// replace all quotes with placeholders
$count = 0;
do {
$input = preg_replace_callback( '~\[quoute.*?\[/quote\]~i', 'replace_callback', $input, -1, $count );
// replace every occurence
} while ($count > 0);
function undo_replace( $matches ) {
global $cache;
return $cache[$matches[1]];
}
// restore the outer most quotes
$input = preg_replace_callback( '~REPLACE:[a-f0-9]{40}~i', 'undo_replace', $input );
// remove the references to the inner quotes
$input = preg_replace( '~REPLACE:[a-f0-9]{40}~i', '', $input );
Этот код не протестирован, так как я не имею под рукой PHP для его тестирования. Если есть ошибки, которые вы не можете исправить, просто опубликуйте их здесь, и я их исправлю.
Ура,
Хагги
Я искал пару решений с preg_replace для вложенных кавычек, но никто не работал. Так что я попробовал свою маленькую версию в соответствии с моим требованием.
$position = strrpos($string, '[/quote:'); // this will get the position of last quote
$text = substr(strip_tags($string),$position+17); // this will get the data after the last quote used.
Надеюсь, это кому-нибудь поможет.