1<?php 2 3namespace dokuwiki\plugin\struct\meta; 4 5class AggregationCloud extends Aggregation 6{ 7 /** @var int */ 8 protected $max; 9 10 /** @var int */ 11 protected $min; 12 13 /** 14 * Initialize the Aggregation renderer and executes the search 15 * 16 * You need to call @param string $id 17 * @param string $mode 18 * @param \Doku_Renderer $renderer 19 * @param SearchConfig $searchConfig 20 * @see render() on the resulting object. 21 * 22 */ 23 public function __construct($id, $mode, \Doku_Renderer $renderer, SearchCloud $searchConfig) 24 { 25 parent::__construct($id, $mode, $renderer, $searchConfig); 26 27 $this->max = $this->result[0]['count']; 28 $this->min = end($this->result)['count']; 29 } 30 31 /** @inheritdoc */ 32 public function render($showNotFound = false) 33 { 34 $this->sortResults(); 35 $this->startList(); 36 foreach ($this->result as $result) { 37 $this->renderTag($result); 38 } 39 $this->finishList(); 40 } 41 42 /** 43 * Render a tag of the cloud 44 * 45 * @param ['tag' => Value, 'count' => int] $result 46 */ 47 protected function renderTag($result) 48 { 49 /** 50 * @var Value $value 51 */ 52 $value = $result['tag']; 53 $count = $result['count']; 54 if ($value->isEmpty()) { 55 return; 56 } 57 58 $type = strtolower($value->getColumn()->getType()->getClass()); 59 $weight = $this->getWeight($count, $this->min, $this->max); 60 61 if (!empty($this->data['target'])) { 62 $target = $this->data['target']; 63 } else { 64 global $INFO; 65 $target = $INFO['id']; 66 } 67 68 $tagValue = $value->getDisplayValue(); 69 if (is_array($tagValue)) { 70 $tagValue = $tagValue[0]; 71 } 72 $key = $value->getColumn()->getFullQualifiedLabel() . '='; 73 $filter = SearchConfigParameters::$PARAM_FILTER . '[' . urlencode($key) . ']=' . urlencode($tagValue); 74 75 $this->renderer->listitem_open(1); 76 $this->renderer->listcontent_open(); 77 78 if ($this->mode == 'xhtml') { 79 $this->renderer->doc .= 80 "<div style='font-size:$weight%' data-count='$count' class='cloudtag struct_$type'>"; 81 } 82 83 $value->renderAsTagCloudLink($this->renderer, $this->mode, $target, $filter, $weight); 84 85 if ($this->mode == 'xhtml') { 86 $this->renderer->doc .= '</div>'; 87 } 88 89 $this->renderer->listcontent_close(); 90 $this->renderer->listitem_close(); 91 } 92 93 /** 94 * This interpolates the weight between 70 and 150 based on $min, $max and $current 95 * 96 * @param int $current 97 * @param int $min 98 * @param int $max 99 * @return int 100 */ 101 protected function getWeight($current, $min, $max) 102 { 103 if ($min == $max) { 104 return 100; 105 } 106 return round(($current - $min) / ($max - $min) * 80 + 70); 107 } 108 109 /** 110 * Sort the list of results 111 */ 112 protected function sortResults() 113 { 114 usort($this->result, function ($a, $b) { 115 $asort = $a['tag']->getColumn()->getType()->getSortString($a['tag']); 116 $bsort = $b['tag']->getColumn()->getType()->getSortString($b['tag']); 117 if ($asort < $bsort) { 118 return -1; 119 } 120 if ($asort > $bsort) { 121 return 1; 122 } 123 return 0; 124 }); 125 } 126 127 protected function startList() 128 { 129 $this->renderer->listu_open(); 130 } 131 132 protected function finishList() 133 { 134 $this->renderer->listu_close(); 135 } 136} 137