/** * Handles parsing elements whose CodeDefinitions disable parsing of element * contents. This function uses a rolling window of 3 tokens until it finds the * appropriate closing tag or reaches the end of the token stream. * * @param $parent the current parent element * @param $tokenizer the tokenizer we're using */ protected function parseAsTextUntilClose(ElementNode $parent, Tokenizer $tokenizer) { /* $parent's code definition doesn't allow its contents to be parsed. Here we use * a sliding of window of three tokens until we find [ /tagname ], signifying the * end of the parent. */ if (!$tokenizer->hasNext()) { return $parent; } $prevPrev = $tokenizer->next(); if (!$tokenizer->hasNext()) { $this->createTextNode($parent, $prevPrev); return $parent; } $prev = $tokenizer->next(); if (!$tokenizer->hasNext()) { $this->createTextNode($parent, $prevPrev); $this->createTextNode($parent, $prev); return $parent; } $curr = $tokenizer->next(); while ('[' != $prevPrev || '/' . $parent->getTagName() != strtolower($prev) || ']' != $curr) { $this->createTextNode($parent, $prevPrev); $prevPrev = $prev; $prev = $curr; if (!$tokenizer->hasNext()) { $this->createTextNode($parent, $prevPrev); $this->createTextNode($parent, $prev); return $parent; } $curr = $tokenizer->next(); } }
/** * This is the next step in parsing a tag. It's possible for it to still be invalid at this * point but many of the basic invalid tag name conditions have already been handled. * * @param ElementNode $parent the current parent element * @param Tokenizer $tokenizer the tokenizer we're using * @param string $tagContent the text between the [ and the ], assuming there is actually a ] * * @return ElementNode the new parent element */ protected function parseTag(ElementNode $parent, Tokenizer $tokenizer, $tagContent) { if (!$tokenizer->hasNext() || ($next = $tokenizer->next()) != ']') { $this->createTextNode($parent, '['); $this->createTextNode($parent, $tagContent); return $parent; } list($tmpTagName, $options) = $this->parseOptions($tagContent); if ('' != $tmpTagName && '/' == $tmpTagName[0]) { $actualTagName = substr($tmpTagName, 1); } else { $actualTagName = $tmpTagName; } if ('' != $tmpTagName && '/' == $tmpTagName[0]) { $elToClose = $parent->closestParentOfType($actualTagName); if (null === $elToClose || count($options) > 1) { $this->createTextNode($parent, '['); $this->createTextNode($parent, $tagContent); $this->createTextNode($parent, ']'); return $parent; } return $elToClose->getParent(); } if ('' == $actualTagName || !$this->codeExists($actualTagName, !empty($options))) { $this->createTextNode($parent, '['); $this->createTextNode($parent, $tagContent); $this->createTextNode($parent, ']'); return $parent; } $el = new $this->elementNodeClassName(); $el->setNodeId(++$this->nextNodeid); $code = $this->getCode($actualTagName, !empty($options)); $el->setBBCodeDefinition($code); if (!empty($options)) { $el->setAttribute($options); } $parent->addChild($el); return $el; }