mirror of
https://github.com/cosmocode/dokuwiki-plugin-struct.git
synced 2025-08-10 01:35:13 +00:00
major refactoring of the whole table aggregation
this is still completely untested
This commit is contained in:
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