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 @see render() on the resulting object. 46 * 47 * @param string $id 48 * @param string $mode 49 * @param \Doku_Renderer $renderer 50 * @param SearchConfig $searchConfig 51 */ 52 public function __construct($id, $mode, \Doku_Renderer $renderer, SearchCloud $searchConfig) { 53 $this->id = $id; 54 $this->mode = $mode; 55 $this->renderer = $renderer; 56 $this->searchConfig = $searchConfig; 57 $this->data = $searchConfig->getConf(); 58 $this->columns = $searchConfig->getColumns(); 59 $this->result = $this->searchConfig->execute(); 60 $this->resultCount = $this->searchConfig->getCount(); 61 62 $this->max = $this->result[0]['count']; 63 $this->min = end($this->result)['count']; 64 } 65 66 /** 67 * Create the table on the renderer 68 */ 69 public function render() { 70 $this->startScope(); 71 $this->renderer->doc .= '<ul>'; 72 foreach ($this->result as $result) { 73 $this->renderTag($result); 74 } 75 $this->renderer->doc .= '</ul>'; 76 $this->finishScope(); 77 return; 78 } 79 80 /** 81 * Adds additional info to document and renderer in XHTML mode 82 * 83 * @see finishScope() 84 */ 85 protected function startScope() { 86 // wrapping div 87 if($this->mode != 'xhtml') return; 88 $this->renderer->doc .= "<div class=\"structcloud\">"; 89 } 90 91 /** 92 * Closes the table and anything opened in startScope() 93 * 94 * @see startScope() 95 */ 96 protected function finishScope() { 97 // wrapping div 98 if($this->mode != 'xhtml') return; 99 $this->renderer->doc .= '</div>'; 100 } 101 102 /** 103 * Render a tag of the cloud 104 * 105 * @param ['tag' => Value, 'count' => int] $result 106 */ 107 protected function renderTag($result) { 108 /** 109 * @var Value $value 110 */ 111 $value = $result['tag']; 112 $count = $result['count']; 113 $weight = $this->getWeight($count, $this->min, $this->max); 114 $type = 'struct_' . strtolower($value->getColumn()->getType()->getClass()); 115 if ($value->isEmpty()) { 116 return; 117 } 118 119 $tagValue = $value->getDisplayValue(); 120 if (empty($tagValue)) { 121 $tagValue = $value->getRawValue(); 122 } 123 if (is_array($tagValue)) { 124 $tagValue = $tagValue[0]; 125 } 126 $schema = $this->data['schemas'][0][0]; 127 $col = $value->getColumn()->getLabel(); 128 $this->renderer->doc .= '<li><div class="li">'; 129 $this->renderer->doc .= "<div style='font-size:$weight%' data-count='$count' class='cloudtag $type'>"; 130 131 $this->renderer->internallink("?flt[$schema.$col*~]=" . urlencode($tagValue),$tagValue); 132 $this->renderer->doc .= '</div>'; 133 $this->renderer->doc .= '</div></li>'; 134 } 135 136 /** 137 * This interpolates the weight between 70 and 150 based on $min, $max and $current 138 * 139 * @param int $current 140 * @param int $min 141 * @param int $max 142 * @return float|int 143 */ 144 protected function getWeight($current, $min, $max) { 145 if ($min == $max) { 146 return 100; 147 } 148 return ($current - $min)/($max - $min) * 80 + 70; 149 } 150} 151