forena-8.x-1.x-dev/src/FrxPlugin/Renderer/FrxCrosstab.php
src/FrxPlugin/Renderer/FrxCrosstab.php
<?php namespace Drupal\forena\FrxPlugin\Renderer; use Drupal\forena\AppService; use Drupal\forena\FrxAPI; /** * Crosstab Renderer * * @FrxRenderer(id = "FrxCrosstab") * */ class FrxCrosstab extends RendererBase { use FrxAPI; public $templateName = 'Crosstab'; private $dim_columns = array(); private $group_columns = array(); private $dim_headers = array(); private $group_headers = array(); /** * Generate default headers from Embedded xml. */ private function defaultHeaders() { $node = $this->reportNode; if ($node->thead && $node->thead->tr) { /** @var \SimpleXMLElement $cell */ foreach ($node->thead->tr->children() as $name => $cell) { $hcol = array(); $hcol['data'] = $this->innerXML($cell); $hcol['depth'] = 1; foreach ($cell->attributes() as $k => $v) { $hcol[$k] = (string)$v; } if ($name == 'th') { $this->group_headers[] = $hcol; } else { $this->dim_headers[] = $hcol; } } } if ($node->tbody && $node->tbody->tr) { foreach ($node->tbody->tr->children() as $name => $cell) { $col = array(); $col['data'] = $this->innerXML($cell); foreach ($cell->attributes() as $k => $v) { $col[$k] = (string)$v; } if ($name == 'th') { $this->group_columns[] = $col; } else { $this->dim_columns[] = $col; } } } } /** * Render the crosstab */ public function render() { $variables = $this->mergedAttributes(); $attributes = $this->replacedAttributes(); $format = $this->documentManager()->getDocumentType(); if (!empty($variables['hidden']) && $format != 'csv' && $format != 'xls') { return ''; } $path = isset($variables['path']) ? $variables['path'] : '*'; if (!$path) $path = "*"; $group = $variables['group']; $dim = $variables['dim']; $sum = (array)@$variables['sum']; // Get the current context $data = $this->currentDataContext(); // Generate the data nodes. if (is_object($data)) { if (method_exists($data, 'xpath')) { $nodes = $data->xpath($path); } else { $nodes = $data; } } else { $nodes = (array)$data; } // Group the data. $data = $this->report->group($nodes, $group, $sum); $this->dim_headers = array(); $dim_rows = array(); $this->dim_columns = array(); $this->group_columns = array(); $this->group_headers = array(); $dim_values = array(); $rows = array(); foreach ($data as $gk => $group_rows) { $dims = $this->report->group($group_rows, $dim); $rows[$gk] = $group_rows[0]; foreach($dims as $dk=>$r) { $dim_values[$dk] = $dk; $dim_rows[$gk][$dk] = $r[0]; } } // Default controling attributes $this->defaultHeaders(); $hrow = array(); foreach ($this->group_headers as $col) { $cell = $col; if (count($this->dim_columns) > 1) $cell['rowspan'] = 2; $hrow[] = $cell; } // Add the dimension headers. foreach ($dim_values as $dk) { foreach ($this->dim_headers as $i => $col) { $cell = $col; $cell['data'] = $dk; if (count($this->dim_columns) > 1) { $cell['data'] = $i ? $col['data'] : $dk . ' ' . $col['data']; } $hrow [] = $cell; } } $trows = array(); foreach ($rows as $k=>$row) { $this->pushData($row, '_group'); $trow = array(); // Base group foreach($this->group_columns as $col) { $cell = $col; foreach ($col as $key => $v) { $cell[$key] = $this->report->replace($v); } $trow[] = $cell; } $this->popData(); // Dimensions $dim_data = $dim_rows[$k]; foreach($dim_values as $dk) { $dim_row = isset($dim_data[$dk]) ? $dim_data[$dk] : array(); $this->pushData($dim_row, '_dim'); foreach($this->dim_columns as $col) { $cell = $col; foreach ($col as $k => $v) { $cell[$k] = $this->report->replace($v); } $trow[] = $cell; } $this->popData(); } $trows[] = $trow; } $class = 'crosstab-table'; if (isset($attributes['class'])) $class .= ' ' . $attributes['class']; $elements[] = [ '#type' => 'table', '#header' => $hrow, '#rows' => $trows, '#attributes' => array('class' => array($class)), ]; $output = AppService::instance()->drupalRender($elements); return $output; } }