1<?php 2 3namespace dokuwiki\plugin\struct\meta; 4 5class AggregationCloud 6{ 7 /** 8 * @var string the page id of the page this is rendered to 9 */ 10 protected $id; 11 12 /** 13 * @var string the Type of renderer used 14 */ 15 protected $mode; 16 17 /** 18 * @var \Doku_Renderer the DokuWiki renderer used to create the output 19 */ 20 protected $renderer; 21 22 /** 23 * @var SearchConfig the configured search - gives access to columns etc. 24 */ 25 protected $searchConfig; 26 27 /** 28 * @var Column[] the list of columns to be displayed 29 */ 30 protected $columns; 31 32 /** 33 * @var Value[][] the search result 34 */ 35 protected $result; 36 37 /** 38 * @var int number of all results 39 */ 40 protected $resultCount; 41 42 /** 43 * Initialize the Aggregation renderer and executes the search 44 * 45 * You need to call @param string $id 46 * @param string $mode 47 * @param \Doku_Renderer $renderer 48 * @param SearchConfig $searchConfig 49 * @see render() on the resulting object. 50 * 51 */ 52 public function __construct($id, $mode, \Doku_Renderer $renderer, SearchCloud $searchConfig) 53 { 54 $this->id = $id; 55 $this->mode = $mode; 56 $this->renderer = $renderer; 57 $this->searchConfig = $searchConfig; 58 $this->data = $searchConfig->getConf(); 59 $this->columns = $searchConfig->getColumns(); 60 $this->result = $this->searchConfig->execute(); 61 $this->resultCount = $this->searchConfig->getCount(); 62 63 $this->max = $this->result[0]['count']; 64 $this->min = end($this->result)['count']; 65 } 66 67 /** 68 * Create the cloud on the renderer 69 */ 70 public function render() 71 { 72 73 $this->sortResults(); 74 75 $this->startScope(); 76 $this->startList(); 77 foreach ($this->result as $result) { 78 $this->renderTag($result); 79 } 80 $this->finishList(); 81 $this->finishScope(); 82 return; 83 } 84 85 /** 86 * Adds additional info to document and renderer in XHTML mode 87 * 88 * @see finishScope() 89 */ 90 protected function startScope() 91 { 92 // wrapping div 93 if ($this->mode != 'xhtml') return; 94 $this->renderer->doc .= "<div class=\"structcloud\">"; 95 } 96 97 /** 98 * Closes the table and anything opened in startScope() 99 * 100 * @see startScope() 101 */ 102 protected function finishScope() 103 { 104 // wrapping div 105 if ($this->mode != 'xhtml') return; 106 $this->renderer->doc .= '</div>'; 107 } 108 109 /** 110 * Render a tag of the cloud 111 * 112 * @param ['tag' => Value, 'count' => int] $result 113 */ 114 protected function renderTag($result) 115 { 116 /** 117 * @var Value $value 118 */ 119 $value = $result['tag']; 120 $count = $result['count']; 121 if ($value->isEmpty()) { 122 return; 123 } 124 125 $type = strtolower($value->getColumn()->getType()->getClass()); 126 $weight = $this->getWeight($count, $this->min, $this->max); 127 128 if (!empty($this->data['target'])) { 129 $target = $this->data['target']; 130 } else { 131 global $INFO; 132 $target = $INFO['id']; 133 } 134 135 $tagValue = $value->getDisplayValue(); 136 if (is_array($tagValue)) { 137 $tagValue = $tagValue[0]; 138 } 139 $key = $value->getColumn()->getFullQualifiedLabel() . '='; 140 $filter = SearchConfigParameters::$PARAM_FILTER . '[' . urlencode($key) . ']=' . urlencode($tagValue); 141 142 $this->renderer->listitem_open(1); 143 $this->renderer->listcontent_open(); 144 145 if ($this->mode == 'xhtml') { 146 $this->renderer->doc .= 147 "<div style='font-size:$weight%' data-count='$count' class='cloudtag struct_$type'>"; 148 } 149 150 $value->renderAsTagCloudLink($this->renderer, $this->mode, $target, $filter, $weight); 151 152 if ($this->mode == 'xhtml') { 153 $this->renderer->doc .= '</div>'; 154 } 155 156 $this->renderer->listcontent_close(); 157 $this->renderer->listitem_close(); 158 } 159 160 /** 161 * This interpolates the weight between 70 and 150 based on $min, $max and $current 162 * 163 * @param int $current 164 * @param int $min 165 * @param int $max 166 * @return int 167 */ 168 protected function getWeight($current, $min, $max) 169 { 170 if ($min == $max) { 171 return 100; 172 } 173 return round(($current - $min) / ($max - $min) * 80 + 70); 174 } 175 176 /** 177 * Sort the list of results 178 */ 179 protected function sortResults() 180 { 181 usort($this->result, function ($a, $b) { 182 $asort = $a['tag']->getColumn()->getType()->getSortString($a['tag']); 183 $bsort = $b['tag']->getColumn()->getType()->getSortString($b['tag']); 184 if ($asort < $bsort) { 185 return -1; 186 } 187 if ($asort > $bsort) { 188 return 1; 189 } 190 return 0; 191 }); 192 } 193 194 protected function startList() 195 { 196 $this->renderer->listu_open(); 197 } 198 199 protected function finishList() 200 { 201 $this->renderer->listu_close(); 202 } 203} 204