Проблемы со стрток () - PullRequest
       12

Проблемы со стрток ()

1 голос
/ 11 октября 2011

Я боролся с этим некоторое время.Я знаю, что это большой код, но я понятия не имею, в чем проблема, и не могу ее сузить.Я щедро награждаю.

Я написал этот класс для разбора bbcodes.Он в основном использует strtok (), и класс работает отлично, если вы не поместите два тега рядом друг с другом, и я не могу понять, почему.

Например, [b] [i]test1[/i] [/b] приводит к<strong> <em>test1</em> </strong>.Все же [b][i]test1[/i][/b] приводит к <strong>i]test1/b]</strong>.Последний тег </strong> находится только там, потому что анализатор автоматически закрывает теги, для которых не удалось найти закрывающий тег в строке.Каким-то образом он полностью пропускает теги [i] и [/b].

Вот класс, а также тот подкласс, который он использует для настройки различных bb-кодов.Подкласс - это просто структура данных без поведения.

<?php
    // beware images can contain any url/any get request. beware of csrf
    class Lev_TextProcessor_Extension_BbCode {

        protected $elements = array();
        protected $openTags = array();

        public function __construct() {
            $this->elements['b'] = new Lev_TextProcessor_Extension_BbCode_Element('<strong>', '</strong>');
            $this->elements['i'] = new Lev_TextProcessor_Extension_BbCode_Element('<em>', '</em>');
            $this->elements['u'] = new Lev_TextProcessor_Extension_BbCode_Element('<span style="text-decoration: underline;">', '</span>');
            $this->elements['s'] = new Lev_TextProcessor_Extension_BbCode_Element('<span style="text-decoration: line-through;">', '</span>');
            $this->elements['size'] = new Lev_TextProcessor_Extension_BbCode_Element('<span style="font-size: ', '</span>', 'px;">');
            $this->elements['color'] = new Lev_TextProcessor_Extension_BbCode_Element('<span style="color: ', '</span>', ';">');
            $this->elements['center'] = new Lev_TextProcessor_Extension_BbCode_Element('<div style="text-align: center;">', '</div>', '', true, true, false);
            $this->elements['url'] = new Lev_TextProcessor_Extension_BbCode_Element('<a href="', '</a>', '">');
            $this->elements['email'] = new Lev_TextProcessor_Extension_BbCode_Element('<a href="mailto:', '</a>', '">');
            $this->elements['img'] = new Lev_TextProcessor_Extension_BbCode_Element('<img src="', '" alt="" />', '', false, false, true);
            $this->elements['youtube'] = new Lev_TextProcessor_Extension_BbCode_Element('<object width="400" height="325"><param name="movie" value="http://www.youtube.com/v/{param}"></param><embed src="http://www.youtube.com/v/', '" type="application/x-shockwave-flash" width="400" height="325"></embed></object>', '', false, false, false);
            $this->elements['code'] = new Lev_TextProcessor_Extension_BbCode_Element('<pre><code>', '
',' ', true, false, false);} публичная функция processText ($ input) {// предварительная обработка $ input = htmlspecialchars ($ input, ENT_NOQUOTES);$ input = nl2br ($ input);$ input = str_replace (array ("\ n", "\ r"), '', $ input);// начать основную обработку $ output = '';$ allow_child_tags = true;$ allow_child_quotes = true;$ string_segment = strtok ($ input, '[');do {// проверить содержимое на наличие кавычек if ($ allow_child_quotes === false) {if (strpos ($ string_segment, '"') === false) {$ output. = $ string_segment;}} else {// добавить содержимоедля вывода $ output. = $ string_segment;} $ tag_contents = strtok (']'); if (strpos ($ tag_contents, '/') === 0) {// закрывающий тег $ tag = substr ($ tag_contents, 1); if (isset ($ this-> elements [$ tag]) === true && array_search ($ tag, $ this-> openTags)! == false) {// найденный тег do {// закрывает теги до совпадениянайден тег $ last_open_tag = array_pop ($ this-> openTags); $ output. = $ this-> elements [$ last_open_tag] -> htmlAfter;} while= true;}} else {// открывающий тег // отделяет имя тега от аргумента, если есть один $ equal_pos = strpos ($ tag_contents, '='); if ($ equal_pos === false) {$ tag_name = $ tag_contents;} else {$ tag_name = substr ($ tag_contents, 0, $ equal_pos); $ tag_argument = substr ($ tag_contents, $ equal_pos + 1);} if (isset ($ this-> elements [$ tag_name]) = ==True) {// тег найден, если (($ this-> elements [$ tag_name] -> allowParentTags === true ||count ($ this-> openTags) === 0) && $ allow_child_tags === true) {// добавить тег в список открытых тегов и установить флаги $ this-> openTags [] = $ tag_name;$ allow_child_tags = $ this-> elements [$ tag_name] -> allowChildTags;$ allow_child_quotes = $ this-> elements [$ tag_name] -> allowChildQuotes;$ output. = $ this-> elements [$ tag_name] -> htmlBefore;// если аргумент существует if ($ equal_pos! == false) {if (strpos ($ tag_argument, '"') === false) {$ output. = $ tag_argument;}$ output. = $ this-> elements [$ tag_name] -> htmlCenter;}}}} $ string_segment = strtok ('[');} while ($ string_segment! == false);// закрываем оставшиеся теги while ($ tag = array_pop ($ this-> openTags)) {$ output. = $ this-> elements [$ tag] -> htmlAfter;} вернуть $ output;}}?>htmlBefore = $ html_before;$ this-> htmlAfter = $ html_after;$ this-> htmlCenter = $ html_center;$ this-> allowChildQuotes = $ allow_child_quotes;$ this-> allowChildTags = $ allow_child_tags;$ this-> allowParentTags = $ allow_parent_tags;}}?>

edit

Исправлено путем создания следующего класса для маркировки.

<?php

    // unlike PHP's strtok() function, this class will not skip over empty tokens.
    class Lev_TextProcessor_Tokenizer {

        protected $string;

        public function __construct($string) {
            $this->string = $string;
        }

        public function getToken($token) {
            $segment_length = strcspn($this->string, $token);
            $token = substr($this->string, 0, $segment_length);
            $this->string = substr($this->string, $segment_length + 1);
            return $token;
        }
    }
?>

1 Ответ

0 голосов
/ 11 октября 2011

Хотя я не думаю, что это действительно решение, похоже, что это единственный способ донести свою мысль.

Это может быть что-то с тем, как работает strtok(), чтобы получить желаемый результат.

Хотя и не идеально, я смог получить результаты, близкие к тому, что вы ожидали, с этим:

 <?
 $data1 = strtok('[b][i]test1[/i][/b]','[');
 $data2 = strtok(']');
 $data3 = strtok('[');
 $data4 = strtok(']');
 $data5 = strtok('[');
 $data6 = strtok(']');
 var_dump($data1, $data2,$data3, $data4, $data5, $data6);
 /*
  OUTPUT
    string(2) "b]"
    string(1) "i"
    string(5) "test1"
    string(2) "/i"
    string(3) "/b]"
    bool(false)
 * /
 ?>

Как я уже сказал, это не идеально, но, возможно, увидев это поможет вам на вашемспособ справиться с этим решением.Лично я никогда не обрабатывал BBCode с этим синтаксическим анализом, а использовал preg_match().

...