PageRenderTime 50ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/horde-3.3.13/lib/Horde/UI/TagCloud.php

#
PHP | 326 lines | 143 code | 32 blank | 151 comment | 16 complexity | 6df02ea6507d1a9014530226325a547d MD5 | raw file
Possible License(s): LGPL-2.0
  1. <?php
  2. /**
  3. * Horde_UI_TagCloud:: for creating and displaying tag clouds.
  4. *
  5. * Based on a striped down version of Pear's HTML_TagCloud
  6. *
  7. * $Horde: framework/UI/UI/TagCloud.php,v 1.9.2.2 2008/01/20 21:20:43 mrubinsk Exp $
  8. *
  9. * @since Horde 3.2
  10. * @package Horde
  11. */
  12. class Horde_UI_TagCloud {
  13. /**
  14. * @var array
  15. */
  16. var $_elements = array();
  17. /**
  18. * @var int
  19. * @access public
  20. */
  21. var $basefontsize = 24;
  22. /**
  23. * @var int
  24. */
  25. var $fontsizerange = 12;
  26. /**
  27. * @var int
  28. */
  29. var $_max = 0;
  30. /**
  31. * @var int
  32. */
  33. var $_min = 0;
  34. /**
  35. * @var int
  36. */
  37. var $_max_epoc;
  38. /**
  39. * @var int
  40. */
  41. var $_min_epoc;
  42. /**
  43. * @var string
  44. */
  45. var $css_class = 'tagcloud';
  46. /**
  47. * @var string
  48. * mm,cm,in,pt,pc,px,em
  49. */
  50. var $size_suffix = 'px';
  51. /**
  52. * @var int
  53. */
  54. var $factor;
  55. /**
  56. * @var array
  57. */
  58. var $epoc_level = array(
  59. 'earliest',
  60. 'earlier',
  61. 'later',
  62. 'latest'
  63. );
  64. /**
  65. * @var array
  66. */
  67. var $_map = array();
  68. /**
  69. * Class constructor
  70. *
  71. * @param int $basefontsize base font size of output tag (option)
  72. * @param int $fontsizerange font size range
  73. * @access public
  74. */
  75. function Horde_UI_TagCloud($basefontsize = 24, $fontsizerange = 12)
  76. {
  77. $this->basefontsize = $basefontsize;
  78. $this->minfontsize = ($this->basefontsize - $this->fontsizerange > 0) ? $this->basefontsize - $this->fontsizerange : 0;
  79. $this->maxfontsize = $this->basefontsize + $this->fontsizerange;
  80. }
  81. /**
  82. * add a Tag Element to build Tag Cloud
  83. *
  84. * @return void
  85. * @param string $tag
  86. * @param string $url
  87. * @param int $count
  88. * @param int $timestamp unixtimestamp
  89. * @param string $onclick javascript onclick event handler
  90. *
  91. * @access public
  92. */
  93. function addElement($name, $url ='', $count = 0, $timestamp = null,
  94. $onclick = null)
  95. {
  96. if (isset($this->_map[$name])) {
  97. $i = $this->_map[$name];
  98. // Increase the count
  99. $this->_elements[$i]['count'] += $count;
  100. // Keep the latest timestamp
  101. if (!empty($timestamp) &&
  102. $timestamp > $this->_elements[$i]['timestamp']) {
  103. $this->_elements[$i]['timestamp'] = $timestamp;
  104. }
  105. // For onclick and url we will simply overwrite the existing values
  106. // instead of checking if they are empty, then overwriting.
  107. $this->_elements[$i]['onclick'] = $onclick;
  108. $this->elements[$i]['url'] = $url;
  109. } else {
  110. $i = count($this->_elements);
  111. $this->_elements[$i]['name'] = $name;
  112. $this->_elements[$i]['url'] = $url;
  113. $this->_elements[$i]['count'] = $count;
  114. $this->_elements[$i]['timestamp'] = $timestamp == null ? time() : $timestamp;
  115. $this->_elements[$i]['onclick'] = $onclick;
  116. $this->_map[$name] = $i;
  117. }
  118. }
  119. /**
  120. * add a Tag Element to build Tag Cloud
  121. *
  122. * @return void
  123. * @param array $tags Associative array to $this->_elements
  124. * @access public
  125. */
  126. function addElements($tags)
  127. {
  128. $this->_elements = array_merge($this->_elements, $tags);
  129. }
  130. /**
  131. * clear Tag Elements
  132. *
  133. * @access public
  134. */
  135. function clearElements()
  136. {
  137. $this->_elements = array();
  138. }
  139. /**
  140. * build HTML part
  141. *
  142. * @return string HTML
  143. * @param array $param 'limit' => int limit of generation tag num.
  144. * @access public
  145. */
  146. function buildHTML($param = array())
  147. {
  148. return $this->_wrapDiv($this->_buidHTMLTags($param));
  149. }
  150. /**
  151. * calc Tag level and create whole HTML of each Tags
  152. *
  153. * @return string HTML
  154. * @param array $param limit of Tag Number
  155. * @access private
  156. */
  157. function _buidHTMLTags($param)
  158. {
  159. $this->total = count($this->_elements);
  160. // no tags elements
  161. if ($this->total == 0) {
  162. return '';
  163. } elseif ($this->total == 1) {
  164. $tag = $this->_elements[0];
  165. return $this->_createHTMLTag($tag, 'latest', $this->basefontsize);
  166. }
  167. $limit = array_key_exists('limit', $param) ? $param['limit'] : 0;
  168. $this->_sortTags($limit);
  169. $this->_calcMumCount();
  170. $this->_calcMumEpoc();
  171. $range = $this->maxfontsize - $this->minfontsize;
  172. $this->factor = $this->_max == $this->_min ? 1
  173. : $range / (sqrt($this->_max) - sqrt($this->_min));
  174. $this->epoc_factor = $this->_max_epoc == $this->_min_epoc ? 1
  175. : count($this->epoc_level) / (sqrt($this->_max_epoc) - sqrt($this->_min_epoc));
  176. $rtn = array();
  177. foreach ($this->_elements as $tag){
  178. $count_lv = $this->_getCountLevel($tag['count']);
  179. if(! isset($tag['timestamp']) || empty($tag['timestamp'])){
  180. $epoc_lv = count($this->epoc_level) - 1;
  181. }else{
  182. $epoc_lv = $this->_getEpocLevel($tag['timestamp']);
  183. }
  184. $color_type = $this->epoc_level[$epoc_lv];
  185. $font_size = $this->minfontsize + $count_lv;
  186. $rtn[] = $this->_createHTMLTag($tag, $color_type, $font_size);
  187. }
  188. return implode("", $rtn);
  189. }
  190. /**
  191. * create a Element of HTML part
  192. *
  193. * @return string a Element of Tag HTML
  194. * @param array $tag
  195. * @param string $type css class of time line param
  196. * @param int $fontsize
  197. * @access private
  198. */
  199. function _createHTMLTag($tag, $type, $fontsize)
  200. {
  201. return sprintf("<a style=\"font-size: %d%s\" class=\"%s\" href=\"%s\" %s >%s</a>\n",
  202. $fontsize,
  203. $this->size_suffix,
  204. $type,
  205. $tag['url'],
  206. (empty($tag['onclick']) ? '' : 'onClick="' . $tag['onclick'] . '"'),
  207. htmlspecialchars($tag['name']));
  208. }
  209. /**
  210. * sort tags by name
  211. *
  212. * @return array
  213. * @param int $limit limit element number of create TagCloud
  214. * @access private
  215. */
  216. function _sortTags($limit = 0){
  217. usort($this->_elements, array(get_class($this), "_cmpElementsName"));
  218. if ($limit != 0){
  219. $this->_elements = array_splice($this->_elements, 0, $limit);
  220. }
  221. }
  222. /**
  223. * using for usort()
  224. *
  225. * @return int
  226. * @access private
  227. */
  228. function _cmpElementsName($a, $b)
  229. {
  230. if ($a['name'] == $b['name']) {
  231. return 0;
  232. }
  233. return ($a['name'] < $b['name']) ? -1 : 1;
  234. }
  235. /**
  236. * calc max and min tag count of use
  237. *
  238. * @access private
  239. */
  240. function _calcMumCount()
  241. {
  242. foreach($this->_elements as $item){
  243. $array[] = $item['count'];
  244. }
  245. $this->_min = min($array);
  246. $this->_max = max($array);
  247. }
  248. /**
  249. * calc max and min timestamp
  250. *
  251. * @access private
  252. */
  253. function _calcMumEpoc()
  254. {
  255. foreach($this->_elements as $item){
  256. $array[] = $item['timestamp'];
  257. }
  258. $this->_min_epoc = min($array);
  259. $this->_max_epoc = max($array);
  260. }
  261. /**
  262. * calc Tag Level of size
  263. *
  264. * @return int level
  265. * @param int $count
  266. * @access private
  267. */
  268. function _getCountLevel($count = 0)
  269. {
  270. return (int)(sqrt($count) - sqrt($this->_min) ) * $this->factor;
  271. }
  272. /**
  273. * calc timeline level of Tag
  274. *
  275. * @return int level of timeline
  276. * @param int $timestamp
  277. * @access private
  278. */
  279. function _getEpocLevel($timestamp = 0)
  280. {
  281. return (int)(sqrt($timestamp) - sqrt($this->_min_epoc)) * $this->epoc_factor;
  282. }
  283. /**
  284. * wrap div tag
  285. *
  286. * @return string
  287. * @param string $html
  288. * @access private
  289. */
  290. function _wrapDiv($html)
  291. {
  292. return $html == "" ? "" : sprintf("<div class=\"%s\">\n%s</div>\n", $this->css_class, $html);
  293. }
  294. }