1<?php 2 3namespace dokuwiki\plugin\struct\meta; 4 5use dokuwiki\Form\Form; 6use dokuwiki\Utf8\Sort; 7 8/** 9 * Struct filter class 10 */ 11class AggregationFilter extends Aggregation 12{ 13 /** 14 * Render the filter form. 15 * Reuses the structure of advanced search tools to leverage 16 * the core grouping styles and scripts. 17 * 18 * @param bool $showNotFound Inherited from parent method 19 * @return void 20 */ 21 public function render($showNotFound = false) 22 { 23 $schemas = $this->searchConfig->getSchemas(); 24 $schema = $schemas[0]->getTable(); 25 26 $colValues = $this->getAllColumnValues($this->result); 27 28 $form = new Form(['method' => 'get'], true); 29 $form->addClass('struct-filter-form search-results-form'); 30 $form->setHiddenField('id', getID()); 31 32 $form->addFieldsetOpen()->addClass('struct-filter-form search-form'); 33 $form->addHTML('<legend>' . $this->helper->getLang('filter_title') . '</legend>'); 34 35 $form->addTagOpen('div') 36 ->addClass('advancedOptions'); 37 38 // column dropdowns 39 $num = 0; 40 foreach ($colValues as $colName => $colData) { 41 $qualifiedColName = $colName[0] !== '%' ? "$schema.$colName" : $colName; 42 43 $form->addTagOpen('div') 44 ->addClass('toggle') 45 ->id("__filter-$colName") 46 ->attr('aria-haspopup', 'true'); 47 48 // popup toggler uses header if defined in syntax, otherwise label 49 $header = $colData['label']; 50 if (!empty($this->data['headers'][$num])) { 51 $header = $this->data['headers'][$num]; 52 } 53 $form->addTagOpen('div')->addClass('current'); 54 $form->addHTML($header); 55 $form->addTagClose('div'); 56 57 $form->addTagOpen('ul')->attr('aria-expanded', 'false'); 58 59 $i = 0; 60 foreach ($colData['values'] as $value) { 61 $form->addTagOpen('li'); 62 $form->addRadioButton(SearchConfigParameters::$PARAM_FILTER . "[$qualifiedColName*~]") 63 ->val($value) 64 ->id("__$schema.$colName-" . $i); 65 $form->addLabel($value, "__$schema.$colName-" . $i) 66 ->attr('title', $value); 67 $form->addTagClose('li'); 68 $i++; 69 } 70 71 $form->addTagClose('ul'); 72 $form->addTagClose('div'); // close div.toggle 73 $num++; 74 } 75 76 $form->addButton('struct-filter-submit', $this->helper->getLang('filter_button')) 77 ->attr('type', 'submit') 78 ->addClass('struct-filter-submit'); 79 80 $form->addTagClose('div'); // close div.advancedOptions 81 $form->addFieldsetClose(); 82 83 $this->renderer->doc .= $form->toHTML(); 84 } 85 86 /** 87 * Get all values from given search result grouped by column 88 * 89 * @return array 90 */ 91 protected function getAllColumnValues($result) 92 { 93 $colValues = []; 94 95 foreach ($result as $row) { 96 foreach ($row as $value) { 97 /** @var Value $value */ 98 $colName = $value->getColumn()->getFullQualifiedLabel(); 99 $colValues[$colName]['label'] = $value->getColumn()->getTranslatedLabel(); 100 $colValues[$colName]['values'] = $colValues[$colName]['values'] ?? []; 101 102 $opt = $value->getDisplayValue(); 103 104 if (empty($opt)) continue; 105 106 // handle multiple values 107 if (is_array($opt)) { 108 $colValues[$colName]['values'] = array_merge($colValues[$colName]['values'], $opt); 109 } else { 110 $colValues[$colName]['values'][] = $opt; 111 } 112 } 113 } 114 115 array_walk($colValues, function (&$col) { 116 $unique = array_unique($col['values']); 117 Sort::sort($unique); 118 $col['values'] = $unique; 119 }); 120 121 return $colValues; 122 } 123} 124