xref: /plugin/struct/meta/AggregationTable.php (revision ba7f5789bbbcab95d7a655f6ec50a97b731b40d5)
107993756SAndreas Gohr<?php
207993756SAndreas Gohr
3ba766201SAndreas Gohrnamespace dokuwiki\plugin\struct\meta;
407993756SAndreas Gohr
57234bfb1Ssplitbrainuse dokuwiki\Extension\Event;
67234bfb1Ssplitbrain
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
1767f70d54SAnna Dabrowska    public function __construct($id, $mode, \Doku_Renderer $renderer, SearchConfig $searchConfig)
1867f70d54SAnna Dabrowska    {
1967f70d54SAnna Dabrowska        parent::__construct($id, $mode, $renderer, $searchConfig);
2067f70d54SAnna Dabrowska    }
2167f70d54SAnna Dabrowska
22d90aa848SAndreas Gohr    /** @inheritdoc */
23d90aa848SAndreas Gohr    public function render($showNotFound = false)
24d6d97f60SAnna Dabrowska    {
25*ba7f5789SAnna Dabrowska        if (in_array($this->mode, \helper_plugin_struct::BLACKLIST_RENDERER)) return;
2667f70d54SAnna Dabrowska
27b7e1d73bSAndreas Gohr        // abort early if there are no results at all (not filtered)
28*ba7f5789SAnna Dabrowska        if ($this->searchConfig->getCount() <= 0 && !$this->isDynamicallyFiltered() && $showNotFound) {
29b7e1d73bSAndreas Gohr            $this->renderer->cdata($this->helper->getLang('none'));
30b7e1d73bSAndreas Gohr            return;
31b7e1d73bSAndreas Gohr        }
32b7e1d73bSAndreas Gohr
33986ab7e6SAndreas Gohr        $this->renderActiveFilters();
34844a4f01SFrieder Schrempf
357fe2cdf2SAndreas Gohr        $rendercontext = [
36844a4f01SFrieder Schrempf            'table' => $this,
37844a4f01SFrieder Schrempf            'renderer' => $this->renderer,
383f640228SFrieder Schrempf            'format' => $this->mode,
39844a4f01SFrieder Schrempf            'search' => $this->searchConfig,
40844a4f01SFrieder Schrempf            'columns' => $this->columns,
41*ba7f5789SAnna Dabrowska            'data' => $this->searchConfig->getRows()
427fe2cdf2SAndreas Gohr        ];
43844a4f01SFrieder Schrempf
447234bfb1Ssplitbrain        $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
67*ba7f5789SAnna Dabrowska        if ($this->searchConfig->getCount()) {
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
1257234bfb1Ssplitbrain        $fltrs = [];
12607993756SAndreas Gohr        foreach ($filters as $column => $filter) {
1277234bfb1Ssplitbrain            [$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()])) {
2147fe2cdf2SAndreas Gohr                [/*colname*/, $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>";
2263ebc6780SAnna Dabrowska
227da7041d3SAlexander Yakovlev            if (is_a($this->renderer, 'renderer_plugin_dw2pdf')) {
228da7041d3SAlexander Yakovlev                $this->renderer->doc .= hsc($header);
229da7041d3SAlexander Yakovlev            } else {
23017a3a578SAndreas Gohr                $this->renderer->doc .= '<a href="' . $link . '" class="' . $sortclass . '" ' .
23117a3a578SAndreas Gohr                    'title="' . $this->helper->getLang('sort') . '">' . hsc($header) . '</a>';
232da7041d3SAlexander Yakovlev            }
2333ebc6780SAnna Dabrowska
23407993756SAndreas Gohr            $this->renderer->doc .= '</th>';
23507993756SAndreas Gohr        }
23607993756SAndreas Gohr
23707993756SAndreas Gohr        $this->renderer->tablerow_close();
23807993756SAndreas Gohr    }
23907993756SAndreas Gohr
24007993756SAndreas Gohr    /**
241b7e1d73bSAndreas Gohr     * Is the result set currently dynamically filtered?
242b7e1d73bSAndreas Gohr     * @return bool
243b7e1d73bSAndreas Gohr     */
244d6d97f60SAnna Dabrowska    protected function isDynamicallyFiltered()
245d6d97f60SAnna Dabrowska    {
246b7e1d73bSAndreas Gohr        if ($this->mode != 'xhtml') return false;
247b7e1d73bSAndreas Gohr        if (!$this->data['dynfilters']) return false;
248b7e1d73bSAndreas Gohr
249b7e1d73bSAndreas Gohr        $dynamic = $this->searchConfig->getDynamicParameters();
250b7e1d73bSAndreas Gohr        return (bool)$dynamic->getFilters();
251b7e1d73bSAndreas Gohr    }
252b7e1d73bSAndreas Gohr
253b7e1d73bSAndreas Gohr    /**
25407993756SAndreas Gohr     * Add input fields for dynamic filtering
25507993756SAndreas Gohr     */
256d6d97f60SAnna Dabrowska    protected function renderDynamicFilters()
257d6d97f60SAnna Dabrowska    {
25807993756SAndreas Gohr        if ($this->mode != 'xhtml') return;
2591ca21e17SAnna Dabrowska        if (empty($this->data['dynfilters'])) return;
2601bc467a4SMichael Grosse        if (is_a($this->renderer, 'renderer_plugin_dw2pdf')) {
261e6ae02ecSMichael Grosse            return;
262e6ae02ecSMichael Grosse        }
2631bc467a4SMichael Grosse        global $conf;
26407993756SAndreas Gohr
26507993756SAndreas Gohr        $this->renderer->doc .= '<tr class="dataflt">';
26607993756SAndreas Gohr
26707993756SAndreas Gohr        // add extra column for row numbers
26807993756SAndreas Gohr        if ($this->data['rownumbers']) {
26907993756SAndreas Gohr            $this->renderer->doc .= '<th></th>';
27007993756SAndreas Gohr        }
27107993756SAndreas Gohr
27207993756SAndreas Gohr        // each column gets a form
27307993756SAndreas Gohr        foreach ($this->columns as $column) {
27407993756SAndreas Gohr            $this->renderer->doc .= '<th>';
27517a3a578SAndreas Gohr
27617a3a578SAndreas Gohr            // BEGIN FORM
2774b00515cSAnna Dabrowska            $form = new \Doku_Form(
2784b00515cSAnna Dabrowska                [
2794b00515cSAnna Dabrowska                    'method' => 'GET',
2804b00515cSAnna Dabrowska                    'action' => wl($this->id, $this->renderer->info['struct_table_hash'], false, '#')
2814b00515cSAnna Dabrowska                ]
2824b00515cSAnna Dabrowska            );
28376195677SAndreas Gohr            unset($form->_hidden['sectok']); // we don't need it here
28476195677SAndreas Gohr            if (!$conf['userewrite']) $form->addHidden('id', $this->id);
28507993756SAndreas Gohr
28607993756SAndreas Gohr            // current value
28707993756SAndreas Gohr            $dynamic = $this->searchConfig->getDynamicParameters();
28807993756SAndreas Gohr            $filters = $dynamic->getFilters();
28907993756SAndreas Gohr            if (isset($filters[$column->getFullQualifiedLabel()])) {
2907234bfb1Ssplitbrain                [, $current] = $filters[$column->getFullQualifiedLabel()];
29107993756SAndreas Gohr                $dynamic->removeFilter($column);
29207993756SAndreas Gohr            } else {
29307993756SAndreas Gohr                $current = '';
29407993756SAndreas Gohr            }
29507993756SAndreas Gohr
29607993756SAndreas Gohr            // Add current request params
29707993756SAndreas Gohr            $params = $dynamic->getURLParameters();
29807993756SAndreas Gohr            foreach ($params as $key => $val) {
29907993756SAndreas Gohr                $form->addHidden($key, $val);
30007993756SAndreas Gohr            }
30107993756SAndreas Gohr
30207993756SAndreas Gohr            // add input field
303db9b8745SAndreas Gohr            $key = $column->getFullQualifiedLabel() . $column->getType()->getDefaultComparator();
30417a3a578SAndreas Gohr            $form->addElement(
30517a3a578SAndreas Gohr                form_makeField('text', SearchConfigParameters::$PARAM_FILTER . '[' . $key . ']', $current, '')
30617a3a578SAndreas Gohr            );
30707993756SAndreas Gohr            $this->renderer->doc .= $form->getForm();
30817a3a578SAndreas Gohr            // END FORM
30917a3a578SAndreas Gohr
31007993756SAndreas Gohr            $this->renderer->doc .= '</th>';
31107993756SAndreas Gohr        }
31207993756SAndreas Gohr        $this->renderer->doc .= '</tr>';
31307993756SAndreas Gohr    }
31407993756SAndreas Gohr
31507993756SAndreas Gohr    /**
31607993756SAndreas Gohr     * Display the actual table data
31707993756SAndreas Gohr     */
318d6d97f60SAnna Dabrowska    protected function renderResult()
319d6d97f60SAnna Dabrowska    {
320*ba7f5789SAnna Dabrowska        foreach ($this->searchConfig->getRows() as $rownum => $row) {
3217fe2cdf2SAndreas Gohr            $data = [
32247eb8cceSSzymon Olewniczak                'id' => $this->id,
32347eb8cceSSzymon Olewniczak                'mode' => $this->mode,
32447eb8cceSSzymon Olewniczak                'renderer' => $this->renderer,
32547eb8cceSSzymon Olewniczak                'searchConfig' => $this->searchConfig,
32647eb8cceSSzymon Olewniczak                'data' => $this->data,
32747eb8cceSSzymon Olewniczak                'rownum' => &$rownum,
3287fe2cdf2SAndreas Gohr                'row' => &$row
3297fe2cdf2SAndreas Gohr            ];
3307234bfb1Ssplitbrain            $evt = new Event('PLUGIN_STRUCT_AGGREGATIONTABLE_RENDERRESULTROW', $data);
33147eb8cceSSzymon Olewniczak            if ($evt->advise_before()) {
332f107f479SAndreas Gohr                $this->renderResultRow($rownum, $row);
333f107f479SAndreas Gohr            }
33447eb8cceSSzymon Olewniczak            $evt->advise_after();
33547eb8cceSSzymon Olewniczak        }
336f107f479SAndreas Gohr    }
337f107f479SAndreas Gohr
338f107f479SAndreas Gohr    /**
339f107f479SAndreas Gohr     * Render a single result row
340f107f479SAndreas Gohr     *
341f107f479SAndreas Gohr     * @param int $rownum
342f107f479SAndreas Gohr     * @param array $row
343f107f479SAndreas Gohr     */
344d6d97f60SAnna Dabrowska    protected function renderResultRow($rownum, $row)
345d6d97f60SAnna Dabrowska    {
34607993756SAndreas Gohr        $this->renderer->tablerow_open();
34707993756SAndreas Gohr
348d4b5a17cSAndreas Gohr        // add data attribute for inline edit
349d4b5a17cSAndreas Gohr        if ($this->mode == 'xhtml') {
350*ba7f5789SAnna Dabrowska            $pid = $this->searchConfig->getPids()[$rownum];
351*ba7f5789SAnna Dabrowska            $rid = $this->searchConfig->getRids()[$rownum];
352*ba7f5789SAnna Dabrowska            $rev = $this->searchConfig->getRevs()[$rownum];
353d4b5a17cSAndreas Gohr            $this->renderer->doc = substr(rtrim($this->renderer->doc), 0, -1); // remove closing '>'
3546fd73b4bSAnna Dabrowska            $this->renderer->doc .= ' data-pid="' . hsc($pid) . '" data-rev="' . $rev . '" data-rid="' . $rid . '">';
355d4b5a17cSAndreas Gohr        }
356d4b5a17cSAndreas Gohr
35707993756SAndreas Gohr        // row number column
35834ea6e10SAnna Dabrowska        if (!empty($this->data['rownumbers'])) {
35907993756SAndreas Gohr            $this->renderer->tablecell_open();
360fdf37115SAndreas Gohr            $this->renderer->cdata($rownum + $this->searchConfig->getOffset() + 1);
36107993756SAndreas Gohr            $this->renderer->tablecell_close();
36207993756SAndreas Gohr        }
36307993756SAndreas Gohr
36407993756SAndreas Gohr        /** @var Value $value */
36507993756SAndreas Gohr        foreach ($row as $colnum => $value) {
3667234bfb1Ssplitbrain            $align = $this->data['align'][$colnum] ?? null;
36734ea6e10SAnna Dabrowska            $this->renderer->tablecell_open(1, $align);
36807993756SAndreas Gohr            $value->render($this->renderer, $this->mode);
36907993756SAndreas Gohr            $this->renderer->tablecell_close();
37007993756SAndreas Gohr
37107993756SAndreas Gohr            // summarize
3721ca21e17SAnna Dabrowska            if (!empty($this->data['summarize']) && is_numeric($value->getValue())) {
37307993756SAndreas Gohr                if (!isset($this->sums[$colnum])) {
37407993756SAndreas Gohr                    $this->sums[$colnum] = 0;
37507993756SAndreas Gohr                }
37607993756SAndreas Gohr                $this->sums[$colnum] += $value->getValue();
37707993756SAndreas Gohr            }
37807993756SAndreas Gohr        }
37907993756SAndreas Gohr        $this->renderer->tablerow_close();
38007993756SAndreas Gohr    }
38107993756SAndreas Gohr
38207993756SAndreas Gohr    /**
38307993756SAndreas Gohr     * Renders an information row for when no results were found
38407993756SAndreas Gohr     */
385d6d97f60SAnna Dabrowska    protected function renderEmptyResult()
386d6d97f60SAnna Dabrowska    {
38707993756SAndreas Gohr        $this->renderer->tablerow_open();
38870cf6339SAndreas Gohr        $this->renderer->tablecell_open(count($this->columns) + $this->data['rownumbers'], 'center');
38907993756SAndreas Gohr        $this->renderer->cdata($this->helper->getLang('none'));
39007993756SAndreas Gohr        $this->renderer->tablecell_close();
39107993756SAndreas Gohr        $this->renderer->tablerow_close();
39207993756SAndreas Gohr    }
39307993756SAndreas Gohr
39407993756SAndreas Gohr    /**
39507993756SAndreas Gohr     * Add sums if wanted
39607993756SAndreas Gohr     */
397d6d97f60SAnna Dabrowska    protected function renderSums()
398d6d97f60SAnna Dabrowska    {
399d18090e8SAndreas Gohr        if (empty($this->data['summarize'])) return;
40007993756SAndreas Gohr
401a0bf8bb2SAndreas Gohr        $this->renderer->info['struct_table_meta'] = true;
4028925ba29SAndreas Gohr        if ($this->mode == 'xhtml') {
4038925ba29SAndreas Gohr            $this->renderer->tablerow_open('summarize');
4048925ba29SAndreas Gohr        } else {
40507993756SAndreas Gohr            $this->renderer->tablerow_open();
4068925ba29SAndreas Gohr        }
40707993756SAndreas Gohr
40807993756SAndreas Gohr        if ($this->data['rownumbers']) {
4098925ba29SAndreas Gohr            $this->renderer->tableheader_open();
4108925ba29SAndreas Gohr            $this->renderer->tableheader_close();
41107993756SAndreas Gohr        }
41207993756SAndreas Gohr
413aee4116bSAndreas Gohr        $len = count($this->columns);
41407993756SAndreas Gohr        for ($i = 0; $i < $len; $i++) {
4158925ba29SAndreas Gohr            $this->renderer->tableheader_open(1, $this->data['align'][$i]);
416aee4116bSAndreas Gohr            if (!empty($this->sums[$i])) {
4179b97e610SAndreas Gohr                $this->renderer->cdata('∑ ');
4189b97e610SAndreas Gohr                $this->columns[$i]->getType()->renderValue($this->sums[$i], $this->renderer, $this->mode);
4197234bfb1Ssplitbrain            } elseif ($this->mode == 'xhtml') {
42007993756SAndreas Gohr                $this->renderer->doc .= '&nbsp;';
42107993756SAndreas Gohr            }
4228925ba29SAndreas Gohr            $this->renderer->tableheader_close();
42307993756SAndreas Gohr        }
42407993756SAndreas Gohr        $this->renderer->tablerow_close();
425a0bf8bb2SAndreas Gohr        $this->renderer->info['struct_table_meta'] = false;
42607993756SAndreas Gohr    }
42707993756SAndreas Gohr
42807993756SAndreas Gohr    /**
429986ab7e6SAndreas Gohr     * Adds paging controls to the table
43007993756SAndreas Gohr     */
431d6d97f60SAnna Dabrowska    protected function renderPagingControls()
432d6d97f60SAnna Dabrowska    {
433a0bf8bb2SAndreas Gohr        if ($this->mode != 'xhtml') return;
43407993756SAndreas Gohr
435fdf37115SAndreas Gohr        $limit = $this->searchConfig->getLimit();
436fdf37115SAndreas Gohr        if (!$limit) return;
437fdf37115SAndreas Gohr        $offset = $this->searchConfig->getOffset();
438fdf37115SAndreas Gohr
439a0bf8bb2SAndreas Gohr        $this->renderer->info['struct_table_meta'] = true;
44007993756SAndreas Gohr        $this->renderer->tablerow_open();
4414bc1074dSMichael Grosse        $this->renderer->tableheader_open((count($this->columns) + ($this->data['rownumbers'] ? 1 : 0)));
442fdf37115SAndreas Gohr
44307993756SAndreas Gohr
44407993756SAndreas Gohr        // prev link
44507993756SAndreas Gohr        if ($offset) {
446fdf37115SAndreas Gohr            $prev = $offset - $limit;
44707993756SAndreas Gohr            if ($prev < 0) {
44807993756SAndreas Gohr                $prev = 0;
44907993756SAndreas Gohr            }
45007993756SAndreas Gohr
45107993756SAndreas Gohr            $dynamic = $this->searchConfig->getDynamicParameters();
45207993756SAndreas Gohr            $dynamic->setOffset($prev);
45307993756SAndreas Gohr            $link = wl($this->id, $dynamic->getURLParameters());
45407993756SAndreas Gohr            $this->renderer->doc .= '<a href="' . $link . '" class="prev">' . $this->helper->getLang('prev') . '</a>';
45507993756SAndreas Gohr        }
45607993756SAndreas Gohr
45707993756SAndreas Gohr        // next link
458*ba7f5789SAnna Dabrowska        if ($this->searchConfig->getCount() > $offset + $limit) {
459fdf37115SAndreas Gohr            $next = $offset + $limit;
46007993756SAndreas Gohr            $dynamic = $this->searchConfig->getDynamicParameters();
46107993756SAndreas Gohr            $dynamic->setOffset($next);
46207993756SAndreas Gohr            $link = wl($this->id, $dynamic->getURLParameters());
46307993756SAndreas Gohr            $this->renderer->doc .= '<a href="' . $link . '" class="next">' . $this->helper->getLang('next') . '</a>';
46407993756SAndreas Gohr        }
46507993756SAndreas Gohr
46607993756SAndreas Gohr        $this->renderer->tableheader_close();
46707993756SAndreas Gohr        $this->renderer->tablerow_close();
468a0bf8bb2SAndreas Gohr        $this->renderer->info['struct_table_meta'] = true;
46907993756SAndreas Gohr    }
47009dd691aSAndreas Gohr
47109dd691aSAndreas Gohr    /**
47209dd691aSAndreas Gohr     * Adds CSV export controls
47309dd691aSAndreas Gohr     */
474d6d97f60SAnna Dabrowska    protected function renderExportControls()
475d6d97f60SAnna Dabrowska    {
47609dd691aSAndreas Gohr        if ($this->mode != 'xhtml') return;
4777b240ca8SAndreas Gohr        if (empty($this->data['csv'])) return;
478*ba7f5789SAnna Dabrowska        if (!$this->searchConfig->getCount()) return;
47909dd691aSAndreas Gohr
480c8ccdaf8SAndreas Gohr        $dynamic = $this->searchConfig->getDynamicParameters();
481c8ccdaf8SAndreas Gohr        $params = $dynamic->getURLParameters();
482c8ccdaf8SAndreas Gohr        $params['hash'] = $this->renderer->info['struct_table_hash'];
483c8ccdaf8SAndreas Gohr
48409dd691aSAndreas Gohr        // FIXME apply dynamic filters
485eafc109fSAndreas Gohr        $link = exportlink($this->id, 'struct_csv', $params);
48609dd691aSAndreas Gohr
48717a3a578SAndreas Gohr        $this->renderer->doc .= '<a href="' . $link . '" class="export mediafile mf_csv">' .
48817a3a578SAndreas Gohr            $this->helper->getLang('csvexport') . '</a>';
48909dd691aSAndreas Gohr    }
49007993756SAndreas Gohr}
491