private function XBBCodeFilter::buildTree in Extensible BBCode 8.2
1 call to XBBCodeFilter::buildTree()
- XBBCodeFilter::process in src/
Plugin/ Filter/ XBBCodeFilter.php - Performs the filter processing.
File
- src/
Plugin/ Filter/ XBBCodeFilter.php, line 139 - Contains Drupal\xbbcode\Plugin\Filter\XBBCodeFilter.
Class
- XBBCodeFilter
- Provides a filter that converts BBCode to HTML.
Namespace
Drupal\xbbcode\Plugin\FilterCode
private function buildTree($text) {
// Find all opening and closing tags in the text.
preg_match_all(XBBCODE_RE_TAG, $text, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
// Initialize the name tracker, and the list of valid tags.
$open_by_name = [];
$tags = [];
foreach ($matches as $match) {
$tag = new XBBCodeTagMatch($match);
if (isset($this->tags[$tag->name])) {
$tag->selfclosing = $this->tags[$tag->name]->options->selfclosing;
$tags[] = $tag;
$open_by_name[$tag->name] = 0;
}
}
// Initialize the stack with a root element.
$stack = [
new XBBCodeRootElement(),
];
foreach ($tags as $tag) {
// Add text before the new tag to the parent
end($stack)
->advance($text, $tag->start);
// Case 1: The tag is opening and not self-closing.
if (!$tag->closing && !$tag->selfclosing) {
// Stack the open tag, and increment the tracker.
array_push($stack, $tag);
$open_by_name[$tag->name]++;
}
elseif ($tag->selfclosing) {
end($stack)
->append($tag, $tag->end);
}
elseif ($open_by_name[$tag->name]) {
$open_by_name[$tag->name]--;
// Find the last matching opening tag, breaking any unclosed tag since then.
while (end($stack)->name != $tag->name) {
$dangling = array_pop($stack);
end($stack)
->breakTag($dangling);
$open_by_name[$dangling->name]--;
}
$current = array_pop($stack);
$current
->advance($text, $tag->start);
$current->source = substr($text, $current->end, $current->offset - $current->end);
$current->closer = $tag;
end($stack)
->append($current, $tag->end);
}
}
// Add the remainder of the text, and then break any tags still open.
end($stack)
->advance($text, strlen($text));
while (count($stack) > 1) {
$dangling = array_pop($stack);
end($stack)
->breakTag($dangling);
}
return end($stack);
}