xref: /plugin/struct/meta/AggregationTable.php (revision d90aa848684950ae06490f12279278db183f4fa5)
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 */
10*d90aa848SAndreas Gohrclass AggregationTable extends Aggregation
11d6d97f60SAnna Dabrowska{
12*d90aa848SAndreas Gohr    /** @var array for summing up columns */
13*d90aa848SAndreas Gohr    protected $sums;
1407993756SAndreas Gohr
15*d90aa848SAndreas Gohr    /** @var string[] the result PIDs for each row */
16d4b5a17cSAndreas Gohr    protected $resultPIDs;
170ceefd5cSAnna Dabrowska    protected $resultRids;
186fd73b4bSAnna Dabrowska    protected $resultRevs;
19d4b5a17cSAndreas Gohr
208ce43f5aSAnna Dabrowska    public function __construct($id, $mode, \Doku_Renderer $renderer, SearchConfig $searchConfig)
21d6d97f60SAnna Dabrowska    {
22*d90aa848SAndreas Gohr        parent::__construct($id, $mode, $renderer, $searchConfig);
23d4b5a17cSAndreas Gohr        $this->resultPIDs = $this->searchConfig->getPids();
240ceefd5cSAnna Dabrowska        $this->resultRids = $this->searchConfig->getRids();
256fd73b4bSAnna Dabrowska        $this->resultRevs = $this->searchConfig->getRevs();
2607993756SAndreas Gohr    }
2707993756SAndreas Gohr
28*d90aa848SAndreas Gohr    /** @inheritdoc */
29*d90aa848SAndreas Gohr    public function render($showNotFound = false)
30d6d97f60SAnna Dabrowska    {
31b7e1d73bSAndreas Gohr
32b7e1d73bSAndreas Gohr        // abort early if there are no results at all (not filtered)
33*d90aa848SAndreas Gohr        if (!$this->resultCount && !$this->isDynamicallyFiltered() && $showNotFound) {
34b7e1d73bSAndreas Gohr            $this->startScope();
35b7e1d73bSAndreas Gohr            $this->renderer->cdata($this->helper->getLang('none'));
36b7e1d73bSAndreas Gohr            $this->finishScope();
37b7e1d73bSAndreas Gohr            return;
38b7e1d73bSAndreas Gohr        }
39b7e1d73bSAndreas Gohr
4007993756SAndreas Gohr        $this->startScope();
41986ab7e6SAndreas Gohr        $this->renderActiveFilters();
42844a4f01SFrieder Schrempf
43844a4f01SFrieder Schrempf        $rendercontext = array(
44844a4f01SFrieder Schrempf            'table' => $this,
45844a4f01SFrieder Schrempf            'renderer' => $this->renderer,
463f640228SFrieder Schrempf            'format' => $this->mode,
47844a4f01SFrieder Schrempf            'search' => $this->searchConfig,
48844a4f01SFrieder Schrempf            'columns' => $this->columns,
49844a4f01SFrieder Schrempf            'data' => $this->result
50844a4f01SFrieder Schrempf        );
51844a4f01SFrieder Schrempf
522dbe71f8SAnna Dabrowska        $event = new \Doku_Event(
53844a4f01SFrieder Schrempf            'PLUGIN_STRUCT_RENDER_AGGREGATION_TABLE',
542dbe71f8SAnna Dabrowska            $rendercontext
55844a4f01SFrieder Schrempf        );
562dbe71f8SAnna Dabrowska        $event->trigger([$this, 'renderTable']);
57844a4f01SFrieder Schrempf
58844a4f01SFrieder Schrempf        // export handle
59844a4f01SFrieder Schrempf        $this->renderExportControls();
60844a4f01SFrieder Schrempf        $this->finishScope();
61844a4f01SFrieder Schrempf    }
62844a4f01SFrieder Schrempf
63844a4f01SFrieder Schrempf    /**
64844a4f01SFrieder Schrempf     * Render the default aggregation table
65844a4f01SFrieder Schrempf     */
66844a4f01SFrieder Schrempf    public function renderTable($rendercontext)
67844a4f01SFrieder Schrempf    {
6807993756SAndreas Gohr        $this->renderer->table_open();
6907993756SAndreas Gohr
7007993756SAndreas Gohr        // header
7107993756SAndreas Gohr        $this->renderer->tablethead_open();
72986ab7e6SAndreas Gohr        $this->renderColumnHeaders();
73986ab7e6SAndreas Gohr        $this->renderDynamicFilters();
7407993756SAndreas Gohr        $this->renderer->tablethead_close();
7507993756SAndreas Gohr
7607993756SAndreas Gohr        if ($this->resultCount) {
7707993756SAndreas Gohr            // actual data
78a9fd81f9SAndreas Gohr            $this->renderer->tabletbody_open();
79986ab7e6SAndreas Gohr            $this->renderResult();
80a9fd81f9SAndreas Gohr            $this->renderer->tabletbody_close();
8107993756SAndreas Gohr
82a9fd81f9SAndreas Gohr            // footer (tfoot is develonly currently)
83a9fd81f9SAndreas Gohr            if (method_exists($this->renderer, 'tabletfoot_open')) $this->renderer->tabletfoot_open();
84986ab7e6SAndreas Gohr            $this->renderSums();
85986ab7e6SAndreas Gohr            $this->renderPagingControls();
86a9fd81f9SAndreas Gohr            if (method_exists($this->renderer, 'tabletfoot_close')) $this->renderer->tabletfoot_close();
8707993756SAndreas Gohr        } else {
8807993756SAndreas Gohr            // nothing found
89986ab7e6SAndreas Gohr            $this->renderEmptyResult();
9007993756SAndreas Gohr        }
9107993756SAndreas Gohr
9207993756SAndreas Gohr        // table close
9307993756SAndreas Gohr        $this->renderer->table_close();
9407993756SAndreas Gohr    }
9507993756SAndreas Gohr
9607993756SAndreas Gohr    /**
9707993756SAndreas Gohr     * Adds additional info to document and renderer in XHTML mode
9807993756SAndreas Gohr     *
9907993756SAndreas Gohr     * @see finishScope()
10007993756SAndreas Gohr     */
101d6d97f60SAnna Dabrowska    protected function startScope()
102d6d97f60SAnna Dabrowska    {
10307993756SAndreas Gohr        // unique identifier for this aggregation
10407993756SAndreas Gohr        $this->renderer->info['struct_table_hash'] = md5(var_export($this->data, true));
10509dd691aSAndreas Gohr
10609dd691aSAndreas Gohr        // wrapping div
10709dd691aSAndreas Gohr        if ($this->mode != 'xhtml') return;
10809dd691aSAndreas Gohr        $this->renderer->doc .= "<div class=\"structaggregation\">";
10907993756SAndreas Gohr    }
11007993756SAndreas Gohr
11107993756SAndreas Gohr    /**
11207993756SAndreas Gohr     * Closes the table and anything opened in startScope()
11307993756SAndreas Gohr     *
11407993756SAndreas Gohr     * @see startScope()
11507993756SAndreas Gohr     */
116d6d97f60SAnna Dabrowska    protected function finishScope()
117d6d97f60SAnna Dabrowska    {
11807993756SAndreas Gohr        // remove identifier from renderer again
11907993756SAndreas Gohr        if (isset($this->renderer->info['struct_table_hash'])) {
12007993756SAndreas Gohr            unset($this->renderer->info['struct_table_hash']);
12107993756SAndreas Gohr        }
12209dd691aSAndreas Gohr
12309dd691aSAndreas Gohr        // wrapping div
12409dd691aSAndreas Gohr        if ($this->mode != 'xhtml') return;
12509dd691aSAndreas Gohr        $this->renderer->doc .= '</div>';
12607993756SAndreas Gohr    }
12707993756SAndreas Gohr
12807993756SAndreas Gohr    /**
12907993756SAndreas Gohr     * Displays info about the currently applied filters
13007993756SAndreas Gohr     */
131d6d97f60SAnna Dabrowska    protected function renderActiveFilters()
132d6d97f60SAnna Dabrowska    {
13307993756SAndreas Gohr        if ($this->mode != 'xhtml') return;
13407993756SAndreas Gohr        $dynamic = $this->searchConfig->getDynamicParameters();
13507993756SAndreas Gohr        $filters = $dynamic->getFilters();
13607993756SAndreas Gohr        if (!$filters) return;
13707993756SAndreas Gohr
13807993756SAndreas Gohr        $fltrs = array();
13907993756SAndreas Gohr        foreach ($filters as $column => $filter) {
14007993756SAndreas Gohr            list($comp, $value) = $filter;
14104ec4785SAnna Dabrowska
14204ec4785SAnna Dabrowska            // display the filters in a human readable format
14304ec4785SAnna Dabrowska            foreach ($this->columns as $col) {
14404ec4785SAnna Dabrowska                if ($column === $col->getFullQualifiedLabel()) {
14504ec4785SAnna Dabrowska                    $column = $col->getTranslatedLabel();
14604ec4785SAnna Dabrowska                }
14704ec4785SAnna Dabrowska            }
1481f075418SAnna Dabrowska            $fltrs[] = sprintf('"%s" %s "%s"', $column, $this->helper->getLang("comparator $comp"), $value);
14907993756SAndreas Gohr        }
15007993756SAndreas Gohr
15107993756SAndreas Gohr        $this->renderer->doc .= '<div class="filter">';
15217a3a578SAndreas Gohr        $this->renderer->doc .= '<h4>' .
15317a3a578SAndreas Gohr            sprintf(
15417a3a578SAndreas Gohr                $this->helper->getLang('tablefilteredby'),
15517a3a578SAndreas Gohr                hsc(implode(' & ', $fltrs))
15617a3a578SAndreas Gohr            ) .
15717a3a578SAndreas Gohr            '</h4>';
15807993756SAndreas Gohr        $this->renderer->doc .= '<div class="resetfilter">';
15907993756SAndreas Gohr        $this->renderer->internallink($this->id, $this->helper->getLang('tableresetfilter'));
16007993756SAndreas Gohr        $this->renderer->doc .= '</div>';
16107993756SAndreas Gohr        $this->renderer->doc .= '</div>';
16207993756SAndreas Gohr    }
16307993756SAndreas Gohr
16407993756SAndreas Gohr    /**
16507993756SAndreas Gohr     * Shows the column headers with links to sort by column
16607993756SAndreas Gohr     */
167d6d97f60SAnna Dabrowska    protected function renderColumnHeaders()
168d6d97f60SAnna Dabrowska    {
16907993756SAndreas Gohr        $this->renderer->tablerow_open();
17007993756SAndreas Gohr
17107993756SAndreas Gohr        // additional column for row numbers
17234ea6e10SAnna Dabrowska        if (!empty($this->data['rownumbers'])) {
17307993756SAndreas Gohr            $this->renderer->tableheader_open();
17407993756SAndreas Gohr            $this->renderer->cdata('#');
17507993756SAndreas Gohr            $this->renderer->tableheader_close();
17607993756SAndreas Gohr        }
17707993756SAndreas Gohr
17807993756SAndreas Gohr        // show all headers
1798c4ee9beSAndreas Gohr        foreach ($this->columns as $num => $column) {
1808c4ee9beSAndreas Gohr            $header = '';
1818c4ee9beSAndreas Gohr            if (isset($this->data['headers'][$num])) {
1828c4ee9beSAndreas Gohr                $header = $this->data['headers'][$num];
1838c4ee9beSAndreas Gohr            }
18407993756SAndreas Gohr
18507993756SAndreas Gohr            // use field label if no header was set
18607993756SAndreas Gohr            if (blank($header)) {
18701f8b845SAndreas Gohr                if (is_a($column, 'dokuwiki\plugin\struct\meta\Column')) {
18807993756SAndreas Gohr                    $header = $column->getTranslatedLabel();
18907993756SAndreas Gohr                } else {
19007993756SAndreas Gohr                    $header = 'column ' . $num; // this should never happen
19107993756SAndreas Gohr                }
19207993756SAndreas Gohr            }
19307993756SAndreas Gohr
19407993756SAndreas Gohr            // simple mode first
19507993756SAndreas Gohr            if ($this->mode != 'xhtml') {
19607993756SAndreas Gohr                $this->renderer->tableheader_open();
19707993756SAndreas Gohr                $this->renderer->cdata($header);
19807993756SAndreas Gohr                $this->renderer->tableheader_close();
19907993756SAndreas Gohr                continue;
20007993756SAndreas Gohr            }
20107993756SAndreas Gohr
20207993756SAndreas Gohr            // still here? create custom header for more flexibility
20307993756SAndreas Gohr
2049113d04aSAndreas Gohr            // width setting, widths are prevalidated, no escape needed
20507993756SAndreas Gohr            $width = '';
2069113d04aSAndreas Gohr            if (isset($this->data['widths'][$num]) && $this->data['widths'][$num] != '-') {
2079113d04aSAndreas Gohr                $width = ' style="min-width: ' . $this->data['widths'][$num] . ';' .
2089113d04aSAndreas Gohr                    'max-width: ' . $this->data['widths'][$num] . ';"';
20907993756SAndreas Gohr            }
21007993756SAndreas Gohr
211d4b5a17cSAndreas Gohr            // prepare data attribute for inline edits
212d6d97f60SAnna Dabrowska            if (
213d6d97f60SAnna Dabrowska                !is_a($column, '\dokuwiki\plugin\struct\meta\PageColumn') &&
214d4b5a17cSAndreas Gohr                !is_a($column, '\dokuwiki\plugin\struct\meta\RevisionColumn')
215d4b5a17cSAndreas Gohr            ) {
216d4b5a17cSAndreas Gohr                $data = 'data-field="' . hsc($column->getFullQualifiedLabel()) . '"';
217d4b5a17cSAndreas Gohr            } else {
218d4b5a17cSAndreas Gohr                $data = '';
219d4b5a17cSAndreas Gohr            }
220d4b5a17cSAndreas Gohr
22107993756SAndreas Gohr            // sort indicator and link
22207993756SAndreas Gohr            $sortclass = '';
22307993756SAndreas Gohr            $sorts = $this->searchConfig->getSorts();
22407993756SAndreas Gohr            $dynamic = $this->searchConfig->getDynamicParameters();
225aa124708SAndreas Gohr            $dynamic->setSort($column, true);
22607993756SAndreas Gohr            if (isset($sorts[$column->getFullQualifiedLabel()])) {
227aa124708SAndreas Gohr                list(/*colname*/, $currentSort) = $sorts[$column->getFullQualifiedLabel()];
228aa124708SAndreas Gohr                if ($currentSort) {
22907993756SAndreas Gohr                    $sortclass = 'sort-down';
23007993756SAndreas Gohr                    $dynamic->setSort($column, false);
23107993756SAndreas Gohr                } else {
23207993756SAndreas Gohr                    $sortclass = 'sort-up';
23307993756SAndreas Gohr                }
23407993756SAndreas Gohr            }
23507993756SAndreas Gohr            $link = wl($this->id, $dynamic->getURLParameters());
23607993756SAndreas Gohr
23707993756SAndreas Gohr            // output XHTML header
238d4b5a17cSAndreas Gohr            $this->renderer->doc .= "<th $width $data>";
23917a3a578SAndreas Gohr            $this->renderer->doc .= '<a href="' . $link . '" class="' . $sortclass . '" ' .
24017a3a578SAndreas Gohr                'title="' . $this->helper->getLang('sort') . '">' . hsc($header) . '</a>';
24107993756SAndreas Gohr            $this->renderer->doc .= '</th>';
24207993756SAndreas Gohr        }
24307993756SAndreas Gohr
24407993756SAndreas Gohr        $this->renderer->tablerow_close();
24507993756SAndreas Gohr    }
24607993756SAndreas Gohr
24707993756SAndreas Gohr    /**
248b7e1d73bSAndreas Gohr     * Is the result set currently dynamically filtered?
249b7e1d73bSAndreas Gohr     * @return bool
250b7e1d73bSAndreas Gohr     */
251d6d97f60SAnna Dabrowska    protected function isDynamicallyFiltered()
252d6d97f60SAnna Dabrowska    {
253b7e1d73bSAndreas Gohr        if ($this->mode != 'xhtml') return false;
254b7e1d73bSAndreas Gohr        if (!$this->data['dynfilters']) return false;
255b7e1d73bSAndreas Gohr
256b7e1d73bSAndreas Gohr        $dynamic = $this->searchConfig->getDynamicParameters();
257b7e1d73bSAndreas Gohr        return (bool)$dynamic->getFilters();
258b7e1d73bSAndreas Gohr    }
259b7e1d73bSAndreas Gohr
260b7e1d73bSAndreas Gohr    /**
26107993756SAndreas Gohr     * Add input fields for dynamic filtering
26207993756SAndreas Gohr     */
263d6d97f60SAnna Dabrowska    protected function renderDynamicFilters()
264d6d97f60SAnna Dabrowska    {
26507993756SAndreas Gohr        if ($this->mode != 'xhtml') return;
2661ca21e17SAnna Dabrowska        if (empty($this->data['dynfilters'])) return;
2671bc467a4SMichael Grosse        if (is_a($this->renderer, 'renderer_plugin_dw2pdf')) {
268e6ae02ecSMichael Grosse            return;
269e6ae02ecSMichael Grosse        }
2701bc467a4SMichael Grosse        global $conf;
27107993756SAndreas Gohr
27207993756SAndreas Gohr        $this->renderer->doc .= '<tr class="dataflt">';
27307993756SAndreas Gohr
27407993756SAndreas Gohr        // add extra column for row numbers
27507993756SAndreas Gohr        if ($this->data['rownumbers']) {
27607993756SAndreas Gohr            $this->renderer->doc .= '<th></th>';
27707993756SAndreas Gohr        }
27807993756SAndreas Gohr
27907993756SAndreas Gohr        // each column gets a form
28007993756SAndreas Gohr        foreach ($this->columns as $column) {
28107993756SAndreas Gohr            $this->renderer->doc .= '<th>';
28217a3a578SAndreas Gohr
28317a3a578SAndreas Gohr            // BEGIN FORM
28407993756SAndreas Gohr            $form = new \Doku_Form(array('method' => 'GET', 'action' => wl($this->id)));
28576195677SAndreas Gohr            unset($form->_hidden['sectok']); // we don't need it here
28676195677SAndreas Gohr            if (!$conf['userewrite']) $form->addHidden('id', $this->id);
28707993756SAndreas Gohr
28807993756SAndreas Gohr            // current value
28907993756SAndreas Gohr            $dynamic = $this->searchConfig->getDynamicParameters();
29007993756SAndreas Gohr            $filters = $dynamic->getFilters();
29107993756SAndreas Gohr            if (isset($filters[$column->getFullQualifiedLabel()])) {
29207993756SAndreas Gohr                list(, $current) = $filters[$column->getFullQualifiedLabel()];
29307993756SAndreas Gohr                $dynamic->removeFilter($column);
29407993756SAndreas Gohr            } else {
29507993756SAndreas Gohr                $current = '';
29607993756SAndreas Gohr            }
29707993756SAndreas Gohr
29807993756SAndreas Gohr            // Add current request params
29907993756SAndreas Gohr            $params = $dynamic->getURLParameters();
30007993756SAndreas Gohr            foreach ($params as $key => $val) {
30107993756SAndreas Gohr                $form->addHidden($key, $val);
30207993756SAndreas Gohr            }
30307993756SAndreas Gohr
30407993756SAndreas Gohr            // add input field
305db9b8745SAndreas Gohr            $key = $column->getFullQualifiedLabel() . $column->getType()->getDefaultComparator();
30617a3a578SAndreas Gohr            $form->addElement(
30717a3a578SAndreas Gohr                form_makeField('text', SearchConfigParameters::$PARAM_FILTER . '[' . $key . ']', $current, '')
30817a3a578SAndreas Gohr            );
30907993756SAndreas Gohr            $this->renderer->doc .= $form->getForm();
31017a3a578SAndreas Gohr            // END FORM
31117a3a578SAndreas Gohr
31207993756SAndreas Gohr            $this->renderer->doc .= '</th>';
31307993756SAndreas Gohr        }
31407993756SAndreas Gohr        $this->renderer->doc .= '</tr>';
31507993756SAndreas Gohr    }
31607993756SAndreas Gohr
31707993756SAndreas Gohr    /**
31807993756SAndreas Gohr     * Display the actual table data
31907993756SAndreas Gohr     */
320d6d97f60SAnna Dabrowska    protected function renderResult()
321d6d97f60SAnna Dabrowska    {
32207993756SAndreas Gohr        foreach ($this->result as $rownum => $row) {
32347eb8cceSSzymon Olewniczak            $data = array(
32447eb8cceSSzymon Olewniczak                'id' => $this->id,
32547eb8cceSSzymon Olewniczak                'mode' => $this->mode,
32647eb8cceSSzymon Olewniczak                'renderer' => $this->renderer,
32747eb8cceSSzymon Olewniczak                'searchConfig' => $this->searchConfig,
32847eb8cceSSzymon Olewniczak                'data' => $this->data,
32947eb8cceSSzymon Olewniczak                'rownum' => &$rownum,
33047eb8cceSSzymon Olewniczak                'row' => &$row,
33147eb8cceSSzymon Olewniczak            );
33247eb8cceSSzymon Olewniczak            $evt = new \Doku_Event('PLUGIN_STRUCT_AGGREGATIONTABLE_RENDERRESULTROW', $data);
33347eb8cceSSzymon Olewniczak            if ($evt->advise_before()) {
334f107f479SAndreas Gohr                $this->renderResultRow($rownum, $row);
335f107f479SAndreas Gohr            }
33647eb8cceSSzymon Olewniczak            $evt->advise_after();
33747eb8cceSSzymon Olewniczak        }
338f107f479SAndreas Gohr    }
339f107f479SAndreas Gohr
340f107f479SAndreas Gohr    /**
341f107f479SAndreas Gohr     * Render a single result row
342f107f479SAndreas Gohr     *
343f107f479SAndreas Gohr     * @param int $rownum
344f107f479SAndreas Gohr     * @param array $row
345f107f479SAndreas Gohr     */
346d6d97f60SAnna Dabrowska    protected function renderResultRow($rownum, $row)
347d6d97f60SAnna Dabrowska    {
34807993756SAndreas Gohr        $this->renderer->tablerow_open();
34907993756SAndreas Gohr
350d4b5a17cSAndreas Gohr        // add data attribute for inline edit
351d4b5a17cSAndreas Gohr        if ($this->mode == 'xhtml') {
352d4b5a17cSAndreas Gohr            $pid = $this->resultPIDs[$rownum];
3530ceefd5cSAnna Dabrowska            $rid = $this->resultRids[$rownum];
3546fd73b4bSAnna Dabrowska            $rev = $this->resultRevs[$rownum];
355d4b5a17cSAndreas Gohr            $this->renderer->doc = substr(rtrim($this->renderer->doc), 0, -1); // remove closing '>'
3566fd73b4bSAnna Dabrowska            $this->renderer->doc .= ' data-pid="' . hsc($pid) . '" data-rev="' . $rev . '" data-rid="' . $rid . '">';
357d4b5a17cSAndreas Gohr        }
358d4b5a17cSAndreas Gohr
35907993756SAndreas Gohr        // row number column
36034ea6e10SAnna Dabrowska        if (!empty($this->data['rownumbers'])) {
36107993756SAndreas Gohr            $this->renderer->tablecell_open();
3623215aebfSSzymon Olewniczak            $searchConfigConf = $this->searchConfig->getConf();
3633215aebfSSzymon Olewniczak            $this->renderer->cdata($rownum + $searchConfigConf['offset'] + 1);
36407993756SAndreas Gohr            $this->renderer->tablecell_close();
36507993756SAndreas Gohr        }
36607993756SAndreas Gohr
36707993756SAndreas Gohr        /** @var Value $value */
36807993756SAndreas Gohr        foreach ($row as $colnum => $value) {
36934ea6e10SAnna Dabrowska            $align = isset($this->data['align'][$colnum]) ? $this->data['align'][$colnum] : null;
37034ea6e10SAnna Dabrowska            $this->renderer->tablecell_open(1, $align);
37107993756SAndreas Gohr            $value->render($this->renderer, $this->mode);
37207993756SAndreas Gohr            $this->renderer->tablecell_close();
37307993756SAndreas Gohr
37407993756SAndreas Gohr            // summarize
3751ca21e17SAnna Dabrowska            if (!empty($this->data['summarize']) && is_numeric($value->getValue())) {
37607993756SAndreas Gohr                if (!isset($this->sums[$colnum])) {
37707993756SAndreas Gohr                    $this->sums[$colnum] = 0;
37807993756SAndreas Gohr                }
37907993756SAndreas Gohr                $this->sums[$colnum] += $value->getValue();
38007993756SAndreas Gohr            }
38107993756SAndreas Gohr        }
38207993756SAndreas Gohr        $this->renderer->tablerow_close();
38307993756SAndreas Gohr    }
38407993756SAndreas Gohr
38507993756SAndreas Gohr    /**
38607993756SAndreas Gohr     * Renders an information row for when no results were found
38707993756SAndreas Gohr     */
388d6d97f60SAnna Dabrowska    protected function renderEmptyResult()
389d6d97f60SAnna Dabrowska    {
39007993756SAndreas Gohr        $this->renderer->tablerow_open();
39170cf6339SAndreas Gohr        $this->renderer->tablecell_open(count($this->columns) + $this->data['rownumbers'], 'center');
39207993756SAndreas Gohr        $this->renderer->cdata($this->helper->getLang('none'));
39307993756SAndreas Gohr        $this->renderer->tablecell_close();
39407993756SAndreas Gohr        $this->renderer->tablerow_close();
39507993756SAndreas Gohr    }
39607993756SAndreas Gohr
39707993756SAndreas Gohr    /**
39807993756SAndreas Gohr     * Add sums if wanted
39907993756SAndreas Gohr     */
400d6d97f60SAnna Dabrowska    protected function renderSums()
401d6d97f60SAnna Dabrowska    {
402d18090e8SAndreas Gohr        if (empty($this->data['summarize'])) return;
40307993756SAndreas Gohr
404a0bf8bb2SAndreas Gohr        $this->renderer->info['struct_table_meta'] = true;
4058925ba29SAndreas Gohr        if ($this->mode == 'xhtml') {
4068925ba29SAndreas Gohr            /** @noinspection PhpMethodParametersCountMismatchInspection */
4078925ba29SAndreas Gohr            $this->renderer->tablerow_open('summarize');
4088925ba29SAndreas Gohr        } else {
40907993756SAndreas Gohr            $this->renderer->tablerow_open();
4108925ba29SAndreas Gohr        }
41107993756SAndreas Gohr
41207993756SAndreas Gohr        if ($this->data['rownumbers']) {
4138925ba29SAndreas Gohr            $this->renderer->tableheader_open();
4148925ba29SAndreas Gohr            $this->renderer->tableheader_close();
41507993756SAndreas Gohr        }
41607993756SAndreas Gohr
417aee4116bSAndreas Gohr        $len = count($this->columns);
41807993756SAndreas Gohr        for ($i = 0; $i < $len; $i++) {
4198925ba29SAndreas Gohr            $this->renderer->tableheader_open(1, $this->data['align'][$i]);
420aee4116bSAndreas Gohr            if (!empty($this->sums[$i])) {
4219b97e610SAndreas Gohr                $this->renderer->cdata('∑ ');
4229b97e610SAndreas Gohr                $this->columns[$i]->getType()->renderValue($this->sums[$i], $this->renderer, $this->mode);
42307993756SAndreas Gohr            } else {
42407993756SAndreas Gohr                if ($this->mode == 'xhtml') {
42507993756SAndreas Gohr                    $this->renderer->doc .= '&nbsp;';
42607993756SAndreas Gohr                }
42707993756SAndreas Gohr            }
4288925ba29SAndreas Gohr            $this->renderer->tableheader_close();
42907993756SAndreas Gohr        }
43007993756SAndreas Gohr        $this->renderer->tablerow_close();
431a0bf8bb2SAndreas Gohr        $this->renderer->info['struct_table_meta'] = false;
43207993756SAndreas Gohr    }
43307993756SAndreas Gohr
43407993756SAndreas Gohr    /**
435986ab7e6SAndreas Gohr     * Adds paging controls to the table
43607993756SAndreas Gohr     */
437d6d97f60SAnna Dabrowska    protected function renderPagingControls()
438d6d97f60SAnna Dabrowska    {
43907993756SAndreas Gohr        if (empty($this->data['limit'])) return;
440a0bf8bb2SAndreas Gohr        if ($this->mode != 'xhtml') return;
44107993756SAndreas Gohr
442a0bf8bb2SAndreas Gohr        $this->renderer->info['struct_table_meta'] = true;
44307993756SAndreas Gohr        $this->renderer->tablerow_open();
4444bc1074dSMichael Grosse        $this->renderer->tableheader_open((count($this->columns) + ($this->data['rownumbers'] ? 1 : 0)));
44507993756SAndreas Gohr        $offset = $this->data['offset'];
44607993756SAndreas Gohr
44707993756SAndreas Gohr        // prev link
44807993756SAndreas Gohr        if ($offset) {
44907993756SAndreas Gohr            $prev = $offset - $this->data['limit'];
45007993756SAndreas Gohr            if ($prev < 0) {
45107993756SAndreas Gohr                $prev = 0;
45207993756SAndreas Gohr            }
45307993756SAndreas Gohr
45407993756SAndreas Gohr            $dynamic = $this->searchConfig->getDynamicParameters();
45507993756SAndreas Gohr            $dynamic->setOffset($prev);
45607993756SAndreas Gohr            $link = wl($this->id, $dynamic->getURLParameters());
45707993756SAndreas Gohr            $this->renderer->doc .= '<a href="' . $link . '" class="prev">' . $this->helper->getLang('prev') . '</a>';
45807993756SAndreas Gohr        }
45907993756SAndreas Gohr
46007993756SAndreas Gohr        // next link
46107993756SAndreas Gohr        if ($this->resultCount > $offset + $this->data['limit']) {
46207993756SAndreas Gohr            $next = $offset + $this->data['limit'];
46307993756SAndreas Gohr            $dynamic = $this->searchConfig->getDynamicParameters();
46407993756SAndreas Gohr            $dynamic->setOffset($next);
46507993756SAndreas Gohr            $link = wl($this->id, $dynamic->getURLParameters());
46607993756SAndreas Gohr            $this->renderer->doc .= '<a href="' . $link . '" class="next">' . $this->helper->getLang('next') . '</a>';
46707993756SAndreas Gohr        }
46807993756SAndreas Gohr
46907993756SAndreas Gohr        $this->renderer->tableheader_close();
47007993756SAndreas Gohr        $this->renderer->tablerow_close();
471a0bf8bb2SAndreas Gohr        $this->renderer->info['struct_table_meta'] = true;
47207993756SAndreas Gohr    }
47309dd691aSAndreas Gohr
47409dd691aSAndreas Gohr    /**
47509dd691aSAndreas Gohr     * Adds CSV export controls
47609dd691aSAndreas Gohr     */
477d6d97f60SAnna Dabrowska    protected function renderExportControls()
478d6d97f60SAnna Dabrowska    {
47909dd691aSAndreas Gohr        if ($this->mode != 'xhtml') return;
4807b240ca8SAndreas Gohr        if (empty($this->data['csv'])) return;
48109dd691aSAndreas Gohr        if (!$this->resultCount) return;
48209dd691aSAndreas Gohr
483c8ccdaf8SAndreas Gohr        $dynamic = $this->searchConfig->getDynamicParameters();
484c8ccdaf8SAndreas Gohr        $params = $dynamic->getURLParameters();
485c8ccdaf8SAndreas Gohr        $params['hash'] = $this->renderer->info['struct_table_hash'];
486c8ccdaf8SAndreas Gohr
48709dd691aSAndreas Gohr        // FIXME apply dynamic filters
488eafc109fSAndreas Gohr        $link = exportlink($this->id, 'struct_csv', $params);
48909dd691aSAndreas Gohr
49017a3a578SAndreas Gohr        $this->renderer->doc .= '<a href="' . $link . '" class="export mediafile mf_csv">' .
49117a3a578SAndreas Gohr            $this->helper->getLang('csvexport') . '</a>';
49209dd691aSAndreas Gohr    }
49307993756SAndreas Gohr}
494