You are here

function _collapse_text_process_recurse_levels in Collapse Text 7.2

Same name and namespace in other branches
  1. 6.2 collapse_text.module \_collapse_text_process_recurse_levels()

translate the flat levels array into a tree.

this function is recursive.

1 call to _collapse_text_process_recurse_levels()
_collapse_text_filter_process in ./collapse_text.module
Implements hook_filter_FILTER_process().

File

./collapse_text.module, line 346
collapse_text is an input filter that allows text to be collapsible

Code

function _collapse_text_process_recurse_levels($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;
  $slice_end = count($elements);

  // 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 array(
      array(
        '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 _collapse_text_process_recurse_levels($string, $string_start, $string_end, array_slice($elements, $elt_start + 1), $options);
    }
    else {

      // fall back to just returning the string...
      $text_length = $string_end - $text_start;

      // reset the text length
      return array(
        array(
          'type' => 'text',
          'value' => substr($string, $text_start, $text_length),
        ),
      );
    }
  }
  $parts = array();

  // add the text before the opening element
  $parts[] = array(
    'type' => 'text',
    'value' => substr($string, $text_start, $text_length),
  );

  // add the child element
  $parts[] = array(
    'type' => 'child',
    'tag' => $elements[$elt_start]['tag'],
    'value' => _collapse_text_process_recurse_levels($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, _collapse_text_process_recurse_levels($string, $elements[$elt_end]['end'], $string_end, array_slice($elements, $elt_end), $options));

  // return the result
  return $parts;
}