107993756SAndreas Gohr<?php 207993756SAndreas Gohr 3ba766201SAndreas Gohrnamespace dokuwiki\plugin\struct\meta; 407993756SAndreas Gohr 5*7234bfb1Ssplitbrainuse dokuwiki\Extension\Event; 6*7234bfb1Ssplitbrain 7d60f71efSAndreas Gohr/** 8d60f71efSAndreas Gohr * Creates the table aggregation output 9d60f71efSAndreas Gohr * 10ba766201SAndreas Gohr * @package dokuwiki\plugin\struct\meta 11d60f71efSAndreas Gohr */ 12d90aa848SAndreas Gohrclass AggregationTable extends Aggregation 13d6d97f60SAnna Dabrowska{ 14d90aa848SAndreas Gohr /** @var array for summing up columns */ 15d90aa848SAndreas Gohr protected $sums; 1607993756SAndreas Gohr 17d90aa848SAndreas Gohr /** @var string[] the result PIDs for each row */ 18d4b5a17cSAndreas Gohr protected $resultPIDs; 190ceefd5cSAnna Dabrowska protected $resultRids; 206fd73b4bSAnna Dabrowska protected $resultRevs; 21d4b5a17cSAndreas Gohr 228ce43f5aSAnna Dabrowska public function __construct($id, $mode, \Doku_Renderer $renderer, SearchConfig $searchConfig) 23d6d97f60SAnna Dabrowska { 24d90aa848SAndreas Gohr parent::__construct($id, $mode, $renderer, $searchConfig); 25d4b5a17cSAndreas Gohr $this->resultPIDs = $this->searchConfig->getPids(); 260ceefd5cSAnna Dabrowska $this->resultRids = $this->searchConfig->getRids(); 276fd73b4bSAnna Dabrowska $this->resultRevs = $this->searchConfig->getRevs(); 2807993756SAndreas Gohr } 2907993756SAndreas Gohr 30d90aa848SAndreas Gohr /** @inheritdoc */ 31d90aa848SAndreas Gohr public function render($showNotFound = false) 32d6d97f60SAnna Dabrowska { 33b7e1d73bSAndreas Gohr 34b7e1d73bSAndreas Gohr // abort early if there are no results at all (not filtered) 35d90aa848SAndreas Gohr if (!$this->resultCount && !$this->isDynamicallyFiltered() && $showNotFound) { 36b7e1d73bSAndreas Gohr $this->renderer->cdata($this->helper->getLang('none')); 37b7e1d73bSAndreas Gohr return; 38b7e1d73bSAndreas Gohr } 39b7e1d73bSAndreas Gohr 40986ab7e6SAndreas Gohr $this->renderActiveFilters(); 41844a4f01SFrieder Schrempf 42*7234bfb1Ssplitbrain $rendercontext = ['table' => $this, 'renderer' => $this->renderer, 'format' => $this->mode, 'search' => $this->searchConfig, 'columns' => $this->columns, 'data' => $this->result]; 43844a4f01SFrieder Schrempf 44*7234bfb1Ssplitbrain $event = new Event( 45844a4f01SFrieder Schrempf 'PLUGIN_STRUCT_RENDER_AGGREGATION_TABLE', 462dbe71f8SAnna Dabrowska $rendercontext 47844a4f01SFrieder Schrempf ); 482dbe71f8SAnna Dabrowska $event->trigger([$this, 'renderTable']); 49844a4f01SFrieder Schrempf 50844a4f01SFrieder Schrempf // export handle 51844a4f01SFrieder Schrempf $this->renderExportControls(); 52844a4f01SFrieder Schrempf } 53844a4f01SFrieder Schrempf 54844a4f01SFrieder Schrempf /** 55844a4f01SFrieder Schrempf * Render the default aggregation table 56844a4f01SFrieder Schrempf */ 57844a4f01SFrieder Schrempf public function renderTable($rendercontext) 58844a4f01SFrieder Schrempf { 5907993756SAndreas Gohr $this->renderer->table_open(); 6007993756SAndreas Gohr 6107993756SAndreas Gohr // header 6207993756SAndreas Gohr $this->renderer->tablethead_open(); 63986ab7e6SAndreas Gohr $this->renderColumnHeaders(); 64986ab7e6SAndreas Gohr $this->renderDynamicFilters(); 6507993756SAndreas Gohr $this->renderer->tablethead_close(); 6607993756SAndreas Gohr 6707993756SAndreas Gohr if ($this->resultCount) { 6807993756SAndreas Gohr // actual data 69a9fd81f9SAndreas Gohr $this->renderer->tabletbody_open(); 70986ab7e6SAndreas Gohr $this->renderResult(); 71a9fd81f9SAndreas Gohr $this->renderer->tabletbody_close(); 7207993756SAndreas Gohr 73a9fd81f9SAndreas Gohr // footer (tfoot is develonly currently) 74a9fd81f9SAndreas Gohr if (method_exists($this->renderer, 'tabletfoot_open')) $this->renderer->tabletfoot_open(); 75986ab7e6SAndreas Gohr $this->renderSums(); 76986ab7e6SAndreas Gohr $this->renderPagingControls(); 77a9fd81f9SAndreas Gohr if (method_exists($this->renderer, 'tabletfoot_close')) $this->renderer->tabletfoot_close(); 7807993756SAndreas Gohr } else { 7907993756SAndreas Gohr // nothing found 80986ab7e6SAndreas Gohr $this->renderEmptyResult(); 8107993756SAndreas Gohr } 8207993756SAndreas Gohr 8307993756SAndreas Gohr // table close 8407993756SAndreas Gohr $this->renderer->table_close(); 8507993756SAndreas Gohr } 8607993756SAndreas Gohr 8707993756SAndreas Gohr /** 8807993756SAndreas Gohr * Adds additional info to document and renderer in XHTML mode 8907993756SAndreas Gohr * 9007993756SAndreas Gohr * @see finishScope() 9107993756SAndreas Gohr */ 92af0ce8d2SAndreas Gohr public function startScope() 93d6d97f60SAnna Dabrowska { 9407993756SAndreas Gohr // unique identifier for this aggregation 9507993756SAndreas Gohr $this->renderer->info['struct_table_hash'] = md5(var_export($this->data, true)); 9609dd691aSAndreas Gohr 97af0ce8d2SAndreas Gohr parent::startScope(); 9807993756SAndreas Gohr } 9907993756SAndreas Gohr 10007993756SAndreas Gohr /** 10107993756SAndreas Gohr * Closes the table and anything opened in startScope() 10207993756SAndreas Gohr * 10307993756SAndreas Gohr * @see startScope() 10407993756SAndreas Gohr */ 105af0ce8d2SAndreas Gohr public function finishScope() 106d6d97f60SAnna Dabrowska { 10707993756SAndreas Gohr // remove identifier from renderer again 10807993756SAndreas Gohr if (isset($this->renderer->info['struct_table_hash'])) { 10907993756SAndreas Gohr unset($this->renderer->info['struct_table_hash']); 11007993756SAndreas Gohr } 11109dd691aSAndreas Gohr 112af0ce8d2SAndreas Gohr parent::finishScope(); 11307993756SAndreas Gohr } 11407993756SAndreas Gohr 11507993756SAndreas Gohr /** 11607993756SAndreas Gohr * Displays info about the currently applied filters 11707993756SAndreas Gohr */ 118d6d97f60SAnna Dabrowska protected function renderActiveFilters() 119d6d97f60SAnna Dabrowska { 12007993756SAndreas Gohr if ($this->mode != 'xhtml') return; 12107993756SAndreas Gohr $dynamic = $this->searchConfig->getDynamicParameters(); 12207993756SAndreas Gohr $filters = $dynamic->getFilters(); 12307993756SAndreas Gohr if (!$filters) return; 12407993756SAndreas Gohr 125*7234bfb1Ssplitbrain $fltrs = []; 12607993756SAndreas Gohr foreach ($filters as $column => $filter) { 127*7234bfb1Ssplitbrain [$comp, $value] = $filter; 12804ec4785SAnna Dabrowska 12904ec4785SAnna Dabrowska // display the filters in a human readable format 13004ec4785SAnna Dabrowska foreach ($this->columns as $col) { 13104ec4785SAnna Dabrowska if ($column === $col->getFullQualifiedLabel()) { 13204ec4785SAnna Dabrowska $column = $col->getTranslatedLabel(); 13304ec4785SAnna Dabrowska } 13404ec4785SAnna Dabrowska } 1351f075418SAnna Dabrowska $fltrs[] = sprintf('"%s" %s "%s"', $column, $this->helper->getLang("comparator $comp"), $value); 13607993756SAndreas Gohr } 13707993756SAndreas Gohr 13807993756SAndreas Gohr $this->renderer->doc .= '<div class="filter">'; 13917a3a578SAndreas Gohr $this->renderer->doc .= '<h4>' . 14017a3a578SAndreas Gohr sprintf( 14117a3a578SAndreas Gohr $this->helper->getLang('tablefilteredby'), 14217a3a578SAndreas Gohr hsc(implode(' & ', $fltrs)) 14317a3a578SAndreas Gohr ) . 14417a3a578SAndreas Gohr '</h4>'; 14507993756SAndreas Gohr $this->renderer->doc .= '<div class="resetfilter">'; 14607993756SAndreas Gohr $this->renderer->internallink($this->id, $this->helper->getLang('tableresetfilter')); 14707993756SAndreas Gohr $this->renderer->doc .= '</div>'; 14807993756SAndreas Gohr $this->renderer->doc .= '</div>'; 14907993756SAndreas Gohr } 15007993756SAndreas Gohr 15107993756SAndreas Gohr /** 15207993756SAndreas Gohr * Shows the column headers with links to sort by column 15307993756SAndreas Gohr */ 154d6d97f60SAnna Dabrowska protected function renderColumnHeaders() 155d6d97f60SAnna Dabrowska { 15607993756SAndreas Gohr $this->renderer->tablerow_open(); 15707993756SAndreas Gohr 15807993756SAndreas Gohr // additional column for row numbers 15934ea6e10SAnna Dabrowska if (!empty($this->data['rownumbers'])) { 16007993756SAndreas Gohr $this->renderer->tableheader_open(); 16107993756SAndreas Gohr $this->renderer->cdata('#'); 16207993756SAndreas Gohr $this->renderer->tableheader_close(); 16307993756SAndreas Gohr } 16407993756SAndreas Gohr 16507993756SAndreas Gohr // show all headers 1668c4ee9beSAndreas Gohr foreach ($this->columns as $num => $column) { 1678c4ee9beSAndreas Gohr $header = ''; 1688c4ee9beSAndreas Gohr if (isset($this->data['headers'][$num])) { 1698c4ee9beSAndreas Gohr $header = $this->data['headers'][$num]; 1708c4ee9beSAndreas Gohr } 17107993756SAndreas Gohr 17207993756SAndreas Gohr // use field label if no header was set 17307993756SAndreas Gohr if (blank($header)) { 17401f8b845SAndreas Gohr if (is_a($column, 'dokuwiki\plugin\struct\meta\Column')) { 17507993756SAndreas Gohr $header = $column->getTranslatedLabel(); 17607993756SAndreas Gohr } else { 17707993756SAndreas Gohr $header = 'column ' . $num; // this should never happen 17807993756SAndreas Gohr } 17907993756SAndreas Gohr } 18007993756SAndreas Gohr 18107993756SAndreas Gohr // simple mode first 18207993756SAndreas Gohr if ($this->mode != 'xhtml') { 18307993756SAndreas Gohr $this->renderer->tableheader_open(); 18407993756SAndreas Gohr $this->renderer->cdata($header); 18507993756SAndreas Gohr $this->renderer->tableheader_close(); 18607993756SAndreas Gohr continue; 18707993756SAndreas Gohr } 18807993756SAndreas Gohr 18907993756SAndreas Gohr // still here? create custom header for more flexibility 19007993756SAndreas Gohr 1919113d04aSAndreas Gohr // width setting, widths are prevalidated, no escape needed 19207993756SAndreas Gohr $width = ''; 1939113d04aSAndreas Gohr if (isset($this->data['widths'][$num]) && $this->data['widths'][$num] != '-') { 1949113d04aSAndreas Gohr $width = ' style="min-width: ' . $this->data['widths'][$num] . ';' . 1959113d04aSAndreas Gohr 'max-width: ' . $this->data['widths'][$num] . ';"'; 19607993756SAndreas Gohr } 19707993756SAndreas Gohr 198d4b5a17cSAndreas Gohr // prepare data attribute for inline edits 199d6d97f60SAnna Dabrowska if ( 200d6d97f60SAnna Dabrowska !is_a($column, '\dokuwiki\plugin\struct\meta\PageColumn') && 201d4b5a17cSAndreas Gohr !is_a($column, '\dokuwiki\plugin\struct\meta\RevisionColumn') 202d4b5a17cSAndreas Gohr ) { 203d4b5a17cSAndreas Gohr $data = 'data-field="' . hsc($column->getFullQualifiedLabel()) . '"'; 204d4b5a17cSAndreas Gohr } else { 205d4b5a17cSAndreas Gohr $data = ''; 206d4b5a17cSAndreas Gohr } 207d4b5a17cSAndreas Gohr 20807993756SAndreas Gohr // sort indicator and link 20907993756SAndreas Gohr $sortclass = ''; 21007993756SAndreas Gohr $sorts = $this->searchConfig->getSorts(); 21107993756SAndreas Gohr $dynamic = $this->searchConfig->getDynamicParameters(); 212aa124708SAndreas Gohr $dynamic->setSort($column, true); 21307993756SAndreas Gohr if (isset($sorts[$column->getFullQualifiedLabel()])) { 214*7234bfb1Ssplitbrain [, $currentSort] = $sorts[$column->getFullQualifiedLabel()]; 215aa124708SAndreas Gohr if ($currentSort) { 21607993756SAndreas Gohr $sortclass = 'sort-down'; 21707993756SAndreas Gohr $dynamic->setSort($column, false); 21807993756SAndreas Gohr } else { 21907993756SAndreas Gohr $sortclass = 'sort-up'; 22007993756SAndreas Gohr } 22107993756SAndreas Gohr } 22207993756SAndreas Gohr $link = wl($this->id, $dynamic->getURLParameters()); 22307993756SAndreas Gohr 22407993756SAndreas Gohr // output XHTML header 225d4b5a17cSAndreas Gohr $this->renderer->doc .= "<th $width $data>"; 22617a3a578SAndreas Gohr $this->renderer->doc .= '<a href="' . $link . '" class="' . $sortclass . '" ' . 22717a3a578SAndreas Gohr 'title="' . $this->helper->getLang('sort') . '">' . hsc($header) . '</a>'; 22807993756SAndreas Gohr $this->renderer->doc .= '</th>'; 22907993756SAndreas Gohr } 23007993756SAndreas Gohr 23107993756SAndreas Gohr $this->renderer->tablerow_close(); 23207993756SAndreas Gohr } 23307993756SAndreas Gohr 23407993756SAndreas Gohr /** 235b7e1d73bSAndreas Gohr * Is the result set currently dynamically filtered? 236b7e1d73bSAndreas Gohr * @return bool 237b7e1d73bSAndreas Gohr */ 238d6d97f60SAnna Dabrowska protected function isDynamicallyFiltered() 239d6d97f60SAnna Dabrowska { 240b7e1d73bSAndreas Gohr if ($this->mode != 'xhtml') return false; 241b7e1d73bSAndreas Gohr if (!$this->data['dynfilters']) return false; 242b7e1d73bSAndreas Gohr 243b7e1d73bSAndreas Gohr $dynamic = $this->searchConfig->getDynamicParameters(); 244b7e1d73bSAndreas Gohr return (bool)$dynamic->getFilters(); 245b7e1d73bSAndreas Gohr } 246b7e1d73bSAndreas Gohr 247b7e1d73bSAndreas Gohr /** 24807993756SAndreas Gohr * Add input fields for dynamic filtering 24907993756SAndreas Gohr */ 250d6d97f60SAnna Dabrowska protected function renderDynamicFilters() 251d6d97f60SAnna Dabrowska { 25207993756SAndreas Gohr if ($this->mode != 'xhtml') return; 2531ca21e17SAnna Dabrowska if (empty($this->data['dynfilters'])) return; 2541bc467a4SMichael Grosse if (is_a($this->renderer, 'renderer_plugin_dw2pdf')) { 255e6ae02ecSMichael Grosse return; 256e6ae02ecSMichael Grosse } 2571bc467a4SMichael Grosse global $conf; 25807993756SAndreas Gohr 25907993756SAndreas Gohr $this->renderer->doc .= '<tr class="dataflt">'; 26007993756SAndreas Gohr 26107993756SAndreas Gohr // add extra column for row numbers 26207993756SAndreas Gohr if ($this->data['rownumbers']) { 26307993756SAndreas Gohr $this->renderer->doc .= '<th></th>'; 26407993756SAndreas Gohr } 26507993756SAndreas Gohr 26607993756SAndreas Gohr // each column gets a form 26707993756SAndreas Gohr foreach ($this->columns as $column) { 26807993756SAndreas Gohr $this->renderer->doc .= '<th>'; 26917a3a578SAndreas Gohr 27017a3a578SAndreas Gohr // BEGIN FORM 271*7234bfb1Ssplitbrain $form = new \Doku_Form(['method' => 'GET', 'action' => wl($this->id)]); 27276195677SAndreas Gohr unset($form->_hidden['sectok']); // we don't need it here 27376195677SAndreas Gohr if (!$conf['userewrite']) $form->addHidden('id', $this->id); 27407993756SAndreas Gohr 27507993756SAndreas Gohr // current value 27607993756SAndreas Gohr $dynamic = $this->searchConfig->getDynamicParameters(); 27707993756SAndreas Gohr $filters = $dynamic->getFilters(); 27807993756SAndreas Gohr if (isset($filters[$column->getFullQualifiedLabel()])) { 279*7234bfb1Ssplitbrain [, $current] = $filters[$column->getFullQualifiedLabel()]; 28007993756SAndreas Gohr $dynamic->removeFilter($column); 28107993756SAndreas Gohr } else { 28207993756SAndreas Gohr $current = ''; 28307993756SAndreas Gohr } 28407993756SAndreas Gohr 28507993756SAndreas Gohr // Add current request params 28607993756SAndreas Gohr $params = $dynamic->getURLParameters(); 28707993756SAndreas Gohr foreach ($params as $key => $val) { 28807993756SAndreas Gohr $form->addHidden($key, $val); 28907993756SAndreas Gohr } 29007993756SAndreas Gohr 29107993756SAndreas Gohr // add input field 292db9b8745SAndreas Gohr $key = $column->getFullQualifiedLabel() . $column->getType()->getDefaultComparator(); 29317a3a578SAndreas Gohr $form->addElement( 29417a3a578SAndreas Gohr form_makeField('text', SearchConfigParameters::$PARAM_FILTER . '[' . $key . ']', $current, '') 29517a3a578SAndreas Gohr ); 29607993756SAndreas Gohr $this->renderer->doc .= $form->getForm(); 29717a3a578SAndreas Gohr // END FORM 29817a3a578SAndreas Gohr 29907993756SAndreas Gohr $this->renderer->doc .= '</th>'; 30007993756SAndreas Gohr } 30107993756SAndreas Gohr $this->renderer->doc .= '</tr>'; 30207993756SAndreas Gohr } 30307993756SAndreas Gohr 30407993756SAndreas Gohr /** 30507993756SAndreas Gohr * Display the actual table data 30607993756SAndreas Gohr */ 307d6d97f60SAnna Dabrowska protected function renderResult() 308d6d97f60SAnna Dabrowska { 30907993756SAndreas Gohr foreach ($this->result as $rownum => $row) { 310*7234bfb1Ssplitbrain $data = ['id' => $this->id, 'mode' => $this->mode, 'renderer' => $this->renderer, 'searchConfig' => $this->searchConfig, 'data' => $this->data, 'rownum' => &$rownum, 'row' => &$row]; 311*7234bfb1Ssplitbrain $evt = new Event('PLUGIN_STRUCT_AGGREGATIONTABLE_RENDERRESULTROW', $data); 31247eb8cceSSzymon Olewniczak if ($evt->advise_before()) { 313f107f479SAndreas Gohr $this->renderResultRow($rownum, $row); 314f107f479SAndreas Gohr } 31547eb8cceSSzymon Olewniczak $evt->advise_after(); 31647eb8cceSSzymon Olewniczak } 317f107f479SAndreas Gohr } 318f107f479SAndreas Gohr 319f107f479SAndreas Gohr /** 320f107f479SAndreas Gohr * Render a single result row 321f107f479SAndreas Gohr * 322f107f479SAndreas Gohr * @param int $rownum 323f107f479SAndreas Gohr * @param array $row 324f107f479SAndreas Gohr */ 325d6d97f60SAnna Dabrowska protected function renderResultRow($rownum, $row) 326d6d97f60SAnna Dabrowska { 32707993756SAndreas Gohr $this->renderer->tablerow_open(); 32807993756SAndreas Gohr 329d4b5a17cSAndreas Gohr // add data attribute for inline edit 330d4b5a17cSAndreas Gohr if ($this->mode == 'xhtml') { 331d4b5a17cSAndreas Gohr $pid = $this->resultPIDs[$rownum]; 3320ceefd5cSAnna Dabrowska $rid = $this->resultRids[$rownum]; 3336fd73b4bSAnna Dabrowska $rev = $this->resultRevs[$rownum]; 334d4b5a17cSAndreas Gohr $this->renderer->doc = substr(rtrim($this->renderer->doc), 0, -1); // remove closing '>' 3356fd73b4bSAnna Dabrowska $this->renderer->doc .= ' data-pid="' . hsc($pid) . '" data-rev="' . $rev . '" data-rid="' . $rid . '">'; 336d4b5a17cSAndreas Gohr } 337d4b5a17cSAndreas Gohr 33807993756SAndreas Gohr // row number column 33934ea6e10SAnna Dabrowska if (!empty($this->data['rownumbers'])) { 34007993756SAndreas Gohr $this->renderer->tablecell_open(); 341fdf37115SAndreas Gohr $this->renderer->cdata($rownum + $this->searchConfig->getOffset() + 1); 34207993756SAndreas Gohr $this->renderer->tablecell_close(); 34307993756SAndreas Gohr } 34407993756SAndreas Gohr 34507993756SAndreas Gohr /** @var Value $value */ 34607993756SAndreas Gohr foreach ($row as $colnum => $value) { 347*7234bfb1Ssplitbrain $align = $this->data['align'][$colnum] ?? null; 34834ea6e10SAnna Dabrowska $this->renderer->tablecell_open(1, $align); 34907993756SAndreas Gohr $value->render($this->renderer, $this->mode); 35007993756SAndreas Gohr $this->renderer->tablecell_close(); 35107993756SAndreas Gohr 35207993756SAndreas Gohr // summarize 3531ca21e17SAnna Dabrowska if (!empty($this->data['summarize']) && is_numeric($value->getValue())) { 35407993756SAndreas Gohr if (!isset($this->sums[$colnum])) { 35507993756SAndreas Gohr $this->sums[$colnum] = 0; 35607993756SAndreas Gohr } 35707993756SAndreas Gohr $this->sums[$colnum] += $value->getValue(); 35807993756SAndreas Gohr } 35907993756SAndreas Gohr } 36007993756SAndreas Gohr $this->renderer->tablerow_close(); 36107993756SAndreas Gohr } 36207993756SAndreas Gohr 36307993756SAndreas Gohr /** 36407993756SAndreas Gohr * Renders an information row for when no results were found 36507993756SAndreas Gohr */ 366d6d97f60SAnna Dabrowska protected function renderEmptyResult() 367d6d97f60SAnna Dabrowska { 36807993756SAndreas Gohr $this->renderer->tablerow_open(); 36970cf6339SAndreas Gohr $this->renderer->tablecell_open(count($this->columns) + $this->data['rownumbers'], 'center'); 37007993756SAndreas Gohr $this->renderer->cdata($this->helper->getLang('none')); 37107993756SAndreas Gohr $this->renderer->tablecell_close(); 37207993756SAndreas Gohr $this->renderer->tablerow_close(); 37307993756SAndreas Gohr } 37407993756SAndreas Gohr 37507993756SAndreas Gohr /** 37607993756SAndreas Gohr * Add sums if wanted 37707993756SAndreas Gohr */ 378d6d97f60SAnna Dabrowska protected function renderSums() 379d6d97f60SAnna Dabrowska { 380d18090e8SAndreas Gohr if (empty($this->data['summarize'])) return; 38107993756SAndreas Gohr 382a0bf8bb2SAndreas Gohr $this->renderer->info['struct_table_meta'] = true; 3838925ba29SAndreas Gohr if ($this->mode == 'xhtml') { 3848925ba29SAndreas Gohr /** @noinspection PhpMethodParametersCountMismatchInspection */ 3858925ba29SAndreas Gohr $this->renderer->tablerow_open('summarize'); 3868925ba29SAndreas Gohr } else { 38707993756SAndreas Gohr $this->renderer->tablerow_open(); 3888925ba29SAndreas Gohr } 38907993756SAndreas Gohr 39007993756SAndreas Gohr if ($this->data['rownumbers']) { 3918925ba29SAndreas Gohr $this->renderer->tableheader_open(); 3928925ba29SAndreas Gohr $this->renderer->tableheader_close(); 39307993756SAndreas Gohr } 39407993756SAndreas Gohr 395aee4116bSAndreas Gohr $len = count($this->columns); 39607993756SAndreas Gohr for ($i = 0; $i < $len; $i++) { 3978925ba29SAndreas Gohr $this->renderer->tableheader_open(1, $this->data['align'][$i]); 398aee4116bSAndreas Gohr if (!empty($this->sums[$i])) { 3999b97e610SAndreas Gohr $this->renderer->cdata('∑ '); 4009b97e610SAndreas Gohr $this->columns[$i]->getType()->renderValue($this->sums[$i], $this->renderer, $this->mode); 401*7234bfb1Ssplitbrain } elseif ($this->mode == 'xhtml') { 40207993756SAndreas Gohr $this->renderer->doc .= ' '; 40307993756SAndreas Gohr } 4048925ba29SAndreas Gohr $this->renderer->tableheader_close(); 40507993756SAndreas Gohr } 40607993756SAndreas Gohr $this->renderer->tablerow_close(); 407a0bf8bb2SAndreas Gohr $this->renderer->info['struct_table_meta'] = false; 40807993756SAndreas Gohr } 40907993756SAndreas Gohr 41007993756SAndreas Gohr /** 411986ab7e6SAndreas Gohr * Adds paging controls to the table 41207993756SAndreas Gohr */ 413d6d97f60SAnna Dabrowska protected function renderPagingControls() 414d6d97f60SAnna Dabrowska { 415a0bf8bb2SAndreas Gohr if ($this->mode != 'xhtml') return; 41607993756SAndreas Gohr 417fdf37115SAndreas Gohr $limit = $this->searchConfig->getLimit(); 418fdf37115SAndreas Gohr if (!$limit) return; 419fdf37115SAndreas Gohr $offset = $this->searchConfig->getOffset(); 420fdf37115SAndreas Gohr 421a0bf8bb2SAndreas Gohr $this->renderer->info['struct_table_meta'] = true; 42207993756SAndreas Gohr $this->renderer->tablerow_open(); 4234bc1074dSMichael Grosse $this->renderer->tableheader_open((count($this->columns) + ($this->data['rownumbers'] ? 1 : 0))); 424fdf37115SAndreas Gohr 42507993756SAndreas Gohr 42607993756SAndreas Gohr // prev link 42707993756SAndreas Gohr if ($offset) { 428fdf37115SAndreas Gohr $prev = $offset - $limit; 42907993756SAndreas Gohr if ($prev < 0) { 43007993756SAndreas Gohr $prev = 0; 43107993756SAndreas Gohr } 43207993756SAndreas Gohr 43307993756SAndreas Gohr $dynamic = $this->searchConfig->getDynamicParameters(); 43407993756SAndreas Gohr $dynamic->setOffset($prev); 43507993756SAndreas Gohr $link = wl($this->id, $dynamic->getURLParameters()); 43607993756SAndreas Gohr $this->renderer->doc .= '<a href="' . $link . '" class="prev">' . $this->helper->getLang('prev') . '</a>'; 43707993756SAndreas Gohr } 43807993756SAndreas Gohr 43907993756SAndreas Gohr // next link 440fdf37115SAndreas Gohr if ($this->resultCount > $offset + $limit) { 441fdf37115SAndreas Gohr $next = $offset + $limit; 44207993756SAndreas Gohr $dynamic = $this->searchConfig->getDynamicParameters(); 44307993756SAndreas Gohr $dynamic->setOffset($next); 44407993756SAndreas Gohr $link = wl($this->id, $dynamic->getURLParameters()); 44507993756SAndreas Gohr $this->renderer->doc .= '<a href="' . $link . '" class="next">' . $this->helper->getLang('next') . '</a>'; 44607993756SAndreas Gohr } 44707993756SAndreas Gohr 44807993756SAndreas Gohr $this->renderer->tableheader_close(); 44907993756SAndreas Gohr $this->renderer->tablerow_close(); 450a0bf8bb2SAndreas Gohr $this->renderer->info['struct_table_meta'] = true; 45107993756SAndreas Gohr } 45209dd691aSAndreas Gohr 45309dd691aSAndreas Gohr /** 45409dd691aSAndreas Gohr * Adds CSV export controls 45509dd691aSAndreas Gohr */ 456d6d97f60SAnna Dabrowska protected function renderExportControls() 457d6d97f60SAnna Dabrowska { 45809dd691aSAndreas Gohr if ($this->mode != 'xhtml') return; 4597b240ca8SAndreas Gohr if (empty($this->data['csv'])) return; 46009dd691aSAndreas Gohr if (!$this->resultCount) return; 46109dd691aSAndreas Gohr 462c8ccdaf8SAndreas Gohr $dynamic = $this->searchConfig->getDynamicParameters(); 463c8ccdaf8SAndreas Gohr $params = $dynamic->getURLParameters(); 464c8ccdaf8SAndreas Gohr $params['hash'] = $this->renderer->info['struct_table_hash']; 465c8ccdaf8SAndreas Gohr 46609dd691aSAndreas Gohr // FIXME apply dynamic filters 467eafc109fSAndreas Gohr $link = exportlink($this->id, 'struct_csv', $params); 46809dd691aSAndreas Gohr 46917a3a578SAndreas Gohr $this->renderer->doc .= '<a href="' . $link . '" class="export mediafile mf_csv">' . 47017a3a578SAndreas Gohr $this->helper->getLang('csvexport') . '</a>'; 47109dd691aSAndreas Gohr } 47207993756SAndreas Gohr} 473