Удаление вложенного bbcode (кавычек) в PHP - PullRequest
3 голосов
/ 27 августа 2010

Я пытаюсь удалить вложенные цитаты из доски объявлений, но у меня возникли некоторые проблемы.

Пример ввода:

[цитата автора = ссылка на personX = topic = 12.msg1910 # msg1910 date = 1282745641]

[quote author=PersonY link=topic=12.msg1795#msg1795 date=1282727068]

The message in the original quote

[/quote]

Второе сообщение, цитирующее первое

[/ цитата]

[цитата автора = ссылка на PersonZ = тема = 1.msg1 # msg1 date = 1282533805]

Случайная третья цитата

[/ цитата]

Пример вывода

[цитата автора = ссылка на personX = 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); 

Он вообще ничего не делает.

Есть идеи по этому поводу?


Edit:

Спасибо за помощь, Хагги.

Я продолжаю прибегать к неприятностям.

Цикл пока вокруг

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 ]

2 голосов
/ 27 августа 2010

то, что первый из них остается единственным, довольно легко узнать:

'$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 под рукой, чтобы проверить его.Если есть ошибки, которые вы не можете исправить, просто опубликуйте их здесь, и я их исправлю.

Ура,Хагги

0 голосов
/ 26 августа 2013

Я искал пару решений с 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. 

Надеюсь, это кому-нибудь поможет.

...