1fa04b28cSMichael Grosse<?php 25282d027SMichael Grosse 3fa04b28cSMichael Grossenamespace dokuwiki\plugin\struct\meta; 45282d027SMichael Grosse 5*d6d97f60SAnna Dabrowskaclass AggregationCloud 6*d6d97f60SAnna Dabrowska{ 75282d027SMichael Grosse 8fa04b28cSMichael Grosse /** 9fa04b28cSMichael Grosse * @var string the page id of the page this is rendered to 10fa04b28cSMichael Grosse */ 11fa04b28cSMichael Grosse protected $id; 125282d027SMichael Grosse 13fa04b28cSMichael Grosse /** 14fa04b28cSMichael Grosse * @var string the Type of renderer used 15fa04b28cSMichael Grosse */ 16fa04b28cSMichael Grosse protected $mode; 175282d027SMichael Grosse 18fa04b28cSMichael Grosse /** 19fa04b28cSMichael Grosse * @var \Doku_Renderer the DokuWiki renderer used to create the output 20fa04b28cSMichael Grosse */ 21fa04b28cSMichael Grosse protected $renderer; 225282d027SMichael Grosse 23fa04b28cSMichael Grosse /** 24fa04b28cSMichael Grosse * @var SearchConfig the configured search - gives access to columns etc. 25fa04b28cSMichael Grosse */ 26fa04b28cSMichael Grosse protected $searchConfig; 275282d027SMichael Grosse 28fa04b28cSMichael Grosse /** 29fa04b28cSMichael Grosse * @var Column[] the list of columns to be displayed 30fa04b28cSMichael Grosse */ 31fa04b28cSMichael Grosse protected $columns; 325282d027SMichael Grosse 33fa04b28cSMichael Grosse /** 34fa04b28cSMichael Grosse * @var Value[][] the search result 35fa04b28cSMichael Grosse */ 36fa04b28cSMichael Grosse protected $result; 375282d027SMichael Grosse 38fa04b28cSMichael Grosse /** 39fa04b28cSMichael Grosse * @var int number of all results 40fa04b28cSMichael Grosse */ 41fa04b28cSMichael Grosse protected $resultCount; 425282d027SMichael Grosse 43fa04b28cSMichael Grosse /** 44fa04b28cSMichael Grosse * Initialize the Aggregation renderer and executes the search 45fa04b28cSMichael Grosse * 46fa04b28cSMichael Grosse * You need to call @see render() on the resulting object. 47fa04b28cSMichael Grosse * 48fa04b28cSMichael Grosse * @param string $id 49fa04b28cSMichael Grosse * @param string $mode 50fa04b28cSMichael Grosse * @param \Doku_Renderer $renderer 51fa04b28cSMichael Grosse * @param SearchConfig $searchConfig 52fa04b28cSMichael Grosse */ 53*d6d97f60SAnna Dabrowska public function __construct($id, $mode, \Doku_Renderer $renderer, SearchCloud $searchConfig) 54*d6d97f60SAnna Dabrowska { 55fa04b28cSMichael Grosse $this->id = $id; 56fa04b28cSMichael Grosse $this->mode = $mode; 57fa04b28cSMichael Grosse $this->renderer = $renderer; 58fa04b28cSMichael Grosse $this->searchConfig = $searchConfig; 59fa04b28cSMichael Grosse $this->data = $searchConfig->getConf(); 60fa04b28cSMichael Grosse $this->columns = $searchConfig->getColumns(); 610699ff47SMichael Grosse $this->result = $this->searchConfig->execute(); 620699ff47SMichael Grosse $this->resultCount = $this->searchConfig->getCount(); 63aafac1c1SMichael Grosse 64aafac1c1SMichael Grosse $this->max = $this->result[0]['count']; 65aafac1c1SMichael Grosse $this->min = end($this->result)['count']; 66fa04b28cSMichael Grosse } 67fa04b28cSMichael Grosse 68fa04b28cSMichael Grosse /** 699e7e1786SMichael Grosse * Create the cloud on the renderer 70fa04b28cSMichael Grosse */ 71*d6d97f60SAnna Dabrowska public function render() 72*d6d97f60SAnna Dabrowska { 738b4531cfSMichael Grosse 748b4531cfSMichael Grosse $this->sortResults(); 758b4531cfSMichael Grosse 76fa04b28cSMichael Grosse $this->startScope(); 77c7dd6b6aSMichael Grosse $this->startList(); 78fa04b28cSMichael Grosse foreach ($this->result as $result) { 7933bd00e9SMichael Grosse $this->renderTag($result); 80fa04b28cSMichael Grosse } 81c7dd6b6aSMichael Grosse $this->finishList(); 82fa04b28cSMichael Grosse $this->finishScope(); 83fa04b28cSMichael Grosse return; 84fa04b28cSMichael Grosse } 855282d027SMichael Grosse 86fa04b28cSMichael Grosse /** 87fa04b28cSMichael Grosse * Adds additional info to document and renderer in XHTML mode 88fa04b28cSMichael Grosse * 89fa04b28cSMichael Grosse * @see finishScope() 90fa04b28cSMichael Grosse */ 91*d6d97f60SAnna Dabrowska protected function startScope() 92*d6d97f60SAnna Dabrowska { 93fa04b28cSMichael Grosse // wrapping div 94fa04b28cSMichael Grosse if ($this->mode != 'xhtml') return; 95be2ae900SMichael Grosse $this->renderer->doc .= "<div class=\"structcloud\">"; 96fa04b28cSMichael Grosse } 975282d027SMichael Grosse 98fa04b28cSMichael Grosse /** 99fa04b28cSMichael Grosse * Closes the table and anything opened in startScope() 100fa04b28cSMichael Grosse * 101fa04b28cSMichael Grosse * @see startScope() 102fa04b28cSMichael Grosse */ 103*d6d97f60SAnna Dabrowska protected function finishScope() 104*d6d97f60SAnna Dabrowska { 105fa04b28cSMichael Grosse // wrapping div 106fa04b28cSMichael Grosse if ($this->mode != 'xhtml') return; 107fa04b28cSMichael Grosse $this->renderer->doc .= '</div>'; 108fa04b28cSMichael Grosse } 109aafac1c1SMichael Grosse 11033bd00e9SMichael Grosse /** 11133bd00e9SMichael Grosse * Render a tag of the cloud 11233bd00e9SMichael Grosse * 11333bd00e9SMichael Grosse * @param ['tag' => Value, 'count' => int] $result 11433bd00e9SMichael Grosse */ 115*d6d97f60SAnna Dabrowska protected function renderTag($result) 116*d6d97f60SAnna Dabrowska { 117fa04b28cSMichael Grosse /** 118fa04b28cSMichael Grosse * @var Value $value 119fa04b28cSMichael Grosse */ 120fa04b28cSMichael Grosse $value = $result['tag']; 121fa04b28cSMichael Grosse $count = $result['count']; 122fa04b28cSMichael Grosse if ($value->isEmpty()) { 123fa04b28cSMichael Grosse return; 124fa04b28cSMichael Grosse } 125fa04b28cSMichael Grosse 126c7dd6b6aSMichael Grosse $type = strtolower($value->getColumn()->getType()->getClass()); 127c7dd6b6aSMichael Grosse $weight = $this->getWeight($count, $this->min, $this->max); 1288e54e6f4SMichael Grosse 12985edf4f2SMichael Grosse if (!empty($this->data['target'])) { 13085edf4f2SMichael Grosse $target = $this->data['target']; 13185edf4f2SMichael Grosse } else { 13285edf4f2SMichael Grosse global $INFO; 13385edf4f2SMichael Grosse $target = $INFO['id']; 13485edf4f2SMichael Grosse } 1358e54e6f4SMichael Grosse 136ce8676aeSMichael Grosse $tagValue = $value->getDisplayValue(); 137ce8676aeSMichael Grosse if (is_array($tagValue)) { 138ce8676aeSMichael Grosse $tagValue = $tagValue[0]; 139fa04b28cSMichael Grosse } 14057775e30SSzymon Olewniczak $key = $value->getColumn()->getFullQualifiedLabel() . '='; 14143d76406SSzymon Olewniczak $filter = SearchConfigParameters::$PARAM_FILTER . '[' . urlencode($key) . ']=' . urlencode($tagValue); 142c7dd6b6aSMichael Grosse 143da11327aSMichael Grosse $this->renderer->listitem_open(1); 144da11327aSMichael Grosse $this->renderer->listcontent_open(); 145da11327aSMichael Grosse 146262c0fc6SMichael Grosse if ($this->mode == 'xhtml') { 147c7dd6b6aSMichael Grosse $this->renderer->doc .= "<div style='font-size:$weight%' data-count='$count' class='cloudtag struct_$type'>"; 1488e54e6f4SMichael Grosse } 1498e54e6f4SMichael Grosse 150262c0fc6SMichael Grosse $value->renderAsTagCloudLink($this->renderer, $this->mode, $target, $filter, $weight); 151262c0fc6SMichael Grosse 152262c0fc6SMichael Grosse if ($this->mode == 'xhtml') { 153c7dd6b6aSMichael Grosse $this->renderer->doc .= '</div>'; 154fa04b28cSMichael Grosse } 155da11327aSMichael Grosse 156da11327aSMichael Grosse $this->renderer->listcontent_close(); 157da11327aSMichael Grosse $this->renderer->listitem_close(); 158262c0fc6SMichael Grosse } 159aafac1c1SMichael Grosse 160aafac1c1SMichael Grosse /** 161aafac1c1SMichael Grosse * This interpolates the weight between 70 and 150 based on $min, $max and $current 162aafac1c1SMichael Grosse * 163aafac1c1SMichael Grosse * @param int $current 164aafac1c1SMichael Grosse * @param int $min 165aafac1c1SMichael Grosse * @param int $max 1668e54e6f4SMichael Grosse * @return int 167aafac1c1SMichael Grosse */ 168*d6d97f60SAnna Dabrowska protected function getWeight($current, $min, $max) 169*d6d97f60SAnna Dabrowska { 170aafac1c1SMichael Grosse if ($min == $max) { 171aafac1c1SMichael Grosse return 100; 172aafac1c1SMichael Grosse } 1738e54e6f4SMichael Grosse return round(($current - $min) / ($max - $min) * 80 + 70); 174aafac1c1SMichael Grosse } 1758b4531cfSMichael Grosse 1768b4531cfSMichael Grosse /** 1778b4531cfSMichael Grosse * Sort the list of results 1788b4531cfSMichael Grosse */ 179*d6d97f60SAnna Dabrowska protected function sortResults() 180*d6d97f60SAnna Dabrowska { 1818b4531cfSMichael Grosse usort($this->result, function ($a, $b) { 182d560ea13SMichael Grosse $asort = $a['tag']->getColumn()->getType()->getSortString($a['tag']); 183d560ea13SMichael Grosse $bsort = $b['tag']->getColumn()->getType()->getSortString($b['tag']); 184d560ea13SMichael Grosse if ($asort < $bsort) { 1858b4531cfSMichael Grosse return -1; 1868b4531cfSMichael Grosse } 187d560ea13SMichael Grosse if ($asort > $bsort) { 1888b4531cfSMichael Grosse return 1; 1898b4531cfSMichael Grosse } 1908b4531cfSMichael Grosse return 0; 1918b4531cfSMichael Grosse }); 1928b4531cfSMichael Grosse } 1938b4531cfSMichael Grosse 194*d6d97f60SAnna Dabrowska protected function startList() 195*d6d97f60SAnna Dabrowska { 196c7dd6b6aSMichael Grosse $this->renderer->listu_open(); 197c7dd6b6aSMichael Grosse } 198c7dd6b6aSMichael Grosse 199*d6d97f60SAnna Dabrowska protected function finishList() 200*d6d97f60SAnna Dabrowska { 201c7dd6b6aSMichael Grosse $this->renderer->listu_close(); 202c7dd6b6aSMichael Grosse } 203fa04b28cSMichael Grosse} 204