You are here

public function RendererBase::renderDomNode in Forena Reports 7.5

Recursive report renderer Walks the nodes rendering the report.

2 calls to RendererBase::renderDomNode()
RendererBase::render in src/Renderer/RendererBase.php
Default Render action, which simply does normal forena rendering. You can use renderDomNode at any time to generate the default forena rendering methods.
RendererBase::renderChildren in src/Renderer/RendererBase.php

File

src/Renderer/RendererBase.php, line 87
FrxRenderer.php Base class for Frx custom Renderer @author davidmetzler

Class

RendererBase

Namespace

Drupal\forena\Renderer

Code

public function renderDomNode(DOMNode $dom_node, &$o) {

  // Write out buffer if we've gotten too big
  if ($this->frxReport->allowDirectWrite && strlen($this->frxReport->html) > 100000) {
    $this->frxReport
      ->writeBuffer();
  }
  $continue = TRUE;
  $is_data_block = FALSE;

  //$o = '';
  $node_type = $dom_node->nodeType;
  $settings = $this->settings;
  $context = Frx::Data()
    ->currentContextArray();
  $last_block = $this->blockName;

  // Shortcut process a text node
  if ($node_type == XML_TEXT_NODE || $node_type == XML_ENTITY_REF_NODE || $node_type == XML_ENTITY_NODE) {
    $text = $dom_node->textContent;
    if (!empty($settings['stripWhiteSpace'])) {
      $o .= trim($this->frxReport
        ->replace(htmlspecialchars($text, ENT_NOQUOTES)));
    }
    else {
      $o .= $this->frxReport
        ->replace(htmlspecialchars($text, ENT_NOQUOTES));
    }
    return;
  }

  //Handle comment nodes
  if ($node_type == XML_COMMENT_NODE) {
    if (!empty($dom_node->length) && !empty($dom_node->data)) {
      $text = $dom_node->data;

      // strip empty comments if configured to
      if (!empty($settings['stripEmptyComments'])) {
        $comment_text = trim($this->frxReport
          ->replace($text));
        if ($comment_text === '') {
          return '';
        }
      }

      // comment markup is stripped so need to add it back in
      $o .= '<!--' . $this->frxReport
        ->replace($text) . '-->';
      return;
    }
    else {
      return;
    }
  }

  // Continue processing non text nodes
  $node = simplexml_import_dom($dom_node);

  // Special catch to make sure we don't process bad nodes
  if (!is_object($node)) {
    return;
  }
  $frx = $node
    ->attributes(FRX_NS);
  $include_root = !isset($frx['skip_root']) || !$frx['skip_root'];
  $elements = $dom_node->childNodes->length;

  // Check for invalid link processing.
  if (@(string) $frx['invalid_link']) {
    $old_link_mode = $this->link_mode;
    $this->frxReport->link_mode = (string) $frx['invalid_link'];
  }

  // Test to see if we have any nodes that contain data url
  $attrs = $node
    ->attributes();
  $id = (string) $attrs['id'];
  $tag = $node
    ->getName();
  $has_children = TRUE;

  // Preprocessing for detecting blank nodes
  if (@$settings['stripEmptyElements']) {
    $has_children = count($node
      ->children()) > 0;
    $has_attributes = FALSE;
    foreach ($attrs as $attr) {
      if (trim($this->frxReport
        ->replace((string) $attr))) {
        $has_attributes = TRUE;
      }
    }
    if (!$has_children && !$has_attributes) {
      $has_text = trim($this->frxReport
        ->replace((string) $dom_node->textContent)) !== '';
      if (!$has_text) {
        return;
      }
      else {
        $has_children = TRUE;
      }
    }
  }
  else {
    $has_children = count($node
      ->children()) > 0 || trim($dom_node->textContent) !== '';
  }
  if ((string) $frx['block']) {

    // Determine the context
    $this->blockName = (string) $frx['block'];
    $this->blockParms = $context;
    if ($this->frxReport->preview_mode) {
      $o .= Frx::Editor()
        ->blockLinks($this->blockName, $frx, $attrs, $id, $this->blockParms);
    }

    // Now get the block
    $is_data_block = TRUE;
    $xml = $this->frxReport
      ->getData((string) $frx['block'], $id, (string) $frx['parameters']);
    if ($xml) {
      Frx::Data()
        ->push($xml, $id);
    }
    else {
      if ($id) {
        Frx::Data()
          ->setContext($id, $xml);
      }
      return;
    }
  }

  //Implment if then logic
  if ((string) $frx['if']) {
    $cond = (string) $frx['if'];
    if (!$this->frxReport
      ->test($cond)) {
      return;
    }
  }

  // Preserve plain attributes
  $attr_text = '';
  $tmp_attrs = array();
  if ($attrs) {
    foreach ($attrs as $key => $value) {
      $attr_text .= ' ' . $key . '="' . (string) $value . '"';
      $tmp_attrs[$key] = (string) $value;
    }
  }

  // Preserve other namespaced attributes
  $ns_attrs = '';
  foreach ($node
    ->getNamespaces() as $ns_key => $ns_uri) {
    if ($ns_key && $ns_key != 'frx') {
      foreach ($node
        ->attributes($ns_uri) as $key => $value) {
        $ns_attrs .= ' ' . $ns_key . ':' . $key . '="' . (string) $value . '"';
      }
    }
  }

  // Check for include syntax
  $include_file = (string) $frx['include'];
  if ($include_file) {
    $parms = Frx::Data()
      ->currentContextArray();
    $o .= forena_report_include($include_file, $parms);
    return;
  }

  // Determine if we have a custom renderer
  $renderer = (string) $frx['renderer'];

  // if we have a foreach in this node, we need to iterate the children
  if ((string) $frx['foreach']) {

    // Get proper XML for current data context.
    $path = $this->frxReport
      ->replace((string) $frx['foreach'], TRUE);
    if ($path && strpos($path, '.')) {
      @(list($context, $path) = explode('.', $path, 2));
      $data = Frx::Data()
        ->getContext($context);
    }
    else {
      $data = Frx::Data()
        ->currentContext();
    }
    if (is_object($data) || $path != '*') {
      if (method_exists($data, 'xpath') || is_array($data)) {
        if (is_array($data)) {
          $data = FrxData::arrayToXml($data);
        }
        $nodes = $data
          ->xpath($path);
      }
      else {
        $nodes = $data;
      }
    }
    else {
      $nodes = (array) $data;
    }

    // Sort values
    $sort = @(string) $frx['sort'];
    if ($sort) {
      $compare_type = @(string) $frx['compare'];
      $this->frxReport
        ->sort($data, $sort, $compare_type);
    }

    //  values
    $group = @(string) $frx['group'];
    if ($group) {
      $opt = $this
        ->mergedAttributes($node);
      $sums = (array) @$opt['sum'];
      $nodes = $this->frxReport
        ->group($nodes, $group, $sums);
    }
    $i = 0;

    //$tmp_attrs = (array)$attrs;
    if ($nodes) {
      foreach ($nodes as $x) {
        if ($group) {
          Frx::Data()
            ->setContext('group', $x[0]);
        }
        Frx::Data()
          ->push($x, $id);
        $i++;
        $odd = $i & 1;
        $row_class = $odd ? 'odd' : 'even';
        $r_attr_text = '';
        if (trim($id)) {
          if (strpos($attrs['id'], '{') !== FALSE) {
            $id_attr = $this->frxReport
              ->replace($attrs['id']);
          }
          else {
            if (!empty($settings['numericFrxForeachID'])) {
              $id_attr = $i;
            }
            else {
              $id_attr = $attrs['id'] . '-' . $i;
            }
          }
          $tmp_attrs['id'] = $id_attr;
        }
        if (@(!$settings['noHelperClasses'])) {
          $tmp_attrs['class'] = trim($attrs['class'] . ' ' . $row_class);
        }
        foreach ($tmp_attrs as $key => $value) {
          $r_attr_text .= ' ' . $key . '="' . (string) $value . '"';
        }
        if ($include_root) {
          $o .= $this->frxReport
            ->replace('<' . $tag . $r_attr_text . $ns_attrs . '>', TRUE);
        }
        foreach ($dom_node->childNodes as $child) {
          $this
            ->renderDomNode($child, $o);
        }
        if ($i == 1 && strtolower($tag) == 'div' && $this->frxReport->preview_mode) {
          $o .= Frx::Editor()
            ->foreachLinks($this->blockName, $attrs['id']);
        }
        if ($include_root) {
          $o .= '</' . $tag . '>';
        }
        Frx::Data()
          ->pop();
      }
    }
  }
  elseif ($continue) {
    if ($renderer) {

      // Implement custom renderer.
      $co = Frx::Controls($renderer);
      if ($co) {
        $co
          ->initReportNode($dom_node, $this->frxReport);
        if (!empty($settings['stripWhiteSpace'])) {
          $o .= trim($co
            ->render());
        }
        else {
          $o .= $co
            ->render();
        }
      }
    }
    else {
      if ($has_children) {
        if ($include_root) {
          $o .= $this->frxReport
            ->replace('<' . $tag . $attr_text . $ns_attrs . '>', TRUE);
        }

        // None found, so render children
        foreach ($dom_node->childNodes as $child) {
          $this
            ->renderDomNode($child, $o);
        }
        if ($include_root) {
          $o .= '</' . $tag . '>';
        }
      }
      else {
        $o .= $this->frxReport
          ->replace('<' . $tag . $attr_text . $ns_attrs . '/>', TRUE);
      }
    }
  }
  if ($is_data_block && $continue) {
    Frx::Data()
      ->pop();
  }

  // Restore link processing.
  if (@(string) $frx['invalid_link']) {
    $this->frxReport->link_mode = $old_link_mode;
  }
  $this->blockName = $last_block;
  return;
}