1f1812f0bSAndreas Gohr<?php 2f1812f0bSAndreas Gohr 3f1812f0bSAndreas Gohrnamespace dokuwiki\plugin\struct\meta; 4f1812f0bSAndreas Gohr 5f1812f0bSAndreas Gohruse dokuwiki\Form\Form; 6f1812f0bSAndreas Gohruse dokuwiki\Utf8\Sort; 7f1812f0bSAndreas Gohr 8f1812f0bSAndreas Gohr/** 9f1812f0bSAndreas Gohr * Struct filter class 10f1812f0bSAndreas Gohr */ 11f1812f0bSAndreas Gohrclass AggregationFilter extends Aggregation 12f1812f0bSAndreas Gohr{ 13f1812f0bSAndreas Gohr /** 14f1812f0bSAndreas Gohr * Render the filter form. 15f1812f0bSAndreas Gohr * Reuses the structure of advanced search tools to leverage 16f1812f0bSAndreas Gohr * the core grouping styles and scripts. 17f1812f0bSAndreas Gohr * 18f1812f0bSAndreas Gohr * @param bool $showNotFound Inherited from parent method 19f1812f0bSAndreas Gohr * @return void 20f1812f0bSAndreas Gohr */ 21f1812f0bSAndreas Gohr public function render($showNotFound = false) 22f1812f0bSAndreas Gohr { 23*267f1164SAndreas Gohr $colValues = $this->getAllColumnValues($this->searchConfig->getResult()->getRows()); 24f1812f0bSAndreas Gohr 25f1812f0bSAndreas Gohr // column dropdowns 26bea7239dSAndreas Gohr foreach ($colValues as $num => $colData) { 27bea7239dSAndreas Gohr /** @var Column $column */ 28bea7239dSAndreas Gohr $column = $colData['column']; 29457017d1SAndreas Gohr $label = $this->data['headers'][$num] ?? $colData['label']; 30f1812f0bSAndreas Gohr 31bea7239dSAndreas Gohr $this->renderer->doc .= '<details>'; 32457017d1SAndreas Gohr $this->renderer->doc .= '<summary>' . hsc($label) . '</summary>'; 33bea7239dSAndreas Gohr $this->renderer->doc .= '<ul>'; 34bea7239dSAndreas Gohr foreach ($colData['values'] as $value => $displayValue) { 350ebf3045SAndreas Gohr $current = false; 36fd9c77d3SAndreas Gohr $dyn = $this->searchConfig->getDynamicParameters(); 370ebf3045SAndreas Gohr $allFilters = $dyn->getFilters(); 380ebf3045SAndreas Gohr if (isset($allFilters[$column->getFullQualifiedLabel()])) { 390ebf3045SAndreas Gohr if ($allFilters[$column->getFullQualifiedLabel()][1] == $displayValue) { 400ebf3045SAndreas Gohr $current = true; 410ebf3045SAndreas Gohr } 420ebf3045SAndreas Gohr $dyn->removeFilter($column); // remove previous filter for this column 430ebf3045SAndreas Gohr } 440ebf3045SAndreas Gohr if (!$current) { 450ebf3045SAndreas Gohr // add new filter unless it's the current item 46fd9c77d3SAndreas Gohr $dyn->addFilter($column, '=', $displayValue); 470ebf3045SAndreas Gohr } 48fd9c77d3SAndreas Gohr $params = $dyn->getURLParameters(); 49fd9c77d3SAndreas Gohr $filter = buildURLparams($params); 50fd9c77d3SAndreas Gohr 510ebf3045SAndreas Gohr $this->renderer->doc .= '<li ' . ($current ? 'class="active"' : '') . '><div class="li">'; 52bea7239dSAndreas Gohr $column->getType()->renderTagCloudLink($value, $this->renderer, $this->mode, $this->id, $filter, 100); 53bea7239dSAndreas Gohr $this->renderer->doc .= '</div></li>'; 54f1812f0bSAndreas Gohr } 55bea7239dSAndreas Gohr $this->renderer->doc .= '</ul>'; 56bea7239dSAndreas Gohr $this->renderer->doc .= '</details>'; 57f1812f0bSAndreas Gohr } 58f1812f0bSAndreas Gohr } 59f1812f0bSAndreas Gohr 60f1812f0bSAndreas Gohr /** 61f1812f0bSAndreas Gohr * Get all values from given search result grouped by column 62f1812f0bSAndreas Gohr * 63f1812f0bSAndreas Gohr * @return array 64f1812f0bSAndreas Gohr */ 65f1812f0bSAndreas Gohr protected function getAllColumnValues($result) 66f1812f0bSAndreas Gohr { 67f1812f0bSAndreas Gohr $colValues = []; 68f1812f0bSAndreas Gohr 69f1812f0bSAndreas Gohr foreach ($result as $row) { 70f1812f0bSAndreas Gohr foreach ($row as $value) { 71f1812f0bSAndreas Gohr /** @var Value $value */ 72f1812f0bSAndreas Gohr $colName = $value->getColumn()->getFullQualifiedLabel(); 73bea7239dSAndreas Gohr $colValues[$colName]['column'] = $value->getColumn(); 74f1812f0bSAndreas Gohr $colValues[$colName]['label'] = $value->getColumn()->getTranslatedLabel(); 755e29103aSannda $colValues[$colName]['values'] ??= []; 76f1812f0bSAndreas Gohr 77bea7239dSAndreas Gohr if (empty($value->getDisplayValue())) continue; 78f1812f0bSAndreas Gohr 79bea7239dSAndreas Gohr // create an array with [value => displayValue] pairs 80bea7239dSAndreas Gohr // the cast to array will handle single and multi-value fields the same 81bea7239dSAndreas Gohr // using the full value as key will make sure we don't have duplicates 82da8d86adSAndreas Gohr // 83da8d86adSAndreas Gohr // because a value might be interpreted as integer in the array key, we pad 84da8d86adSAndreas Gohr // each key with a space at the end to enforce string keys. The space will 85da8d86adSAndreas Gohr // be ignored when parsing JSON values and trimmed for all other types. 86da8d86adSAndreas Gohr // This is a work around for #665 87da8d86adSAndreas Gohr $pairs = array_combine( 88da8d86adSAndreas Gohr array_map( 89da8d86adSAndreas Gohr static fn($v) => "$v ", 90da8d86adSAndreas Gohr (array)$value->getValue() 91da8d86adSAndreas Gohr ), 92da8d86adSAndreas Gohr (array)$value->getDisplayValue() 93da8d86adSAndreas Gohr ); 94bea7239dSAndreas Gohr $colValues[$colName]['values'] = array_merge($colValues[$colName]['values'], $pairs); 95f1812f0bSAndreas Gohr } 96f1812f0bSAndreas Gohr } 97f1812f0bSAndreas Gohr 98bea7239dSAndreas Gohr // sort by display value 99f1812f0bSAndreas Gohr array_walk($colValues, function (&$col) { 100bea7239dSAndreas Gohr Sort::asort($col['values']); 101f1812f0bSAndreas Gohr }); 102f1812f0bSAndreas Gohr 103bea7239dSAndreas Gohr return array_values($colValues); // reindex 104f1812f0bSAndreas Gohr } 105f1812f0bSAndreas Gohr} 106