You are here

class FrxCrosstab in Forena Reports 8

Same name in this branch
  1. 8 src/FrxPlugin/Template/FrxCrosstab.php \Drupal\forena\Template\FrxCrosstab
  2. 8 src/FrxPlugin/Renderer/FrxCrosstab.php \Drupal\forena\FrxPlugin\Renderer\FrxCrosstab

Crosstab Report Template

Plugin annotation


@FrxTemplate(id="FrxCrosstab", name="Cross Tab Data")

Hierarchy

Expanded class hierarchy of FrxCrosstab

2 string references to 'FrxCrosstab'
FrxCrosstab::generate in src/FrxPlugin/Template/FrxCrosstab.php
FrxSVGGraph::generateCrossTab in src/FrxPlugin/Template/FrxSVGGraph.php
Generate a crosstab table.

File

src/FrxPlugin/Template/FrxCrosstab.php, line 12

Namespace

Drupal\forena\Template
View source
class FrxCrosstab extends TemplateBase {
  use FrxAPI;
  public $templateName = 'Crosstab';
  private $headers = array();
  private $dim_columns = array();
  private $group_columns = array();
  private $dim_headers = array();
  private $group_headers = array();
  private $weight;

  /**
   * Crosstab configuration form.
   */
  public function configForm($config) {

    // Load header informationi from parent config.
    $form = parent::configForm($config);
    $this
      ->weight_sort($config['crosstab_columns']);
    $types = array(
      'heading' => t('Heading'),
      'crosstab' => t('Crosstab'),
      'value' => 'Value',
      'ignore' => t('Ignore'),
    );
    $form['crosstab_columns'] = array(
      '#theme' => 'forena_element_draggable',
      '#draggable_id' => 'FrxCrosstab-columns',
    );
    foreach ($config['crosstab_columns'] as $key => $col) {
      $ctl = array();
      $ctl['label'] = array(
        '#type' => 'textfield',
        '#size' => 30,
        '#title' => t('Label'),
        '#default_value' => $col['label'],
      );
      $ctl['contents'] = array(
        '#type' => 'textfield',
        '#size' => '30',
        '#title' => t('Data'),
        '#default_value' => $col['contents'],
      );
      $ctl['type'] = array(
        '#type' => 'radios',
        '#title' => t('Type'),
        '#default_value' => $col['type'],
        '#options' => $types,
        '#ajax' => $this
          ->configAjax(),
      );
      $ctl['weight'] = array(
        "#type" => 'weight',
        '#title' => t('Weight'),
        '#delta' => 50,
        '#default_value' => $col['weight'],
      );
      $form['crosstab_columns'][$key] = $ctl;
    }
    return $form;
  }
  public function generate() {
    $config['class'] = get_class($this);
    $block = @$config['block'];
    $id = @$config['id'];
    if ($block) {
      $id = $this
        ->idFromBlock($block);
      $config['id'] = $id . '_block';
    }
    $config['class'] = @$config['class'] ? $config['class'] . ' FrxCrosstab' : 'FrxCrosstab';
    $div = $this
      ->blockDiv($config);

    // PUt on the header
    $this
      ->removeChildren($div);
    if (isset($config['header']['value'])) {
      $this
        ->addFragment($div, $config['header']['value']);
    }

    // Decide to inlcude columns
    $found_columns = $this
      ->columns($xml);
    if (!$found_columns) {
      $found_columns = $this
        ->columns($xml, '/*');
      $attrs = array();
    }
    $numeric_columns = $this->numeric_columns;
    $new_columns = @$config['crosstab_columns'] ? FALSE : TRUE;
    foreach ($found_columns as $column => $label) {
      $token = '{' . $column . '}';
      if ($new_columns) {
        $type = isset($numeric_columns[$column]) ? 'value' : 'heading';
      }
      else {
        $type = 'ignore';
      }
      if (!isset($config['crosstab_columns'][$column])) {
        $this
          ->addColumn($type, '{' . $column . '}', $column, $config);
      }
    }

    // Generate the grouping row
    $group = '';
    $dim = array();
    foreach ($config['crosstab_columns'] as $col) {
      if ($col['type'] == 'heading') {
        $group .= $col['contents'];
      }
      if ($col['type'] == 'crosstab') {
        $dim = $col['contents'];
      }
    }
    $r_id = $id . '-renderer';
    $table_frx['renderer'] = 'FrxCrosstab';
    $table_frx['group'] = $group;
    $table_frx['dim'] = $dim;
    $attrs[$id] = $r_id;

    //$attrs = array('foreach' => '*');
    $table = $this
      ->setFirstNode($div, 4, 'table', NULL, $attrs, $table_frx);
    $thead = $this
      ->setFirstNode($table, 6, 'thead');
    $throw = $this
      ->setFirstNode($thead, 8, 'tr');
    $tbody = $this
      ->setFirstNode($table, 6, 'tbody');
    $tdrow = $this
      ->setFirstNode($tbody, 8, 'tr', NULL, array(
      'id' => $id,
    ), $attrs);
    if ($config['crosstab_columns']) {
      foreach ($config['crosstab_columns'] as $key => $col) {
        if ($col['type'] !== 'ignore') {
          if ($col['type'] == 'heading') {
            $tag = 'th';
          }
          else {
            $tag = 'td';
          }
          if ($col['type'] != 'crosstab') {
            $this
              ->addNode($throw, 10, $tag, $col['label']);
            $this
              ->addNode($tdrow, 10, $tag, $col['contents']);
          }
        }
      }
    }
    if (isset($config['footer']['value'])) {
      $this
        ->addFragment($div, $config['footer']['value']);
    }
  }

  /**
   * Default configuration validator. Simply validates header and footer attributes.
   * @param array $config
   *   configuration
   * @return array
   *   errors in configuration.
   */
  public function configValidate(&$config) {
    $errors = $this
      ->validateTextFormats($config, array(
      'header',
      'footer',
    ));
    $dims = 0;
    if (@$config['crosstab_columns']) {
      foreach ($config['crosstab_columns'] as $col) {
        if (@$col['type'] == 'value') {
          $dims++;
        }
      }
    }
    if ($dims > 1) {
      $errors[] = t('Too many value columns.  Please select only one');
    }
    return $errors;
  }
  private function addColumn($type, $token, $label, &$config) {
    $key = trim($token, '{}');
    $this->weight++;
    $config['crosstab_columns'][$key] = array(
      'contents' => $token,
      'label' => $label,
      'type' => $type,
      'weight' => $this->weight,
    );
  }

  /**
   * Extract table configuration from the HTML
   * @see FrxRenderer::scrapeConfig()
   */
  public function scrapeConfig(\SimpleXMLElement $xml) {
    $this->weight = 0;
    $config = array();
    $nodes = $this->reportDocNode
      ->xpath('//table');
    if ($nodes) {
      $table = $nodes[0];
      $attrs = $this
        ->mergedAttributes($table);
    }
    $config['group'] = $group = $attrs['group'];
    $config['dim'] = $dim = $attrs['dim'];
    $this
      ->extractTemplateHTML($this->reportDocDomNode, $config, array(
      'table',
    ));
    $head_ths = $this
      ->extractXPathInnerHTML('*//thead/tr/th', $this->reportDocDomNode, FALSE);
    $head_tds = $this
      ->extractXPathInnerHTML('*//thead/tr/td', $this->reportDocDomNode, FALSE);
    $body_ths = $this
      ->extractXPathInnerHTML('*//tbody/tr/th', $this->reportDocDomNode, FALSE);
    $body_tds = $this
      ->extractXPathInnerHTML('*//tbody/tr/td', $this->reportDocDomNode, FALSE);
    $heading_cols = array_combine($head_ths, $body_ths);
    $data_cols = array_combine($head_tds, $body_tds);

    // Get the named headers
    foreach ($heading_cols as $label => $token) {
      $this
        ->addColumn('heading', $token, $label, $config);
    }

    // Get the data cells
    if ($dim) {
      $dims = (array) $dim;
      foreach ($dims as $dim) {
        $this
          ->addColumn('crosstab', $dim, trim($dim, '{}'), $config);
      }
    }
    foreach ($data_cols as $label => $token) {
      $this
        ->addColumn('value', $token, $label, $config);
    }
    return $config;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
FrxAPI::app public function Returns containing application service
FrxAPI::currentDataContext public function Get the current data context.
FrxAPI::currentDataContextArray public function
FrxAPI::dataManager public function Returns the data manager service
FrxAPI::dataService public function Return Data Service
FrxAPI::documentManager public function Returns the fornea document manager
FrxAPI::error public function Report an error
FrxAPI::getDataContext public function Get the context of a specific id.
FrxAPI::getDocument public function Get the current document
FrxAPI::getReportFileContents public function Load the contents of a file in the report file system.
FrxAPI::innerXML function Enter description here... 1
FrxAPI::popData public function Pop data off of the stack.
FrxAPI::pushData public function Push data onto the Stack
FrxAPI::report public function Run a report with a particular format. 1
FrxAPI::reportFileSystem public function Get the current report file system.
FrxAPI::setDataContext public function Set Data context by id.
FrxAPI::setDocument public function Change to a specific document type.
FrxAPI::skins public function Get list of skins.
FrxCrosstab::$dim_columns private property
FrxCrosstab::$dim_headers private property
FrxCrosstab::$group_columns private property
FrxCrosstab::$group_headers private property
FrxCrosstab::$headers private property
FrxCrosstab::$templateName public property
FrxCrosstab::$weight private property
FrxCrosstab::addColumn private function
FrxCrosstab::configForm public function Crosstab configuration form.
FrxCrosstab::configValidate public function Default configuration validator. Simply validates header and footer attributes.
FrxCrosstab::generate public function Overrides TemplateInterface::generate
FrxCrosstab::scrapeConfig public function Extract table configuration from the HTML Overrides TemplateInterface::scrapeConfig
TemplateBase::$columns public property
TemplateBase::$configuration public property @var array Confiuration of template
TemplateBase::$id public property
TemplateBase::$name public property
TemplateBase::$numeric_columns public property
TemplateBase::$xmlns public property
TemplateBase::columns public function Extract a list of columns from the data context.
TemplateBase::configure public function Overrides TemplateInterface::configure