PageRenderTime 65ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/elgg/engine/lib/tags.php

https://bitbucket.org/rhizomatik/lorea_production/
PHP | 398 lines | 189 code | 76 blank | 133 comment | 27 complexity | 63c318d16b9f04180d79b8c8f4db2300 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, BSD-3-Clause, LGPL-2.1
  1. <?php
  2. /**
  3. * Elgg tags
  4. * Functions for managing tags and tag clouds.
  5. *
  6. * @package Elgg
  7. * @subpackage Core
  8. */
  9. /**
  10. * The algorithm working out the size of font based on the number of tags.
  11. * This is quick and dirty.
  12. */
  13. function calculate_tag_size($min, $max, $number_of_tags, $buckets = 6) {
  14. $delta = (($max - $min) / $buckets);
  15. $thresholds = array();
  16. for ($n=1; $n <= $buckets; $n++) {
  17. $thresholds[$n-1] = ($min + $n) * $delta;
  18. }
  19. // Correction
  20. if ($thresholds[$buckets-1]>$max) {
  21. $thresholds[$buckets-1] = $max;
  22. }
  23. $size = 0;
  24. for ($n = 0; $n < count($thresholds); $n++) {
  25. if ($number_of_tags >= $thresholds[$n]) {
  26. $size = $n;
  27. }
  28. }
  29. return $size;
  30. }
  31. /**
  32. * This function generates an array of tags with a weighting.
  33. *
  34. * @param array $tags The array of tags.
  35. * @return An associated array of tags with a weighting, this can then be mapped to a display class.
  36. */
  37. function generate_tag_cloud(array $tags, $buckets = 6) {
  38. $cloud = array();
  39. $min = 65535;
  40. $max = 0;
  41. foreach ($tags as $tag) {
  42. $cloud[$tag]++;
  43. if ($cloud[$tag]>$max) {
  44. $max = $cloud[$tag];
  45. }
  46. if ($cloud[$tag]<$min) {
  47. $min = $cloud[$tag];
  48. }
  49. }
  50. foreach ($cloud as $k => $v) {
  51. $cloud[$k] = calculate_tag_size($min, $max, $v, $buckets);
  52. }
  53. return $cloud;
  54. }
  55. /**
  56. * Get popular tags and their frequencies
  57. *
  58. * Supports similar arguments as elgg_get_entities()
  59. *
  60. *
  61. * @param array $options Array in format:
  62. *
  63. * threshold => INT minimum tag count
  64. *
  65. * tag_names => array() metadata tag names - must be registered tags
  66. *
  67. * limit => INT number of tags to return
  68. *
  69. * types => NULL|STR entity type (SQL: type = '$type')
  70. *
  71. * subtypes => NULL|STR entity subtype (SQL: subtype = '$subtype')
  72. *
  73. * type_subtype_pairs => NULL|ARR (array('type' => 'subtype')) (SQL: type = '$type' AND subtype = '$subtype') pairs
  74. *
  75. * owner_guids => NULL|INT entity guid
  76. *
  77. * container_guids => NULL|INT container_guid
  78. *
  79. * site_guids => NULL (current_site)|INT site_guid
  80. *
  81. * created_time_lower => NULL|INT Created time lower boundary in epoch time
  82. *
  83. * created_time_upper => NULL|INT Created time upper boundary in epoch time
  84. *
  85. * modified_time_lower => NULL|INT Modified time lower boundary in epoch time
  86. *
  87. * modified_time_upper => NULL|INT Modified time upper boundary in epoch time
  88. *
  89. * wheres => array() Additional where clauses to AND together
  90. *
  91. * joins => array() Additional joins
  92. *
  93. * @return false/array - if no tags or error, false
  94. * otherwise, array of objects with ->tag and ->total values
  95. * @since 1.7.1
  96. */
  97. function elgg_get_tags(array $options = array()) {
  98. global $CONFIG;
  99. $defaults = array(
  100. 'threshold' => 1,
  101. 'tag_names' => array(),
  102. 'limit' => 10,
  103. 'types' => ELGG_ENTITIES_ANY_VALUE,
  104. 'subtypes' => ELGG_ENTITIES_ANY_VALUE,
  105. 'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE,
  106. 'owner_guids' => ELGG_ENTITIES_ANY_VALUE,
  107. 'container_guids' => ELGG_ENTITIES_ANY_VALUE,
  108. 'site_guids' => $CONFIG->site_guid,
  109. 'modified_time_lower' => ELGG_ENTITIES_ANY_VALUE,
  110. 'modified_time_upper' => ELGG_ENTITIES_ANY_VALUE,
  111. 'created_time_lower' => ELGG_ENTITIES_ANY_VALUE,
  112. 'created_time_upper' => ELGG_ENTITIES_ANY_VALUE,
  113. 'joins' => array(),
  114. 'wheres' => array(),
  115. );
  116. $options = array_merge($defaults, $options);
  117. $singulars = array('type', 'subtype', 'owner_guid', 'container_guid', 'site_guid');
  118. $options = elgg_normalise_plural_options_array($options, $singulars);
  119. $registered_tags = elgg_get_registered_tag_metadata_names();
  120. if (!is_array($options['tag_names'])) {
  121. return false;
  122. }
  123. // empty array so use all registered tag names
  124. if (count($options['tag_names']) == 0) {
  125. $options['tag_names'] = $registered_tags;
  126. }
  127. $diff = array_diff($options['tag_names'], $registered_tags);
  128. if (count($diff) > 0) {
  129. elgg_deprecated_notice('Tag metadata names must be registered by elgg_register_tag_metadata_name()', 1.7);
  130. // return false;
  131. }
  132. $wheres = $options['wheres'];
  133. // catch for tags that were spaces
  134. $wheres[] = "msv.string != ''";
  135. foreach ($options['tag_names'] as $tag) {
  136. $sanitised_tags[] = '"' . sanitise_string($tag) . '"';
  137. }
  138. $tags_in = implode(',', $sanitised_tags);
  139. $wheres[] = "(msn.string IN ($tags_in))";
  140. $wheres[] = elgg_get_entity_type_subtype_where_sql('e', $options['types'], $options['subtypes'], $options['type_subtype_pairs']);
  141. $wheres[] = elgg_get_entity_site_where_sql('e', $options['site_guids']);
  142. $wheres[] = elgg_get_entity_owner_where_sql('e', $options['owner_guids']);
  143. $wheres[] = elgg_get_entity_container_where_sql('e', $options['container_guids']);
  144. $wheres[] = elgg_get_entity_time_where_sql('e', $options['created_time_upper'],
  145. $options['created_time_lower'], $options['modified_time_upper'], $options['modified_time_lower']);
  146. // remove identical where clauses
  147. $wheres = array_unique($wheres);
  148. // see if any functions failed
  149. // remove empty strings on successful functions
  150. foreach ($wheres as $i => $where) {
  151. if ($where === FALSE) {
  152. return FALSE;
  153. } elseif (empty($where)) {
  154. unset($wheres[$i]);
  155. }
  156. }
  157. $joins = $options['joins'];
  158. $joins[] = "JOIN {$CONFIG->dbprefix}metadata md on md.entity_guid = e.guid";
  159. $joins[] = "JOIN {$CONFIG->dbprefix}metastrings msv on msv.id = md.value_id";
  160. $joins[] = "JOIN {$CONFIG->dbprefix}metastrings msn on md.name_id = msn.id";
  161. // remove identical join clauses
  162. $joins = array_unique($joins);
  163. foreach ($joins as $i => $join) {
  164. if ($join === FALSE) {
  165. return FALSE;
  166. } elseif (empty($join)) {
  167. unset($joins[$i]);
  168. }
  169. }
  170. $query = "SELECT msv.string as tag, count(msv.id) as total ";
  171. $query .= "FROM {$CONFIG->dbprefix}entities e ";
  172. // add joins
  173. foreach ($joins as $j) {
  174. $query .= " $j ";
  175. }
  176. // add wheres
  177. $query .= ' WHERE ';
  178. foreach ($wheres as $w) {
  179. $query .= " $w AND ";
  180. }
  181. // Add access controls
  182. $query .= get_access_sql_suffix('e');
  183. $threshold = sanitise_int($options['threshold']);
  184. $query .= " GROUP BY msv.string HAVING total >= {$threshold} ";
  185. $query .= " ORDER BY total DESC ";
  186. $limit = sanitise_int($options['limit']);
  187. $query .= " LIMIT {$limit} ";
  188. return get_data($query);
  189. }
  190. /**
  191. * Get an array of tags with weights for use with the output/tagcloud view.
  192. *
  193. * @param int $threshold Get the threshold of minimum number of each tags to bother with (ie only show tags where there are more than $threshold occurances)
  194. * @param int $limit Number of tags to return
  195. * @param string $metadata_name Optionally, the name of the field you want to grab for
  196. * @param string $entity_type Optionally, the entity type ('object' etc)
  197. * @param string $entity_subtype The entity subtype, optionally
  198. * @param int $owner_guid The GUID of the tags owner, optionally
  199. * @param int $site_guid Optionally, the site to restrict to (default is the current site)
  200. * @param int $start_ts Optionally specify a start timestamp for tags used to generate cloud.
  201. * @param int $ent_ts Optionally specify an end timestamp for tags used to generate cloud.
  202. * @return array|false Array of objects with ->tag and ->total values, or false on failure
  203. */
  204. function get_tags($threshold = 1, $limit = 10, $metadata_name = "", $entity_type = "object", $entity_subtype = "", $owner_guid = "", $site_guid = -1, $start_ts = "", $end_ts = "") {
  205. //elgg_deprecated_notice('get_tags() has been replaced by elgg_get_tags()', 1.8);
  206. if (is_array($metadata_name)) {
  207. return false;
  208. }
  209. $options = array();
  210. if ($metadata_name === '') {
  211. $options['tag_names'] = array();
  212. } else {
  213. $options['tag_names'] = array($metadata_name);
  214. }
  215. $options['threshold'] = $threshold;
  216. $options['limit'] = $limit;
  217. // rewrite owner_guid to container_guid to emulate old functionality
  218. $container_guid = $owner_guid;
  219. if ($container_guid) {
  220. $options['container_guids'] = $container_guid;
  221. }
  222. if ($entity_type) {
  223. $options['type'] = $entity_type;
  224. }
  225. if ($entity_subtype) {
  226. $options['subtype'] = $entity_subtype;
  227. }
  228. if ($site_guid != -1) {
  229. $options['site_guids'] = $site_guid;
  230. }
  231. if ($end_ts) {
  232. $options['created_time_upper'] = $end_ts;
  233. }
  234. if ($start_ts) {
  235. $options['created_time_lower'] = $start_ts;
  236. }
  237. $r = elgg_get_tags($options);
  238. return $r;
  239. }
  240. /**
  241. * Returns viewable tagcloud
  242. *
  243. *
  244. * @see elgg_get_tags
  245. *
  246. * @param array $options Any elgg_get_tags() options except:
  247. *
  248. * type => must be single entity type
  249. *
  250. * subtype => must be single entity subtype
  251. *
  252. * @return string
  253. * @since 1.7.1
  254. */
  255. function elgg_view_tagcloud(array $options = array()) {
  256. $type = $subtype = '';
  257. if (isset($options['type'])) {
  258. $type = $options['type'];
  259. }
  260. if (isset($options['subtype'])) {
  261. $subtype = $options['subtype'];
  262. }
  263. $tag_data = elgg_get_tags($options);
  264. return elgg_view("output/tagcloud",array('value' => $tag_data,
  265. 'type' => $type,
  266. 'container_guid' => $options['container_guid'],
  267. 'subtype' => $subtype));
  268. }
  269. /**
  270. * Loads and displays a tagcloud given particular criteria.
  271. *
  272. * @param int $threshold Get the threshold of minimum number of each tags to bother with (ie only show tags where there are more than $threshold occurances)
  273. * @param int $limit Number of tags to return
  274. * @param string $metadata_name Optionally, the name of the field you want to grab for
  275. * @param string $entity_type Optionally, the entity type ('object' etc)
  276. * @param string $entity_subtype The entity subtype, optionally
  277. * @param int $owner_guid The GUID of the tags owner, optionally
  278. * @param int $site_guid Optionally, the site to restrict to (default is the current site)
  279. * @param int $start_ts Optionally specify a start timestamp for tags used to generate cloud.
  280. * @param int $ent_ts Optionally specify an end timestamp for tags used to generate cloud.
  281. * @return string The HTML (or other, depending on view type) of the tagcloud.
  282. */
  283. function display_tagcloud($threshold = 1, $limit = 10, $metadata_name = "", $entity_type = "object", $entity_subtype = "", $owner_guid = "", $site_guid = -1, $start_ts = "", $end_ts = "") {
  284. //elgg_deprecated_notice('display_cloud() was deprecated by elgg_view_tagcloud()!', 1.8);
  285. return elgg_view("output/tagcloud",array('value' => get_tags($threshold, $limit, $metadata_name, $entity_type, $entity_subtype, $owner_guid, $site_guid, $start_ts, $end_ts),
  286. 'type' => $entity_type,
  287. 'container_guids' => $owner_guid,
  288. 'subtype' => $entity_subtype));
  289. }
  290. /**
  291. * Registers a metadata name as containing tags for an entity.
  292. * This is required if you are using a non-standard metadata name
  293. * for your tags.
  294. *
  295. *
  296. * @param string $name
  297. * @return bool
  298. * @since 1.7.0
  299. */
  300. function elgg_register_tag_metadata_name($name) {
  301. global $CONFIG;
  302. if (!isset($CONFIG->registered_tag_metadata_names)) {
  303. $CONFIG->registered_tag_metadata_names = array();
  304. }
  305. if (!in_array($name, $CONFIG->registered_tag_metadata_names)) {
  306. $CONFIG->registered_tag_metadata_names[] = $name;
  307. }
  308. return TRUE;
  309. }
  310. /**
  311. * Returns an array of valid metadata names for tags.
  312. *
  313. * @return array
  314. * @since 1.7.0
  315. */
  316. function elgg_get_registered_tag_metadata_names() {
  317. global $CONFIG;
  318. $names = (isset($CONFIG->registered_tag_metadata_names)) ? $CONFIG->registered_tag_metadata_names : array();
  319. return $names;
  320. }
  321. // register the standard tags metadata name
  322. elgg_register_tag_metadata_name('tags');