mirror of
https://github.com/cosmocode/dokuwiki-plugin-struct.git
synced 2025-08-13 13:37:20 +00:00
major refactoring of the whole table aggregation
this is still completely untested
This commit is contained in:
395
meta/AggregationTable.php
Normal file
395
meta/AggregationTable.php
Normal file
@ -0,0 +1,395 @@
|
||||
<?php
|
||||
|
||||
namespace plugin\struct\meta;
|
||||
|
||||
class AggregationTable {
|
||||
|
||||
/**
|
||||
* @var string the page id of the page this is rendered to
|
||||
*/
|
||||
protected $id;
|
||||
/**
|
||||
* @var string the Type of renderer used
|
||||
*/
|
||||
protected $mode;
|
||||
/**
|
||||
* @var \Doku_Renderer the DokuWiki renderer used to create the output
|
||||
*/
|
||||
protected $renderer;
|
||||
/**
|
||||
* @var SearchConfig the configured search - gives access to columns etc.
|
||||
*/
|
||||
protected $searchConfig;
|
||||
|
||||
/**
|
||||
* @var Column[] the list of columns to be displayed
|
||||
*/
|
||||
protected $columns;
|
||||
|
||||
/**
|
||||
* @var Value[][] the search result
|
||||
*/
|
||||
protected $result;
|
||||
|
||||
/**
|
||||
* @var int number of all results
|
||||
*/
|
||||
protected $resultCount;
|
||||
|
||||
/**
|
||||
* @var array for summing up columns
|
||||
*/
|
||||
protected $sums;
|
||||
|
||||
/**
|
||||
* @todo we might be able to get rid of this helper and move this to SearchConfig
|
||||
* @var \helper_plugin_struct_config
|
||||
*/
|
||||
protected $helper;
|
||||
|
||||
/**
|
||||
* Initialize the Aggregation renderer and executes the search
|
||||
*
|
||||
* You need to call @see render() on the resulting object.
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $mode
|
||||
* @param \Doku_Renderer $renderer
|
||||
* @param SearchConfig $searchConfig
|
||||
*/
|
||||
public function __construct($id, $mode, \Doku_Renderer $renderer, SearchConfig $searchConfig) {
|
||||
$this->id = $id;
|
||||
$this->mode = $mode;
|
||||
$this->renderer = $renderer;
|
||||
$this->searchConfig = $searchConfig;
|
||||
$this->data = $searchConfig->getConf();
|
||||
$this->columns = $searchConfig->getColumns();
|
||||
|
||||
$this->result = $this->searchConfig->execute();
|
||||
$this->resultCount = $this->searchConfig->getCount();
|
||||
$this->helper = plugin_load('helper', 'struct_config');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the table on the renderer
|
||||
*/
|
||||
public function render() {
|
||||
// table open
|
||||
$this->startScope();
|
||||
$this->showActiveFilters();
|
||||
$this->renderer->table_open();
|
||||
|
||||
// header
|
||||
$this->renderer->tablethead_open();
|
||||
$this->buildColumnHeaders();
|
||||
$this->addDynamicFilters();
|
||||
$this->renderer->tablethead_close();
|
||||
|
||||
if($this->resultCount) {
|
||||
// actual data
|
||||
$this->renderRows();
|
||||
|
||||
// footer
|
||||
$this->summarize();
|
||||
$this->addLimitControls();
|
||||
} else {
|
||||
// nothing found
|
||||
$this->nullRow();
|
||||
}
|
||||
|
||||
// table close
|
||||
$this->renderer->table_close();
|
||||
$this->finishScope();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds additional info to document and renderer in XHTML mode
|
||||
*
|
||||
* @see finishScope()
|
||||
*/
|
||||
protected function startScope() {
|
||||
if($this->mode != 'xhtml') return;
|
||||
|
||||
// wrapping div
|
||||
$this->renderer->doc .= "<div class=\"structaggregation\">";
|
||||
|
||||
// unique identifier for this aggregation
|
||||
$this->renderer->info['struct_table_hash'] = md5(var_export($this->data, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the table and anything opened in startScope()
|
||||
*
|
||||
* @see startScope()
|
||||
*/
|
||||
protected function finishScope() {
|
||||
if($this->mode != 'xhtml') return;
|
||||
|
||||
// wrapping div
|
||||
$this->renderer->doc .= '</div>';
|
||||
|
||||
// remove identifier from renderer again
|
||||
if(isset($this->renderer->info['struct_table_hash'])) {
|
||||
unset($this->renderer->info['struct_table_hash']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays info about the currently applied filters
|
||||
*/
|
||||
protected function showActiveFilters() {
|
||||
if($this->mode != 'xhtml') return;
|
||||
$dynamic = $this->searchConfig->getDynamicParameters();
|
||||
$filters = $dynamic->getFilters();
|
||||
if(!$filters) return;
|
||||
|
||||
$fltrs = array();
|
||||
foreach($filters as $column => $filter) {
|
||||
list($comp, $value) = $filter;
|
||||
|
||||
if(strpos($comp, '~') !== false) {
|
||||
if(strpos($comp, '!~') !== false) {
|
||||
$comparator_value = '!~' . str_replace('%', '*', $value);
|
||||
} else {
|
||||
$comparator_value = '~' . str_replace('%', '', $value);
|
||||
}
|
||||
$fltrs[] = $column . $comparator_value;
|
||||
} else {
|
||||
$fltrs[] = $column . $comp . $value;
|
||||
}
|
||||
}
|
||||
|
||||
$this->renderer->doc .= '<div class="filter">';
|
||||
$this->renderer->doc .= '<h4>' . sprintf($this->helper->getLang('tablefilteredby'), hsc(implode(' & ', $fltrs))) . '</h4>';
|
||||
$this->renderer->doc .= '<div class="resetfilter">';
|
||||
$this->renderer->internallink($this->id, $this->helper->getLang('tableresetfilter'));
|
||||
$this->renderer->doc .= '</div>';
|
||||
$this->renderer->doc .= '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the column headers with links to sort by column
|
||||
*/
|
||||
protected function buildColumnHeaders() {
|
||||
$this->renderer->tablerow_open();
|
||||
|
||||
// additional column for row numbers
|
||||
if($this->data['rownumbers']) {
|
||||
$this->renderer->tableheader_open();
|
||||
$this->renderer->cdata('#');
|
||||
$this->renderer->tableheader_close();
|
||||
}
|
||||
|
||||
// show all headers
|
||||
foreach($this->data['headers'] as $num => $header) {
|
||||
$column = $this->columns[$num];
|
||||
|
||||
// use field label if no header was set
|
||||
if(blank($header)) {
|
||||
if(is_a($column, 'plugin\struct\meta\PageColumn')) {
|
||||
$header = $this->helper->getLang('pagelabel'); // @todo this could be part of PageColumn::getTranslatedLabel
|
||||
} else if(is_a($column, 'plugin\struct\meta\Column')) {
|
||||
$header = $column->getTranslatedLabel();
|
||||
} else {
|
||||
$header = 'column ' . $num; // this should never happen
|
||||
}
|
||||
}
|
||||
|
||||
// simple mode first
|
||||
if($this->mode != 'xhtml') {
|
||||
$this->renderer->tableheader_open();
|
||||
$this->renderer->cdata($header);
|
||||
$this->renderer->tableheader_close();
|
||||
continue;
|
||||
}
|
||||
|
||||
// still here? create custom header for more flexibility
|
||||
|
||||
// width setting
|
||||
$width = '';
|
||||
if(isset($data['widths'][$num]) && $data['widths'][$num] != '-') {
|
||||
$width = ' style="width: ' . $data['widths'][$num] . ';"';
|
||||
}
|
||||
|
||||
// sort indicator and link
|
||||
$sortclass = '';
|
||||
$sorts = $this->searchConfig->getSorts();
|
||||
$dynamic = $this->searchConfig->getDynamicParameters();
|
||||
if(isset($sorts[$column->getFullQualifiedLabel()])) {
|
||||
list(, $currentSort) = $sorts[$column->getFullQualifiedLabel()];
|
||||
if($currentSort[1]) {
|
||||
$sortclass = 'sort-down';
|
||||
$dynamic->setSort($column, false);
|
||||
} else {
|
||||
$sortclass = 'sort-up';
|
||||
}
|
||||
}
|
||||
$dynamic->setSort($column, true);
|
||||
$link = wl($this->id, $dynamic->getURLParameters());
|
||||
|
||||
// output XHTML header
|
||||
$this->renderer->doc .= "<th $width >";
|
||||
$this->renderer->doc .= '<a href="' . $link . '" class="' . $sortclass . '" title="' . $this->helper->getLang('sort') . '">' . hsc($header) . '</a>';
|
||||
$this->renderer->doc .= '</th>';
|
||||
}
|
||||
|
||||
$this->renderer->tablerow_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add input fields for dynamic filtering
|
||||
*/
|
||||
protected function addDynamicFilters() {
|
||||
if($this->mode != 'xhtml') return;
|
||||
if(!$this->data['dynfilters']) return;
|
||||
|
||||
$this->renderer->doc .= '<tr class="dataflt">';
|
||||
|
||||
// add extra column for row numbers
|
||||
if($this->data['rownumbers']) {
|
||||
$this->renderer->doc .= '<th></th>';
|
||||
}
|
||||
|
||||
// each column gets a form
|
||||
foreach($this->columns as $column) {
|
||||
$this->renderer->doc .= '<th>';
|
||||
{
|
||||
$form = new \Doku_Form(array('method' => 'GET', 'action' => wl($this->id)));
|
||||
|
||||
// current value
|
||||
$dynamic = $this->searchConfig->getDynamicParameters();
|
||||
$filters = $dynamic->getFilters();
|
||||
if(isset($filters[$column->getFullQualifiedLabel()])) {
|
||||
list(, $current) = $filters[$column->getFullQualifiedLabel()];
|
||||
$dynamic->removeFilter($column);
|
||||
} else {
|
||||
$current = '';
|
||||
}
|
||||
|
||||
// Add current request params
|
||||
$params = $dynamic->getURLParameters();
|
||||
foreach($params as $key => $val) {
|
||||
$form->addHidden($key, $val);
|
||||
}
|
||||
|
||||
// add input field
|
||||
$key = $column->getFullQualifiedLabel() . '*~';
|
||||
$form->addElement(form_makeField('text', 'dataflt[' . $key . ']', $current, ''));
|
||||
$this->renderer->doc .= $form->getForm();
|
||||
}
|
||||
$this->renderer->doc .= '</th>';
|
||||
}
|
||||
$this->renderer->doc .= '</tr>';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the actual table data
|
||||
*/
|
||||
protected function renderRows() {
|
||||
$this->renderer->tabletbody_open();
|
||||
foreach($this->result as $rownum => $row) {
|
||||
$this->renderer->tablerow_open();
|
||||
|
||||
// row number column
|
||||
if($this->data['rownumbers']) {
|
||||
$this->renderer->tablecell_open();
|
||||
$this->renderer->doc .= $rownum + 1;
|
||||
$this->renderer->tablecell_close();
|
||||
}
|
||||
|
||||
/** @var Value $value */
|
||||
foreach($row as $colnum => $value) {
|
||||
$this->renderer->tablecell_open();
|
||||
$value->render($this->renderer, $this->mode);
|
||||
$this->renderer->tablecell_close();
|
||||
|
||||
// summarize
|
||||
if($this->data['summarize'] && is_numeric($value->getValue())) {
|
||||
if(!isset($this->sums[$colnum])) {
|
||||
$this->sums[$colnum] = 0;
|
||||
}
|
||||
$this->sums[$colnum] += $value->getValue();
|
||||
}
|
||||
}
|
||||
$this->renderer->tablerow_close();
|
||||
}
|
||||
$this->renderer->tabletbody_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an information row for when no results were found
|
||||
*/
|
||||
protected function nullRow() {
|
||||
$this->renderer->tablerow_open();
|
||||
$this->renderer->tablecell_open(count($this->data['cols']) + $this->data['rownumbers'], 'center');
|
||||
$this->renderer->cdata($this->helper->getLang('none'));
|
||||
$this->renderer->tablecell_close();
|
||||
$this->renderer->tablerow_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add sums if wanted
|
||||
*/
|
||||
protected function summarize() {
|
||||
if($this->data['summarize']) return;
|
||||
|
||||
$this->renderer->tablerow_open();
|
||||
$len = count($this->data['cols']);
|
||||
|
||||
if($this->data['rownumbers']) {
|
||||
$this->renderer->tablecell_open();
|
||||
$this->renderer->tablecell_close();
|
||||
}
|
||||
|
||||
for($i = 0; $i < $len; $i++) {
|
||||
$this->renderer->tablecell_open(1, $this->data['align'][$i]);
|
||||
if(!empty($sums[$i])) {
|
||||
$this->renderer->cdata('∑ ' . $sums[$i]);
|
||||
} else {
|
||||
if($this->mode == 'xhtml') {
|
||||
$this->renderer->doc .= ' ';
|
||||
}
|
||||
}
|
||||
$this->renderer->tablecell_close();
|
||||
}
|
||||
$this->renderer->tablerow_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds pagin controls to the table
|
||||
*/
|
||||
protected function addLimitControls() {
|
||||
if(empty($this->data['limit'])) return;
|
||||
if($this->mode != 'xhtml') ;
|
||||
|
||||
$this->renderer->tablerow_open();
|
||||
$this->renderer->tableheader_open((count($this->data['cols']) + ($this->data['rownumbers'] ? 1 : 0)));
|
||||
$offset = $this->data['offset'];
|
||||
|
||||
// prev link
|
||||
if($offset) {
|
||||
$prev = $offset - $this->data['limit'];
|
||||
if($prev < 0) {
|
||||
$prev = 0;
|
||||
}
|
||||
|
||||
$dynamic = $this->searchConfig->getDynamicParameters();
|
||||
$dynamic->setOffset($prev);
|
||||
$link = wl($this->id, $dynamic->getURLParameters());
|
||||
$this->renderer->doc .= '<a href="' . $link . '" class="prev">' . $this->helper->getLang('prev') . '</a>';
|
||||
}
|
||||
|
||||
// next link
|
||||
if($this->resultCount > $offset + $this->data['limit']) {
|
||||
$next = $offset + $this->data['limit'];
|
||||
$dynamic = $this->searchConfig->getDynamicParameters();
|
||||
$dynamic->setOffset($next);
|
||||
$link = wl($this->id, $dynamic->getURLParameters());
|
||||
$this->renderer->doc .= '<a href="' . $link . '" class="next">' . $this->helper->getLang('next') . '</a>';
|
||||
}
|
||||
|
||||
$this->renderer->tableheader_close();
|
||||
$this->renderer->tablerow_close();
|
||||
}
|
||||
}
|
@ -96,7 +96,16 @@ class Search {
|
||||
$col = $this->findColumn($colname);
|
||||
if(!$col) return; //FIXME do we really want to ignore missing columns?
|
||||
|
||||
$this->sortby[] = array($col, $asc);
|
||||
$this->sortby[$col->getFullQualifiedLabel()] = array($col, $asc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all set sort columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSorts() {
|
||||
return $this->sortby;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,11 +45,11 @@ class SearchConfig extends Search {
|
||||
$this->addSort($sort[0], $sort[1] === 'ASC');
|
||||
}
|
||||
|
||||
if (!empty($config['limit'])) {
|
||||
if(!empty($config['limit'])) {
|
||||
$this->setLimit($config['limit']);
|
||||
}
|
||||
|
||||
if (!empty($config['offset'])) {
|
||||
if(!empty($config['offset'])) {
|
||||
$this->setLimit($config['offset']);
|
||||
}
|
||||
}
|
||||
@ -66,24 +66,10 @@ class SearchConfig extends Search {
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the current config.
|
||||
*
|
||||
* When no key is given the whole configuration is returned. With a key only
|
||||
* that key's value is returned. Returns NULL on a non-existing key
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
* @return array the current config
|
||||
*/
|
||||
public function getConf($key='') {
|
||||
if($key) {
|
||||
if(isset($this->config[$key])) {
|
||||
return $this->config[$key];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
public function getConf() {
|
||||
return $this->config;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -102,6 +102,9 @@ class SearchConfigParameters {
|
||||
/**
|
||||
* Adds another filter
|
||||
*
|
||||
* When there is a filter for that column already, the new filter overwrites it. Setting a
|
||||
* blank value is the same as calling @see removeFilter()
|
||||
*
|
||||
* @param string|Column $column
|
||||
* @param string $comp the comparator
|
||||
* @param string $value the value to compare against
|
||||
@ -110,8 +113,12 @@ class SearchConfigParameters {
|
||||
$column = $this->resolveColumn($column);
|
||||
if(!$column) return;
|
||||
|
||||
if(trim($value) === '') {
|
||||
$this->removeFilter($column);
|
||||
} else {
|
||||
$this->filters[$column] = array($comp, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the filter for the given column
|
||||
@ -131,6 +138,13 @@ class SearchConfigParameters {
|
||||
$this->filters = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array the current filters
|
||||
*/
|
||||
public function getFilters() {
|
||||
return $this->filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current parameters in a form that can be used to create URLs
|
||||
*/
|
||||
|
369
syntax/table.php
369
syntax/table.php
@ -6,12 +6,13 @@
|
||||
* @author Andreas Gohr, Michael Große <dokuwiki@cosmocode.de>
|
||||
*/
|
||||
|
||||
// must be run within Dokuwiki
|
||||
use plugin\struct\meta\Column;
|
||||
|
||||
use plugin\struct\meta\AggregationTable;
|
||||
use plugin\struct\meta\ConfigParser;
|
||||
use plugin\struct\meta\SearchConfig;
|
||||
use plugin\struct\meta\StructException;
|
||||
|
||||
// must be run within Dokuwiki
|
||||
if (!defined('DOKU_INC')) die();
|
||||
|
||||
class syntax_plugin_struct_table extends DokuWiki_Syntax_Plugin {
|
||||
@ -68,8 +69,6 @@ class syntax_plugin_struct_table extends DokuWiki_Syntax_Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
protected $sums = array();
|
||||
|
||||
/**
|
||||
* Render xhtml output or metadata
|
||||
*
|
||||
@ -80,379 +79,23 @@ class syntax_plugin_struct_table extends DokuWiki_Syntax_Plugin {
|
||||
*/
|
||||
public function render($mode, Doku_Renderer $renderer, $data) {
|
||||
if(!$data) return false;
|
||||
global $ID;
|
||||
|
||||
if($mode == 'metadata') {
|
||||
/** @var Doku_Renderer_metadata $renderer */
|
||||
$renderer->meta['plugin']['struct']['hasaggregation'] = true;
|
||||
}
|
||||
|
||||
//reset counters
|
||||
$this->sums = array();
|
||||
|
||||
try {
|
||||
$search = new SearchConfig($data);
|
||||
$data = $search->getConf();
|
||||
$rows = $search->execute();
|
||||
$cnt = $search->getCount();
|
||||
$cols = $search->getColumns();
|
||||
|
||||
if ($cnt === 0) {
|
||||
$this->nullList($data, $mode, $renderer, $cols);
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->renderPreTable($mode, $renderer, $data, $cols);
|
||||
$this->renderRows($mode, $renderer, $data, $rows);
|
||||
$this->renderPostTable($mode, $renderer, $data, $cnt);
|
||||
$table = new AggregationTable($ID, $mode, $renderer, $search);
|
||||
$table->render();
|
||||
} catch (StructException $e) {
|
||||
msg($e->getMessage(), -1, $e->getLine(), $e->getFile());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* create the pretext to the actual table rows
|
||||
*
|
||||
* @param string $mode
|
||||
* @param Doku_Renderer $renderer
|
||||
* @param array $data the configuration data
|
||||
* @param Column[] $cols
|
||||
*/
|
||||
protected function renderPreTable($mode, Doku_Renderer $renderer, $data, $cols) {
|
||||
$this->startScope($mode, $renderer, md5(serialize($data)));
|
||||
$this->showActiveFilters($mode, $renderer);
|
||||
$this->startTable($mode, $renderer);
|
||||
$renderer->tablethead_open();
|
||||
$this->buildColumnHeaders($mode, $renderer, $data, $cols);
|
||||
$this->addDynamicFilters($mode, $renderer, $data);
|
||||
$renderer->tablethead_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mode current render mode
|
||||
* @param Doku_Renderer $renderer
|
||||
* @param array $data
|
||||
* @param int $rowcnt
|
||||
* @return string
|
||||
*/
|
||||
private function renderPostTable($mode, Doku_Renderer $renderer, $data, $rowcnt) {
|
||||
$this->summarize($mode, $renderer, $data, $this->sums);
|
||||
$this->addLimitControls($mode, $renderer, $data, $rowcnt);
|
||||
$this->finishTableAndScope($mode, $renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* if limit was set, add control
|
||||
*
|
||||
* @param string $mode the mode of the renderer
|
||||
* @param Doku_Renderer $renderer the renderer
|
||||
* @param array $data the configuration of the table/search
|
||||
* @param $rowcnt
|
||||
*/
|
||||
protected function addLimitControls($mode, Doku_Renderer $renderer, $data, $rowcnt) {
|
||||
global $ID;
|
||||
|
||||
if($data['limit']) {
|
||||
$renderer->tablerow_open();
|
||||
$renderer->tableheader_open((count($data['cols']) + ($data['rownumbers'] ? 1 : 0)));
|
||||
$offset = (int) $_REQUEST['dataofs'];
|
||||
|
||||
// keep url params
|
||||
$params = array();
|
||||
if (!empty($data['current_params']['dataflt'])) {$params['dataflt'] = $data['current_params']['dataflt'];}
|
||||
if (!empty($data['current_params']['datasrt'])) {$params['datasrt'] = $data['current_params']['datasrt'];}
|
||||
|
||||
if($offset) {
|
||||
$prev = $offset - $data['limit'];
|
||||
if($prev < 0) {
|
||||
$prev = 0;
|
||||
}
|
||||
$params['dataofs'] = $prev;
|
||||
$renderer->internallink($ID . '?' . http_build_query($params), $this->getLang('prev'));
|
||||
}
|
||||
|
||||
if($rowcnt > $offset + $data['limit']) {
|
||||
$next = $offset + $data['limit'];
|
||||
$params['dataofs'] = $next;
|
||||
$renderer->internallink($ID . '?' . http_build_query($params), $this->getLang('next'));
|
||||
}
|
||||
$renderer->tableheader_close();
|
||||
$renderer->tablerow_close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mode the mode of the renderer
|
||||
* @param Doku_Renderer $renderer the renderer
|
||||
*/
|
||||
protected function showActiveFilters($mode, Doku_Renderer $renderer) {
|
||||
global $ID;
|
||||
|
||||
if($mode == 'xhtml' && !empty($data['current_params']['dataflt'])) {
|
||||
$filters = $data['current_params']['dataflt'];
|
||||
/** @var helper_plugin_struct_config $confHelper */
|
||||
$confHelper = $this->loadHelper('struct_config');
|
||||
$fltrs = array();
|
||||
foreach($filters as $colcomp => $filter) {
|
||||
$filter = $confHelper->parseFilterLine('', $colcomp.$filter);
|
||||
if(strpos($filter[1], '~') !== false) {
|
||||
if(strpos($filter[1], '!~') !== false) {
|
||||
$comparator_value = '!~' . str_replace('%', '*', $filter[2]);
|
||||
} else {
|
||||
$comparator_value = '~' . str_replace('%', '', $filter[2]);
|
||||
}
|
||||
$fltrs[] = $filter[0] . $comparator_value;
|
||||
} else {
|
||||
$fltrs[] = $filter[0] . $filter[1] . $filter[2];
|
||||
}
|
||||
}
|
||||
|
||||
$renderer->doc .= '<div class="filter">';
|
||||
$renderer->doc .= '<h4>' . sprintf($this->getLang('tablefilteredby'), hsc(implode(' & ', $fltrs))) . '</h4>';
|
||||
$renderer->doc .= '<div class="resetfilter">';
|
||||
$renderer->internallink($ID, $this->getLang('tableresetfilter'));
|
||||
$renderer->doc .= '</div>';
|
||||
$renderer->doc .= '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mode the mode of the renderer
|
||||
* @param Doku_Renderer $renderer the renderer
|
||||
* @param array $data the configuration of the table/search
|
||||
*/
|
||||
protected function addDynamicFilters($mode, Doku_Renderer $renderer, $data) {
|
||||
if ($mode != 'xhtml') return;
|
||||
|
||||
global $conf, $ID;
|
||||
|
||||
$cur_params = $data['current_params'];
|
||||
$html = '';
|
||||
if($data['dynfilters']) {
|
||||
$html .= '<tr class="dataflt">';
|
||||
|
||||
if($data['rownumbers']) {
|
||||
$html .= '<th></th>';
|
||||
}
|
||||
|
||||
foreach($data['headers'] as $num => $head) {
|
||||
$html .= '<th>';
|
||||
$form = new Doku_Form(array('method' => 'GET',));
|
||||
$form->_hidden = array();
|
||||
if(!$conf['userewrite']) {
|
||||
$form->addHidden('id', $ID);
|
||||
}
|
||||
|
||||
$key = $data['cols'][$num] . '*~';
|
||||
$val = isset($cur_params['dataflt'][$key]) ? $cur_params['dataflt'][$key] : '';
|
||||
|
||||
// Add current request params
|
||||
if (!empty($cur_params['datasrt'])) {
|
||||
$form->addHidden('datasrt', $cur_params['datasrt']);
|
||||
}
|
||||
if (!empty($cur_params['dataofs'])) {
|
||||
$form->addHidden('dataofs', $cur_params['dataofs']);
|
||||
}
|
||||
if (!empty($cur_params['dataflt'])) foreach($cur_params['dataflt'] as $c_key => $c_val) {
|
||||
if($c_val !== '' && $c_key !== $key) {
|
||||
$form->addHidden('dataflt[' . $c_key . ']', $c_val);
|
||||
}
|
||||
}
|
||||
|
||||
$form->addElement(form_makeField('text', 'dataflt[' . $key . ']', $val, ''));
|
||||
$html .= $form->getForm();
|
||||
$html .= '</th>';
|
||||
}
|
||||
$html .= '</tr>';
|
||||
$renderer->doc .= $html;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mode the mode of the renderer
|
||||
* @param Doku_Renderer $renderer the renderer
|
||||
*/
|
||||
private function startTable($mode, Doku_Renderer $renderer) {
|
||||
$renderer->table_open();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mode the mode of the renderer
|
||||
* @param Doku_Renderer $renderer the renderer
|
||||
* @param array $data the configuration of the table/search
|
||||
* @param Column[] $cols
|
||||
*/
|
||||
protected function buildColumnHeaders($mode, Doku_Renderer $renderer, $data, $cols) {
|
||||
global $ID;
|
||||
|
||||
$renderer->tablerow_open();
|
||||
|
||||
if($data['rownumbers']) {
|
||||
$renderer->tableheader_open();
|
||||
$renderer->cdata('#');
|
||||
$renderer->tableheader_close();
|
||||
}
|
||||
|
||||
foreach($data['headers'] as $num => $head) {
|
||||
$ckey = $data['cols'][$num];
|
||||
if(blank($head)) {
|
||||
if(isset($cols[$num]) && is_a($cols[$num], 'plugin\struct\meta\PageColumn')) {
|
||||
$head = $this->getLang('pagelabel');
|
||||
}else if(isset($cols[$num]) && is_a($cols[$num], 'plugin\struct\meta\Column')) {
|
||||
$head = $cols[$num]->getTranslatedLabel();
|
||||
} else {
|
||||
$head = 'column '.$num; // this should never happen
|
||||
}
|
||||
}
|
||||
|
||||
$width = '';
|
||||
if(isset($data['widths'][$num]) AND $data['widths'][$num] != '-') {
|
||||
$width = ' style="width: ' . $data['widths'][$num] . ';"';
|
||||
}
|
||||
if ($mode == 'xhmtl') {
|
||||
$renderer->doc .= '<th' . $width . '>';
|
||||
} else {
|
||||
$renderer->tableheader_open();
|
||||
}
|
||||
|
||||
// output header
|
||||
if ($mode == 'xhtml') {
|
||||
$sort = '';
|
||||
if(isset($data['sort']) && $ckey == $data['sort'][0]) {
|
||||
if($data['sort'][1] == 'ASC') {
|
||||
$sort = 'sort-down';
|
||||
$ckey = '^' . $ckey;
|
||||
} else {
|
||||
$sort = 'sort-up';
|
||||
}
|
||||
}
|
||||
|
||||
$params = $data['current_params'];
|
||||
$params['datasrt'] = $ckey;
|
||||
$link = wl($ID, $params);
|
||||
$renderer->doc .= '<a href="'.$link.'" class="'.$sort.'" title="'.$this->getLang('sort').'">'.hsc($head).'</a>';
|
||||
} else {
|
||||
$renderer->cdata($head);
|
||||
}
|
||||
|
||||
$renderer->tableheader_close();
|
||||
}
|
||||
$renderer->tablerow_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mode the mode of the renderer
|
||||
* @param Doku_Renderer $renderer the renderer
|
||||
* @param string $hash hash to identify the table and group images in gallery
|
||||
*/
|
||||
protected function startScope($mode, \Doku_Renderer $renderer, $hash) {
|
||||
if ($mode == 'xhtml') {
|
||||
$renderer->doc .= "<div class=\"structaggregation\">";
|
||||
$renderer->info['struct_table_hash'] = $hash;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if summarize was set, add sums
|
||||
*
|
||||
* @param string $mode the mode of the renderer
|
||||
* @param Doku_Renderer $renderer the renderer
|
||||
* @param array $data the configuration of the table/search
|
||||
* @param array $sums the summarized output of the numerical fields
|
||||
*/
|
||||
private function summarize($mode, \Doku_Renderer $renderer, $data, $sums) {
|
||||
if($data['summarize']) {
|
||||
$renderer->tablerow_open();
|
||||
$len = count($data['cols']);
|
||||
|
||||
if($data['rownumbers']) {
|
||||
$renderer->tablecell_open();
|
||||
$renderer->tablecell_close();
|
||||
}
|
||||
|
||||
for($i = 0; $i < $len; $i++) {
|
||||
$renderer->tablecell_open(1, $data['align'][$i]);
|
||||
if(!empty($sums[$i])) {
|
||||
$renderer->cdata('∑ ' . $sums[$i]);
|
||||
} else {
|
||||
if ($mode == 'xhtml') {
|
||||
$renderer->doc .= ' ';
|
||||
}
|
||||
}
|
||||
$renderer->tablecell_close();
|
||||
}
|
||||
$renderer->tablerow_close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mode the mode of the renderer
|
||||
* @param Doku_Renderer $renderer the renderer
|
||||
*
|
||||
*/
|
||||
private function finishTableAndScope($mode, Doku_Renderer $renderer) {
|
||||
$renderer->table_close();
|
||||
if ($mode == 'xhtml') {
|
||||
$renderer->doc .= '</div>';
|
||||
if(isset($renderer->info['struct_table_hash'])) {
|
||||
unset($renderer->info['struct_table_hash']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mode the mode of the renderer
|
||||
* @param Doku_Renderer $renderer the renderer
|
||||
* @param array $data the configuration of the table/search
|
||||
* @param $rows
|
||||
*
|
||||
*/
|
||||
private function renderRows($mode, Doku_Renderer $renderer, $data, $rows) {
|
||||
$renderer->tabletbody_open();
|
||||
foreach($rows as $rownum => $row) {
|
||||
$renderer->tablerow_open();
|
||||
|
||||
if($data['rownumbers']) {
|
||||
$renderer->tablecell_open();
|
||||
$renderer->doc .= $rownum + 1;
|
||||
$renderer->tablecell_close();
|
||||
}
|
||||
|
||||
/** @var plugin\struct\meta\Value $value */
|
||||
foreach($row as $colnum => $value) {
|
||||
$renderer->tablecell_open();
|
||||
$value->render($renderer, $mode);
|
||||
$renderer->tablecell_close();
|
||||
|
||||
// summarize
|
||||
if($data['summarize'] && is_numeric($value->getValue())) {
|
||||
if(!isset($this->sums[$colnum])) {
|
||||
$this->sums[$colnum] = 0;
|
||||
}
|
||||
$this->sums[$colnum] += $value->getValue();
|
||||
}
|
||||
}
|
||||
$renderer->tablerow_close();
|
||||
}
|
||||
$renderer->tabletbody_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data the configuration of the table/search
|
||||
* @param string $mode the mode of the renderer
|
||||
* @param Doku_Renderer $renderer the renderer
|
||||
* @param Column[] $cols
|
||||
*/
|
||||
private function nullList($data, $mode, Doku_Renderer $renderer, $cols) {
|
||||
$this->renderPreTable($mode, $renderer, $data, $cols);
|
||||
$renderer->tablerow_open();
|
||||
$renderer->tablecell_open(count($data['cols']) + $data['rownumbers'], 'center');
|
||||
$renderer->cdata($this->getLang('none'));
|
||||
$renderer->tablecell_close();
|
||||
$renderer->tablerow_close();
|
||||
$renderer->table_close();
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:et:
|
||||
|
Reference in New Issue
Block a user