public function CollapseText::processRecurseLevels in Collapse Text 8
Same name and namespace in other branches
- 2.0.x src/Plugin/Filter/CollapseText.php \Drupal\collapse_text\Plugin\Filter\CollapseText::processRecurseLevels()
Helper function to translate the flat levels array into a tree.
This function is recursive.
1 call to CollapseText::processRecurseLevels()
- CollapseText::process in src/
Plugin/ Filter/ CollapseText.php - Performs the filter processing.
File
- src/
Plugin/ Filter/ CollapseText.php, line 339
Class
- CollapseText
- Provides a filter to display Collapsible text blocks.
Namespace
Drupal\collapse_text\Plugin\FilterCode
public function processRecurseLevels($string, $string_start, $string_end, $elements, $options) {
$text_start = $string_start;
$text_length = $string_end - $string_start;
$child_start = $string_start;
$child_end = $string_end;
$slice_start = -1;
// Find the first start element.
$elt_start_found = FALSE;
$elt_start = 0;
while (!$elt_start_found and $elt_start < count($elements)) {
if ($elements[$elt_start]['type'] == 'start') {
$elt_start_found = TRUE;
}
else {
$elt_start++;
}
}
if ($elt_start_found) {
// If there is an opening element,
// set the text length to everything up to it.
$text_length = $elements[$elt_start]['start'] - $string_start;
$child_start = $elements[$elt_start]['end'];
$slice_start = $elt_start + 1;
}
else {
// Otherwise, return everything in this segment as a string.
return [
[
'type' => 'text',
'value' => substr($string, $text_start, $text_length),
],
];
}
// Find the next end element at the same level.
$elt_end_found = FALSE;
$elt_end = $elt_start;
while (!$elt_end_found and $elt_end < count($elements)) {
if ($elements[$elt_end]['type'] == 'end' and $elements[$elt_end]['level'] == $elements[$elt_start]['level']) {
$elt_end_found = TRUE;
}
else {
$elt_end++;
}
}
if ($elt_end_found) {
$child_end = $elements[$elt_end]['start'];
$slice_length = $elt_end - $slice_start;
}
else {
// There is a matching failure.
// Try skipping the start element...
if ($elt_start + 1 < count($elements)) {
return $this
->processRecurseLevels($string, $string_start, $string_end, array_slice($elements, $elt_start + 1), $options);
}
else {
// Fall back to just returning the string...
// Reset the text length.
$text_length = $string_end - $text_start;
return [
[
'type' => 'text',
'value' => substr($string, $text_start, $text_length),
],
];
}
}
$parts = [];
// Add the text before the opening element.
$parts[] = [
'type' => 'text',
'value' => substr($string, $text_start, $text_length),
];
// Add the child element.
$parts[] = [
'type' => 'child',
'tag' => $elements[$elt_start]['tag'],
'value' => $this
->processRecurseLevels($string, $child_start, $child_end, array_slice($elements, $slice_start, $slice_length), $options),
];
// Tail recurse (which ideally could be optimized away,
// although it won't be...) to handle any siblings.
$parts = array_merge($parts, $this
->processRecurseLevels($string, $elements[$elt_end]['end'], $string_end, array_slice($elements, $elt_end), $options));
// Return the result.
return $parts;
}