1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16: class Horde_Core_Ui_TagCloud
17: {
18: 19: 20:
21: public $basefontsize = 24;
22:
23: 24: 25:
26: public $fontsizerange = 12;
27:
28: 29: 30:
31: public $css_class = 'tagcloud';
32:
33: 34: 35: 36:
37: public $size_suffix = 'px';
38:
39: 40: 41:
42: public $factor;
43:
44: 45: 46:
47: public $epoc_level = array(
48: 'earliest',
49: 'earlier',
50: 'later',
51: 'latest'
52: );
53:
54: 55: 56:
57: protected $_elements = array();
58:
59: 60: 61:
62: protected $_max = 0;
63:
64: 65: 66:
67: protected $_min = 0;
68:
69: 70: 71:
72: protected $_max_epoc;
73:
74: 75: 76:
77: protected $_min_epoc;
78:
79: 80: 81:
82: protected $_map = array();
83:
84: 85: 86: 87: 88: 89:
90: public function __construct($basefontsize = 24, $fontsizerange = 12)
91: {
92: $this->basefontsize = $basefontsize;
93: $this->minfontsize = max($this->basefontsize - $this->fontsizerange, 0);
94: $this->maxfontsize = $this->basefontsize + $this->fontsizerange;
95: }
96:
97: 98: 99: 100: 101: 102: 103: 104: 105:
106: public function addElement($name, $url ='', $count = 0, $timestamp = null,
107: $onclick = null)
108: {
109:
110: if (isset($this->_map[$name])) {
111: $i = $this->_map[$name];
112:
113: $this->_elements[$i]['count'] += $count;
114:
115:
116: if (!empty($timestamp) &&
117: $timestamp > $this->_elements[$i]['timestamp']) {
118: $this->_elements[$i]['timestamp'] = $timestamp;
119: }
120:
121:
122: $this->_elements[$i]['onclick'] = $onclick;
123: $this->elements[$i]['url'] = $url;
124: } else {
125: $i = count($this->_elements);
126: $this->_elements[$i]['name'] = $name;
127: $this->_elements[$i]['url'] = $url;
128: $this->_elements[$i]['count'] = $count;
129: $this->_elements[$i]['timestamp'] = $timestamp == null ? time() : $timestamp;
130: $this->_elements[$i]['onclick'] = $onclick;
131: $this->_map[$name] = $i;
132: }
133: }
134:
135: 136: 137: 138: 139:
140: public function addElements($tags)
141: {
142: $this->_elements = array_merge($this->_elements, $tags);
143: }
144:
145: 146: 147:
148: public function clearElements()
149: {
150: $this->_elements = array();
151: }
152:
153: 154: 155: 156: 157: 158: 159:
160: public function buildHTML($param = array())
161: {
162: return $this->_wrapDiv($this->_buidHTMLTags($param));
163: }
164:
165: 166: 167: 168: 169: 170: 171:
172: protected function _buidHTMLTags($param)
173: {
174: $this->total = count($this->_elements);
175:
176: if ($this->total == 0) {
177: return '';
178: } elseif ($this->total == 1) {
179: $tag = $this->_elements[0];
180: return $this->_createHTMLTag($tag, 'latest', $this->basefontsize);
181: }
182:
183: $limit = array_key_exists('limit', $param) ? $param['limit'] : 0;
184: $this->_sortTags($limit);
185: $this->_calcMumCount();
186: $this->_calcMumEpoc();
187:
188: $range = $this->maxfontsize - $this->minfontsize;
189: $this->factor = ($this->_max == $this->_min)
190: ? 1
191: : $range / (sqrt($this->_max) - sqrt($this->_min));
192: $this->epoc_factor = ($this->_max_epoc == $this->_min_epoc)
193: ? 1
194: : count($this->epoc_level) / (sqrt($this->_max_epoc) - sqrt($this->_min_epoc));
195: $rtn = array();
196: foreach ($this->_elements as $tag){
197: $count_lv = $this->_getCountLevel($tag['count']);
198: if (!isset($tag['timestamp']) || empty($tag['timestamp'])) {
199: $epoc_lv = count($this->epoc_level) - 1;
200: } else {
201: $epoc_lv = $this->_getEpocLevel($tag['timestamp']);
202: }
203: $color_type = $this->epoc_level[$epoc_lv];
204: $font_size = $this->minfontsize + $count_lv;
205: $rtn[] = $this->_createHTMLTag($tag, $color_type, $font_size);
206: }
207: return implode('', $rtn);
208: }
209:
210: 211: 212: 213: 214: 215: 216: 217: 218:
219: protected function _createHTMLTag($tag, $type, $fontsize)
220: {
221: return sprintf('<a style="font-size:%d%s" class="%s" href="%s"%s>%s</a>' . "\n",
222: $fontsize,
223: $this->size_suffix,
224: $type,
225: $tag['url'],
226: (empty($tag['onclick']) ? '' : ' onclick="' . $tag['onclick'] . '"'),
227: htmlspecialchars($tag['name']));
228: }
229:
230: 231: 232: 233: 234:
235: protected function _sortTags($limit = 0)
236: {
237: usort($this->_elements, array($this, 'cmpElementsName'));
238: if ($limit != 0){
239: $this->_elements = array_splice($this->_elements, 0, $limit);
240: }
241: }
242:
243: 244: 245: 246: 247:
248: public function cmpElementsName($a, $b)
249: {
250: return ($a['name'] == $b['name'])
251: ? 0
252: : (($a['name'] < $b['name']) ? -1 : 1);
253: }
254:
255: 256: 257:
258: protected function _calcMumCount()
259: {
260: foreach($this->_elements as $item){
261: $array[] = $item['count'];
262: }
263: $this->_min = min($array);
264: $this->_max = max($array);
265: }
266:
267: 268: 269:
270: protected function _calcMumEpoc()
271: {
272: foreach($this->_elements as $item){
273: $array[] = $item['timestamp'];
274: }
275: $this->_min_epoc = min($array);
276: $this->_max_epoc = max($array);
277: }
278:
279: 280: 281: 282: 283: 284: 285:
286: protected function _getCountLevel($count = 0)
287: {
288: return (int)((sqrt($count) - sqrt($this->_min)) * $this->factor);
289: }
290:
291: 292: 293: 294: 295: 296: 297:
298: protected function _getEpocLevel($timestamp = 0)
299: {
300: return (int)((sqrt($timestamp) - sqrt($this->_min_epoc)) * $this->epoc_factor);
301: }
302:
303: 304: 305: 306: 307: 308: 309:
310: protected function _wrapDiv($html)
311: {
312: return ($html == '')
313: ? ''
314: : sprintf("<div class=\"%s\">\n%s</div>\n", $this->css_class, $html);
315: }
316:
317: }
318: