xref: /plugin/struct/meta/AggregationTable.php (revision 47eb8ccecb24681a30caba09b6e9c81ea4b89b48)
107993756SAndreas Gohr<?php
207993756SAndreas Gohr
3ba766201SAndreas Gohrnamespace dokuwiki\plugin\struct\meta;
407993756SAndreas Gohr
5d60f71efSAndreas Gohr/**
6d60f71efSAndreas Gohr * Creates the table aggregation output
7d60f71efSAndreas Gohr *
8ba766201SAndreas Gohr * @package dokuwiki\plugin\struct\meta
9d60f71efSAndreas Gohr */
1007993756SAndreas Gohrclass AggregationTable {
1107993756SAndreas Gohr
1207993756SAndreas Gohr    /**
1307993756SAndreas Gohr     * @var string the page id of the page this is rendered to
1407993756SAndreas Gohr     */
1507993756SAndreas Gohr    protected $id;
1607993756SAndreas Gohr    /**
1707993756SAndreas Gohr     * @var string the Type of renderer used
1807993756SAndreas Gohr     */
1907993756SAndreas Gohr    protected $mode;
2007993756SAndreas Gohr    /**
2107993756SAndreas Gohr     * @var \Doku_Renderer the DokuWiki renderer used to create the output
2207993756SAndreas Gohr     */
2307993756SAndreas Gohr    protected $renderer;
2407993756SAndreas Gohr    /**
2507993756SAndreas Gohr     * @var SearchConfig the configured search - gives access to columns etc.
2607993756SAndreas Gohr     */
2707993756SAndreas Gohr    protected $searchConfig;
2807993756SAndreas Gohr
2907993756SAndreas Gohr    /**
3007993756SAndreas Gohr     * @var Column[] the list of columns to be displayed
3107993756SAndreas Gohr     */
3207993756SAndreas Gohr    protected $columns;
3307993756SAndreas Gohr
3407993756SAndreas Gohr    /**
3507993756SAndreas Gohr     * @var  Value[][] the search result
3607993756SAndreas Gohr     */
3707993756SAndreas Gohr    protected $result;
3807993756SAndreas Gohr
3907993756SAndreas Gohr    /**
4007993756SAndreas Gohr     * @var int number of all results
4107993756SAndreas Gohr     */
4207993756SAndreas Gohr    protected $resultCount;
4307993756SAndreas Gohr
4407993756SAndreas Gohr    /**
45d4b5a17cSAndreas Gohr     * @var string[] the result PIDs for each row
46d4b5a17cSAndreas Gohr     */
47d4b5a17cSAndreas Gohr    protected $resultPIDs;
48d4b5a17cSAndreas Gohr
49d4b5a17cSAndreas Gohr    /**
5007993756SAndreas Gohr     * @var array for summing up columns
5107993756SAndreas Gohr     */
5207993756SAndreas Gohr    protected $sums;
5307993756SAndreas Gohr
5407993756SAndreas Gohr    /**
556b5e52fdSAndreas Gohr     * @var bool skip full table when no results found
566b5e52fdSAndreas Gohr     */
576b5e52fdSAndreas Gohr    protected $simplenone = true;
586b5e52fdSAndreas Gohr
596b5e52fdSAndreas Gohr    /**
6007993756SAndreas Gohr     * @todo we might be able to get rid of this helper and move this to SearchConfig
6107993756SAndreas Gohr     * @var \helper_plugin_struct_config
6207993756SAndreas Gohr     */
6307993756SAndreas Gohr    protected $helper;
6407993756SAndreas Gohr
6507993756SAndreas Gohr    /**
6607993756SAndreas Gohr     * Initialize the Aggregation renderer and executes the search
6707993756SAndreas Gohr     *
6807993756SAndreas Gohr     * You need to call @see render() on the resulting object.
6907993756SAndreas Gohr     *
7007993756SAndreas Gohr     * @param string $id
7107993756SAndreas Gohr     * @param string $mode
7207993756SAndreas Gohr     * @param \Doku_Renderer $renderer
7307993756SAndreas Gohr     * @param SearchConfig $searchConfig
7407993756SAndreas Gohr     */
7507993756SAndreas Gohr    public function __construct($id, $mode, \Doku_Renderer $renderer, SearchConfig $searchConfig) {
7607993756SAndreas Gohr        $this->id = $id;
7707993756SAndreas Gohr        $this->mode = $mode;
7807993756SAndreas Gohr        $this->renderer = $renderer;
7907993756SAndreas Gohr        $this->searchConfig = $searchConfig;
8007993756SAndreas Gohr        $this->data = $searchConfig->getConf();
8107993756SAndreas Gohr        $this->columns = $searchConfig->getColumns();
8207993756SAndreas Gohr
8307993756SAndreas Gohr        $this->result = $this->searchConfig->execute();
8407993756SAndreas Gohr        $this->resultCount = $this->searchConfig->getCount();
85d4b5a17cSAndreas Gohr        $this->resultPIDs = $this->searchConfig->getPids();
8607993756SAndreas Gohr        $this->helper = plugin_load('helper', 'struct_config');
8707993756SAndreas Gohr    }
8807993756SAndreas Gohr
8907993756SAndreas Gohr    /**
9007993756SAndreas Gohr     * Create the table on the renderer
9107993756SAndreas Gohr     */
9207993756SAndreas Gohr    public function render() {
93b7e1d73bSAndreas Gohr
94b7e1d73bSAndreas Gohr        // abort early if there are no results at all (not filtered)
956b5e52fdSAndreas Gohr        if(!$this->resultCount && !$this->isDynamicallyFiltered() && $this->simplenone) {
96b7e1d73bSAndreas Gohr            $this->startScope();
97b7e1d73bSAndreas Gohr            $this->renderer->cdata($this->helper->getLang('none'));
98b7e1d73bSAndreas Gohr            $this->finishScope();
99b7e1d73bSAndreas Gohr            return;
100b7e1d73bSAndreas Gohr        }
101b7e1d73bSAndreas Gohr
10207993756SAndreas Gohr        // table open
10307993756SAndreas Gohr        $this->startScope();
104986ab7e6SAndreas Gohr        $this->renderActiveFilters();
10507993756SAndreas Gohr        $this->renderer->table_open();
10607993756SAndreas Gohr
10707993756SAndreas Gohr        // header
10807993756SAndreas Gohr        $this->renderer->tablethead_open();
109986ab7e6SAndreas Gohr        $this->renderColumnHeaders();
110986ab7e6SAndreas Gohr        $this->renderDynamicFilters();
11107993756SAndreas Gohr        $this->renderer->tablethead_close();
11207993756SAndreas Gohr
11307993756SAndreas Gohr        if($this->resultCount) {
11407993756SAndreas Gohr            // actual data
115a9fd81f9SAndreas Gohr            $this->renderer->tabletbody_open();
116986ab7e6SAndreas Gohr            $this->renderResult();
117a9fd81f9SAndreas Gohr            $this->renderer->tabletbody_close();
11807993756SAndreas Gohr
119a9fd81f9SAndreas Gohr            // footer (tfoot is develonly currently)
120a9fd81f9SAndreas Gohr            if(method_exists($this->renderer, 'tabletfoot_open')) $this->renderer->tabletfoot_open();
121986ab7e6SAndreas Gohr            $this->renderSums();
122986ab7e6SAndreas Gohr            $this->renderPagingControls();
123a9fd81f9SAndreas Gohr            if(method_exists($this->renderer, 'tabletfoot_close')) $this->renderer->tabletfoot_close();
12407993756SAndreas Gohr        } else {
12507993756SAndreas Gohr            // nothing found
126986ab7e6SAndreas Gohr            $this->renderEmptyResult();
12707993756SAndreas Gohr        }
12807993756SAndreas Gohr
12907993756SAndreas Gohr        // table close
13007993756SAndreas Gohr        $this->renderer->table_close();
13109dd691aSAndreas Gohr
13209dd691aSAndreas Gohr        // export handle
13309dd691aSAndreas Gohr        $this->renderExportControls();
13407993756SAndreas Gohr        $this->finishScope();
13507993756SAndreas Gohr    }
13607993756SAndreas Gohr
13707993756SAndreas Gohr    /**
13807993756SAndreas Gohr     * Adds additional info to document and renderer in XHTML mode
13907993756SAndreas Gohr     *
14007993756SAndreas Gohr     * @see finishScope()
14107993756SAndreas Gohr     */
14207993756SAndreas Gohr    protected function startScope() {
14307993756SAndreas Gohr        // unique identifier for this aggregation
14407993756SAndreas Gohr        $this->renderer->info['struct_table_hash'] = md5(var_export($this->data, true));
14509dd691aSAndreas Gohr
14609dd691aSAndreas Gohr        // wrapping div
14709dd691aSAndreas Gohr        if($this->mode != 'xhtml') return;
14809dd691aSAndreas Gohr        $this->renderer->doc .= "<div class=\"structaggregation\">";
14907993756SAndreas Gohr    }
15007993756SAndreas Gohr
15107993756SAndreas Gohr    /**
15207993756SAndreas Gohr     * Closes the table and anything opened in startScope()
15307993756SAndreas Gohr     *
15407993756SAndreas Gohr     * @see startScope()
15507993756SAndreas Gohr     */
15607993756SAndreas Gohr    protected function finishScope() {
15707993756SAndreas Gohr        // remove identifier from renderer again
15807993756SAndreas Gohr        if(isset($this->renderer->info['struct_table_hash'])) {
15907993756SAndreas Gohr            unset($this->renderer->info['struct_table_hash']);
16007993756SAndreas Gohr        }
16109dd691aSAndreas Gohr
16209dd691aSAndreas Gohr        // wrapping div
16309dd691aSAndreas Gohr        if($this->mode != 'xhtml') return;
16409dd691aSAndreas Gohr        $this->renderer->doc .= '</div>';
16507993756SAndreas Gohr    }
16607993756SAndreas Gohr
16707993756SAndreas Gohr    /**
16807993756SAndreas Gohr     * Displays info about the currently applied filters
16907993756SAndreas Gohr     */
170986ab7e6SAndreas Gohr    protected function renderActiveFilters() {
17107993756SAndreas Gohr        if($this->mode != 'xhtml') return;
17207993756SAndreas Gohr        $dynamic = $this->searchConfig->getDynamicParameters();
17307993756SAndreas Gohr        $filters = $dynamic->getFilters();
17407993756SAndreas Gohr        if(!$filters) return;
17507993756SAndreas Gohr
17607993756SAndreas Gohr        $fltrs = array();
17707993756SAndreas Gohr        foreach($filters as $column => $filter) {
17807993756SAndreas Gohr            list($comp, $value) = $filter;
17904ec4785SAnna Dabrowska
18004ec4785SAnna Dabrowska            // display the filters in a human readable format
18104ec4785SAnna Dabrowska            foreach ($this->columns as $col) {
18204ec4785SAnna Dabrowska                if ($column === $col->getFullQualifiedLabel()) {
18304ec4785SAnna Dabrowska                    $column = $col->getTranslatedLabel();
18404ec4785SAnna Dabrowska                }
18504ec4785SAnna Dabrowska            }
1861f075418SAnna Dabrowska            $fltrs[] = sprintf('"%s" %s "%s"', $column, $this->helper->getLang("comparator $comp"), $value);
18707993756SAndreas Gohr        }
18807993756SAndreas Gohr
18907993756SAndreas Gohr        $this->renderer->doc .= '<div class="filter">';
19007993756SAndreas Gohr        $this->renderer->doc .= '<h4>' . sprintf($this->helper->getLang('tablefilteredby'), hsc(implode(' & ', $fltrs))) . '</h4>';
19107993756SAndreas Gohr        $this->renderer->doc .= '<div class="resetfilter">';
19207993756SAndreas Gohr        $this->renderer->internallink($this->id, $this->helper->getLang('tableresetfilter'));
19307993756SAndreas Gohr        $this->renderer->doc .= '</div>';
19407993756SAndreas Gohr        $this->renderer->doc .= '</div>';
19507993756SAndreas Gohr    }
19607993756SAndreas Gohr
19707993756SAndreas Gohr    /**
19807993756SAndreas Gohr     * Shows the column headers with links to sort by column
19907993756SAndreas Gohr     */
200986ab7e6SAndreas Gohr    protected function renderColumnHeaders() {
20107993756SAndreas Gohr        $this->renderer->tablerow_open();
20207993756SAndreas Gohr
20307993756SAndreas Gohr        // additional column for row numbers
20407993756SAndreas Gohr        if($this->data['rownumbers']) {
20507993756SAndreas Gohr            $this->renderer->tableheader_open();
20607993756SAndreas Gohr            $this->renderer->cdata('#');
20707993756SAndreas Gohr            $this->renderer->tableheader_close();
20807993756SAndreas Gohr        }
20907993756SAndreas Gohr
21007993756SAndreas Gohr        // show all headers
2118c4ee9beSAndreas Gohr        foreach($this->columns as $num => $column) {
2128c4ee9beSAndreas Gohr            $header = '';
2138c4ee9beSAndreas Gohr            if(isset($this->data['headers'][$num])) {
2148c4ee9beSAndreas Gohr                $header = $this->data['headers'][$num];
2158c4ee9beSAndreas Gohr            }
21607993756SAndreas Gohr
21707993756SAndreas Gohr            // use field label if no header was set
21807993756SAndreas Gohr            if(blank($header)) {
21901f8b845SAndreas Gohr                if(is_a($column, 'dokuwiki\plugin\struct\meta\Column')) {
22007993756SAndreas Gohr                    $header = $column->getTranslatedLabel();
22107993756SAndreas Gohr                } else {
22207993756SAndreas Gohr                    $header = 'column ' . $num; // this should never happen
22307993756SAndreas Gohr                }
22407993756SAndreas Gohr            }
22507993756SAndreas Gohr
22607993756SAndreas Gohr            // simple mode first
22707993756SAndreas Gohr            if($this->mode != 'xhtml') {
22807993756SAndreas Gohr                $this->renderer->tableheader_open();
22907993756SAndreas Gohr                $this->renderer->cdata($header);
23007993756SAndreas Gohr                $this->renderer->tableheader_close();
23107993756SAndreas Gohr                continue;
23207993756SAndreas Gohr            }
23307993756SAndreas Gohr
23407993756SAndreas Gohr            // still here? create custom header for more flexibility
23507993756SAndreas Gohr
2369113d04aSAndreas Gohr            // width setting, widths are prevalidated, no escape needed
23707993756SAndreas Gohr            $width = '';
2389113d04aSAndreas Gohr            if(isset($this->data['widths'][$num]) && $this->data['widths'][$num] != '-') {
2399113d04aSAndreas Gohr                $width = ' style="min-width: ' . $this->data['widths'][$num] . ';'.
2409113d04aSAndreas Gohr                         'max-width: ' . $this->data['widths'][$num] . ';"';
24107993756SAndreas Gohr            }
24207993756SAndreas Gohr
243d4b5a17cSAndreas Gohr            // prepare data attribute for inline edits
244d4b5a17cSAndreas Gohr            if(!is_a($column, '\dokuwiki\plugin\struct\meta\PageColumn') &&
245d4b5a17cSAndreas Gohr                !is_a($column, '\dokuwiki\plugin\struct\meta\RevisionColumn')
246d4b5a17cSAndreas Gohr            ) {
247d4b5a17cSAndreas Gohr                $data = 'data-field="' . hsc($column->getFullQualifiedLabel()) . '"';
248d4b5a17cSAndreas Gohr            } else {
249d4b5a17cSAndreas Gohr                $data = '';
250d4b5a17cSAndreas Gohr            }
251d4b5a17cSAndreas Gohr
25207993756SAndreas Gohr            // sort indicator and link
25307993756SAndreas Gohr            $sortclass = '';
25407993756SAndreas Gohr            $sorts = $this->searchConfig->getSorts();
25507993756SAndreas Gohr            $dynamic = $this->searchConfig->getDynamicParameters();
256aa124708SAndreas Gohr            $dynamic->setSort($column, true);
25707993756SAndreas Gohr            if(isset($sorts[$column->getFullQualifiedLabel()])) {
258aa124708SAndreas Gohr                list(/*colname*/, $currentSort) = $sorts[$column->getFullQualifiedLabel()];
259aa124708SAndreas Gohr                if($currentSort) {
26007993756SAndreas Gohr                    $sortclass = 'sort-down';
26107993756SAndreas Gohr                    $dynamic->setSort($column, false);
26207993756SAndreas Gohr                } else {
26307993756SAndreas Gohr                    $sortclass = 'sort-up';
26407993756SAndreas Gohr                }
26507993756SAndreas Gohr            }
26607993756SAndreas Gohr            $link = wl($this->id, $dynamic->getURLParameters());
26707993756SAndreas Gohr
26807993756SAndreas Gohr            // output XHTML header
269d4b5a17cSAndreas Gohr            $this->renderer->doc .= "<th $width $data>";
27007993756SAndreas Gohr            $this->renderer->doc .= '<a href="' . $link . '" class="' . $sortclass . '" title="' . $this->helper->getLang('sort') . '">' . hsc($header) . '</a>';
27107993756SAndreas Gohr            $this->renderer->doc .= '</th>';
27207993756SAndreas Gohr        }
27307993756SAndreas Gohr
27407993756SAndreas Gohr        $this->renderer->tablerow_close();
27507993756SAndreas Gohr    }
27607993756SAndreas Gohr
27707993756SAndreas Gohr    /**
278b7e1d73bSAndreas Gohr     * Is the result set currently dynamically filtered?
279b7e1d73bSAndreas Gohr     * @return bool
280b7e1d73bSAndreas Gohr     */
281b7e1d73bSAndreas Gohr    protected function isDynamicallyFiltered() {
282b7e1d73bSAndreas Gohr        if($this->mode != 'xhtml') return false;
283b7e1d73bSAndreas Gohr        if(!$this->data['dynfilters']) return false;
284b7e1d73bSAndreas Gohr
285b7e1d73bSAndreas Gohr        $dynamic = $this->searchConfig->getDynamicParameters();
286b7e1d73bSAndreas Gohr        return (bool) $dynamic->getFilters();
287b7e1d73bSAndreas Gohr    }
288b7e1d73bSAndreas Gohr
289b7e1d73bSAndreas Gohr    /**
29007993756SAndreas Gohr     * Add input fields for dynamic filtering
29107993756SAndreas Gohr     */
292986ab7e6SAndreas Gohr    protected function renderDynamicFilters() {
29307993756SAndreas Gohr        if($this->mode != 'xhtml') return;
29407993756SAndreas Gohr        if(!$this->data['dynfilters']) return;
2951bc467a4SMichael Grosse        if (is_a($this->renderer, 'renderer_plugin_dw2pdf')) {
296e6ae02ecSMichael Grosse            return;
297e6ae02ecSMichael Grosse        }
2981bc467a4SMichael Grosse        global $conf;
29907993756SAndreas Gohr
30007993756SAndreas Gohr        $this->renderer->doc .= '<tr class="dataflt">';
30107993756SAndreas Gohr
30207993756SAndreas Gohr        // add extra column for row numbers
30307993756SAndreas Gohr        if($this->data['rownumbers']) {
30407993756SAndreas Gohr            $this->renderer->doc .= '<th></th>';
30507993756SAndreas Gohr        }
30607993756SAndreas Gohr
30707993756SAndreas Gohr        // each column gets a form
30807993756SAndreas Gohr        foreach($this->columns as $column) {
30907993756SAndreas Gohr            $this->renderer->doc .= '<th>';
31007993756SAndreas Gohr            {
31107993756SAndreas Gohr                $form = new \Doku_Form(array('method' => 'GET', 'action' => wl($this->id)));
31276195677SAndreas Gohr                unset($form->_hidden['sectok']); // we don't need it here
31376195677SAndreas Gohr                if(!$conf['userewrite']) $form->addHidden('id', $this->id);
31407993756SAndreas Gohr
31507993756SAndreas Gohr                // current value
31607993756SAndreas Gohr                $dynamic = $this->searchConfig->getDynamicParameters();
31707993756SAndreas Gohr                $filters = $dynamic->getFilters();
31807993756SAndreas Gohr                if(isset($filters[$column->getFullQualifiedLabel()])) {
31907993756SAndreas Gohr                    list(, $current) = $filters[$column->getFullQualifiedLabel()];
32007993756SAndreas Gohr                    $dynamic->removeFilter($column);
32107993756SAndreas Gohr                } else {
32207993756SAndreas Gohr                    $current = '';
32307993756SAndreas Gohr                }
32407993756SAndreas Gohr
32507993756SAndreas Gohr                // Add current request params
32607993756SAndreas Gohr                $params = $dynamic->getURLParameters();
32707993756SAndreas Gohr                foreach($params as $key => $val) {
32807993756SAndreas Gohr                    $form->addHidden($key, $val);
32907993756SAndreas Gohr                }
33007993756SAndreas Gohr
33107993756SAndreas Gohr                // add input field
332db9b8745SAndreas Gohr                $key = $column->getFullQualifiedLabel() . $column->getType()->getDefaultComparator();
333d60f71efSAndreas Gohr                $form->addElement(form_makeField('text', SearchConfigParameters::$PARAM_FILTER . '[' . $key . ']', $current, ''));
33407993756SAndreas Gohr                $this->renderer->doc .= $form->getForm();
33507993756SAndreas Gohr            }
33607993756SAndreas Gohr            $this->renderer->doc .= '</th>';
33707993756SAndreas Gohr        }
33807993756SAndreas Gohr        $this->renderer->doc .= '</tr>';
33907993756SAndreas Gohr
34007993756SAndreas Gohr    }
34107993756SAndreas Gohr
34207993756SAndreas Gohr    /**
34307993756SAndreas Gohr     * Display the actual table data
34407993756SAndreas Gohr     */
345986ab7e6SAndreas Gohr    protected function renderResult() {
34607993756SAndreas Gohr        foreach($this->result as $rownum => $row) {
347*47eb8cceSSzymon Olewniczak            $data = array(
348*47eb8cceSSzymon Olewniczak                'id' => $this->id,
349*47eb8cceSSzymon Olewniczak                'mode' => $this->mode,
350*47eb8cceSSzymon Olewniczak                'renderer' => $this->renderer,
351*47eb8cceSSzymon Olewniczak                'searchConfig' => $this->searchConfig,
352*47eb8cceSSzymon Olewniczak                'data' => $this->data,
353*47eb8cceSSzymon Olewniczak                'rownum' => &$rownum,
354*47eb8cceSSzymon Olewniczak                'row' => &$row,
355*47eb8cceSSzymon Olewniczak            );
356*47eb8cceSSzymon Olewniczak            $evt = new \Doku_Event('PLUGIN_STRUCT_AGGREGATIONTABLE_RENDERRESULTROW', $data);
357*47eb8cceSSzymon Olewniczak            if($evt->advise_before()) {
358f107f479SAndreas Gohr                $this->renderResultRow($rownum, $row);
359f107f479SAndreas Gohr            }
360*47eb8cceSSzymon Olewniczak            $evt->advise_after();
361*47eb8cceSSzymon Olewniczak        }
362f107f479SAndreas Gohr    }
363f107f479SAndreas Gohr
364f107f479SAndreas Gohr    /**
365f107f479SAndreas Gohr     * Render a single result row
366f107f479SAndreas Gohr     *
367f107f479SAndreas Gohr     * @param int $rownum
368f107f479SAndreas Gohr     * @param array $row
369f107f479SAndreas Gohr     */
370f107f479SAndreas Gohr    protected function renderResultRow($rownum, $row) {
37107993756SAndreas Gohr        $this->renderer->tablerow_open();
37207993756SAndreas Gohr
373d4b5a17cSAndreas Gohr        // add data attribute for inline edit
374d4b5a17cSAndreas Gohr        if($this->mode == 'xhtml') {
375d4b5a17cSAndreas Gohr            $pid = $this->resultPIDs[$rownum];
376d4b5a17cSAndreas Gohr            $this->renderer->doc = substr(rtrim($this->renderer->doc), 0, -1); // remove closing '>'
377d4b5a17cSAndreas Gohr            $this->renderer->doc .= ' data-pid="' . hsc($pid) . '">';
378d4b5a17cSAndreas Gohr        }
379d4b5a17cSAndreas Gohr
38007993756SAndreas Gohr        // row number column
38107993756SAndreas Gohr        if($this->data['rownumbers']) {
38207993756SAndreas Gohr            $this->renderer->tablecell_open();
3833215aebfSSzymon Olewniczak            $searchConfigConf = $this->searchConfig->getConf();
3843215aebfSSzymon Olewniczak            $this->renderer->cdata($rownum + $searchConfigConf['offset'] + 1);
38507993756SAndreas Gohr            $this->renderer->tablecell_close();
38607993756SAndreas Gohr        }
38707993756SAndreas Gohr
38807993756SAndreas Gohr        /** @var Value $value */
38907993756SAndreas Gohr        foreach($row as $colnum => $value) {
39095eef580SAndreas Gohr            $this->renderer->tablecell_open(1, $this->data['align'][$colnum]);
39107993756SAndreas Gohr            $value->render($this->renderer, $this->mode);
39207993756SAndreas Gohr            $this->renderer->tablecell_close();
39307993756SAndreas Gohr
39407993756SAndreas Gohr            // summarize
39507993756SAndreas Gohr            if($this->data['summarize'] && is_numeric($value->getValue())) {
39607993756SAndreas Gohr                if(!isset($this->sums[$colnum])) {
39707993756SAndreas Gohr                    $this->sums[$colnum] = 0;
39807993756SAndreas Gohr                }
39907993756SAndreas Gohr                $this->sums[$colnum] += $value->getValue();
40007993756SAndreas Gohr            }
40107993756SAndreas Gohr        }
40207993756SAndreas Gohr        $this->renderer->tablerow_close();
40307993756SAndreas Gohr    }
40407993756SAndreas Gohr
40507993756SAndreas Gohr    /**
40607993756SAndreas Gohr     * Renders an information row for when no results were found
40707993756SAndreas Gohr     */
408986ab7e6SAndreas Gohr    protected function renderEmptyResult() {
40907993756SAndreas Gohr        $this->renderer->tablerow_open();
41070cf6339SAndreas Gohr        $this->renderer->tablecell_open(count($this->columns) + $this->data['rownumbers'], 'center');
41107993756SAndreas Gohr        $this->renderer->cdata($this->helper->getLang('none'));
41207993756SAndreas Gohr        $this->renderer->tablecell_close();
41307993756SAndreas Gohr        $this->renderer->tablerow_close();
41407993756SAndreas Gohr    }
41507993756SAndreas Gohr
41607993756SAndreas Gohr    /**
41707993756SAndreas Gohr     * Add sums if wanted
41807993756SAndreas Gohr     */
419986ab7e6SAndreas Gohr    protected function renderSums() {
420d18090e8SAndreas Gohr        if(empty($this->data['summarize'])) return;
42107993756SAndreas Gohr
422a0bf8bb2SAndreas Gohr        $this->renderer->info['struct_table_meta'] = true;
4238925ba29SAndreas Gohr        if($this->mode == 'xhtml') {
4248925ba29SAndreas Gohr            /** @noinspection PhpMethodParametersCountMismatchInspection */
4258925ba29SAndreas Gohr            $this->renderer->tablerow_open('summarize');
4268925ba29SAndreas Gohr        } else {
42707993756SAndreas Gohr            $this->renderer->tablerow_open();
4288925ba29SAndreas Gohr        }
42907993756SAndreas Gohr
43007993756SAndreas Gohr        if($this->data['rownumbers']) {
4318925ba29SAndreas Gohr            $this->renderer->tableheader_open();
4328925ba29SAndreas Gohr            $this->renderer->tableheader_close();
43307993756SAndreas Gohr        }
43407993756SAndreas Gohr
435aee4116bSAndreas Gohr        $len = count($this->columns);
43607993756SAndreas Gohr        for($i = 0; $i < $len; $i++) {
4378925ba29SAndreas Gohr            $this->renderer->tableheader_open(1, $this->data['align'][$i]);
438aee4116bSAndreas Gohr            if(!empty($this->sums[$i])) {
4399b97e610SAndreas Gohr                $this->renderer->cdata('∑ ');
4409b97e610SAndreas Gohr                $this->columns[$i]->getType()->renderValue($this->sums[$i], $this->renderer, $this->mode);
44107993756SAndreas Gohr            } else {
44207993756SAndreas Gohr                if($this->mode == 'xhtml') {
44307993756SAndreas Gohr                    $this->renderer->doc .= '&nbsp;';
44407993756SAndreas Gohr                }
44507993756SAndreas Gohr            }
4468925ba29SAndreas Gohr            $this->renderer->tableheader_close();
44707993756SAndreas Gohr        }
44807993756SAndreas Gohr        $this->renderer->tablerow_close();
449a0bf8bb2SAndreas Gohr        $this->renderer->info['struct_table_meta'] = false;
45007993756SAndreas Gohr    }
45107993756SAndreas Gohr
45207993756SAndreas Gohr    /**
453986ab7e6SAndreas Gohr     * Adds paging controls to the table
45407993756SAndreas Gohr     */
455986ab7e6SAndreas Gohr    protected function renderPagingControls() {
45607993756SAndreas Gohr        if(empty($this->data['limit'])) return;
457a0bf8bb2SAndreas Gohr        if($this->mode != 'xhtml') return;
45807993756SAndreas Gohr
459a0bf8bb2SAndreas Gohr        $this->renderer->info['struct_table_meta'] = true;
46007993756SAndreas Gohr        $this->renderer->tablerow_open();
4614bc1074dSMichael Grosse        $this->renderer->tableheader_open((count($this->columns) + ($this->data['rownumbers'] ? 1 : 0)));
46207993756SAndreas Gohr        $offset = $this->data['offset'];
46307993756SAndreas Gohr
46407993756SAndreas Gohr        // prev link
46507993756SAndreas Gohr        if($offset) {
46607993756SAndreas Gohr            $prev = $offset - $this->data['limit'];
46707993756SAndreas Gohr            if($prev < 0) {
46807993756SAndreas Gohr                $prev = 0;
46907993756SAndreas Gohr            }
47007993756SAndreas Gohr
47107993756SAndreas Gohr            $dynamic = $this->searchConfig->getDynamicParameters();
47207993756SAndreas Gohr            $dynamic->setOffset($prev);
47307993756SAndreas Gohr            $link = wl($this->id, $dynamic->getURLParameters());
47407993756SAndreas Gohr            $this->renderer->doc .= '<a href="' . $link . '" class="prev">' . $this->helper->getLang('prev') . '</a>';
47507993756SAndreas Gohr        }
47607993756SAndreas Gohr
47707993756SAndreas Gohr        // next link
47807993756SAndreas Gohr        if($this->resultCount > $offset + $this->data['limit']) {
47907993756SAndreas Gohr            $next = $offset + $this->data['limit'];
48007993756SAndreas Gohr            $dynamic = $this->searchConfig->getDynamicParameters();
48107993756SAndreas Gohr            $dynamic->setOffset($next);
48207993756SAndreas Gohr            $link = wl($this->id, $dynamic->getURLParameters());
48307993756SAndreas Gohr            $this->renderer->doc .= '<a href="' . $link . '" class="next">' . $this->helper->getLang('next') . '</a>';
48407993756SAndreas Gohr        }
48507993756SAndreas Gohr
48607993756SAndreas Gohr        $this->renderer->tableheader_close();
48707993756SAndreas Gohr        $this->renderer->tablerow_close();
488a0bf8bb2SAndreas Gohr        $this->renderer->info['struct_table_meta'] = true;
48907993756SAndreas Gohr    }
49009dd691aSAndreas Gohr
49109dd691aSAndreas Gohr    /**
49209dd691aSAndreas Gohr     * Adds CSV export controls
49309dd691aSAndreas Gohr     */
49409dd691aSAndreas Gohr    protected function renderExportControls() {
49509dd691aSAndreas Gohr        if($this->mode != 'xhtml') return;
4967b240ca8SAndreas Gohr        if(empty($this->data['csv'])) return;
49709dd691aSAndreas Gohr        if(!$this->resultCount) return;
49809dd691aSAndreas Gohr
499c8ccdaf8SAndreas Gohr        $dynamic = $this->searchConfig->getDynamicParameters();
500c8ccdaf8SAndreas Gohr        $params = $dynamic->getURLParameters();
501c8ccdaf8SAndreas Gohr        $params['hash'] = $this->renderer->info['struct_table_hash'];
502c8ccdaf8SAndreas Gohr
50309dd691aSAndreas Gohr        // FIXME apply dynamic filters
504eafc109fSAndreas Gohr        $link = exportlink($this->id, 'struct_csv', $params);
50509dd691aSAndreas Gohr
50609dd691aSAndreas Gohr        $this->renderer->doc .= '<a href="' . $link . '" class="export mediafile mf_csv">'.$this->helper->getLang('csvexport').'</a>';
50709dd691aSAndreas Gohr    }
50807993756SAndreas Gohr}
509