INT minimum tag count * * tag_names => array() metadata tag names - must be registered tags * * limit => INT number of tags to return (default from settings) * * types => null|STR entity type (SQL: type = '$type') * * subtypes => null|STR entity subtype (SQL: subtype IN ('subtype1', 'subtype2)) * Use ELGG_ENTITIES_NO_VALUE to match the default subtype. * Use ELGG_ENTITIES_ANY_VALUE to match any subtype. * * type_subtype_pairs => null|ARR (array('type' => 'subtype')) * array( * 'object' => array('blog', 'file'), // All objects with subtype of 'blog' or 'file' * 'user' => ELGG_ENTITY_ANY_VALUE, // All users irrespective of subtype * ); * * owner_guids => null|INT entity guid * * container_guids => null|INT container_guid * * site_guids => null (current_site)|INT site_guid * * created_time_lower => null|INT Created time lower boundary in epoch time * * created_time_upper => null|INT Created time upper boundary in epoch time * * modified_time_lower => null|INT Modified time lower boundary in epoch time * * modified_time_upper => null|INT Modified time upper boundary in epoch time * * wheres => array() Additional where clauses to AND together * * joins => array() Additional joins * * @return object[]|false If no tags or error, false * otherwise, array of objects with ->tag and ->total values * @since 1.7.1 */ function elgg_get_tags(array $options = array()) { global $CONFIG; $defaults = array( 'threshold' => 1, 'tag_names' => array(), 'limit' => elgg_get_config('default_limit'), 'types' => ELGG_ENTITIES_ANY_VALUE, 'subtypes' => ELGG_ENTITIES_ANY_VALUE, 'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE, 'owner_guids' => ELGG_ENTITIES_ANY_VALUE, 'container_guids' => ELGG_ENTITIES_ANY_VALUE, 'site_guids' => $CONFIG->site_guid, 'modified_time_lower' => ELGG_ENTITIES_ANY_VALUE, 'modified_time_upper' => ELGG_ENTITIES_ANY_VALUE, 'created_time_lower' => ELGG_ENTITIES_ANY_VALUE, 'created_time_upper' => ELGG_ENTITIES_ANY_VALUE, 'joins' => array(), 'wheres' => array(), ); $options = array_merge($defaults, $options); $singulars = array('type', 'subtype', 'owner_guid', 'container_guid', 'site_guid', 'tag_name'); $options = _elgg_normalize_plural_options_array($options, $singulars); $registered_tags = elgg_get_registered_tag_metadata_names(); if (!is_array($options['tag_names'])) { return false; } // empty array so use all registered tag names if (count($options['tag_names']) == 0) { $options['tag_names'] = $registered_tags; } $diff = array_diff($options['tag_names'], $registered_tags); if (count($diff) > 0) { elgg_deprecated_notice('Tag metadata names must be registered by elgg_register_tag_metadata_name()', 1.7); // return false; } $wheres = $options['wheres']; // catch for tags that were spaces $wheres[] = "msv.string != ''"; $sanitised_tags = array(); foreach ($options['tag_names'] as $tag) { $sanitised_tags[] = '"' . sanitise_string($tag) . '"'; } $tags_in = implode(',', $sanitised_tags); $wheres[] = "(msn.string IN ($tags_in))"; $wheres[] = _elgg_get_entity_type_subtype_where_sql('e', $options['types'], $options['subtypes'], $options['type_subtype_pairs']); $wheres[] = _elgg_get_guid_based_where_sql('e.site_guid', $options['site_guids']); $wheres[] = _elgg_get_guid_based_where_sql('e.owner_guid', $options['owner_guids']); $wheres[] = _elgg_get_guid_based_where_sql('e.container_guid', $options['container_guids']); $wheres[] = _elgg_get_entity_time_where_sql('e', $options['created_time_upper'], $options['created_time_lower'], $options['modified_time_upper'], $options['modified_time_lower']); // see if any functions failed // remove empty strings on successful functions foreach ($wheres as $i => $where) { if ($where === false) { return false; } elseif (empty($where)) { unset($wheres[$i]); } } // remove identical where clauses $wheres = array_unique($wheres); $joins = $options['joins']; $joins[] = "JOIN {$CONFIG->dbprefix}metadata md on md.entity_guid = e.guid"; $joins[] = "JOIN {$CONFIG->dbprefix}metastrings msv on msv.id = md.value_id"; $joins[] = "JOIN {$CONFIG->dbprefix}metastrings msn on md.name_id = msn.id"; // remove identical join clauses $joins = array_unique($joins); foreach ($joins as $i => $join) { if ($join === false) { return false; } elseif (empty($join)) { unset($joins[$i]); } } $query = "SELECT msv.string as tag, count(msv.id) as total "; $query .= "FROM {$CONFIG->dbprefix}entities e "; // add joins foreach ($joins as $j) { $query .= " $j "; } // add wheres $query .= ' WHERE '; foreach ($wheres as $w) { $query .= " $w AND "; } // Add access controls $query .= _elgg_get_access_where_sql(); $threshold = sanitise_int($options['threshold']); $query .= " GROUP BY msv.string HAVING total >= {$threshold} "; $query .= " ORDER BY total DESC "; $limit = sanitise_int($options['limit']); $query .= " LIMIT {$limit} "; return get_data($query); } /** * Registers a metadata name as containing tags for an entity. * This is required if you are using a non-standard metadata name * for your tags. * * @param string $name Tag name * * @return bool * @since 1.7.0 */ function elgg_register_tag_metadata_name($name) { global $CONFIG; if (!isset($CONFIG->registered_tag_metadata_names)) { $CONFIG->registered_tag_metadata_names = array(); } if (!in_array($name, $CONFIG->registered_tag_metadata_names)) { $CONFIG->registered_tag_metadata_names[] = $name; } return true; } /** * Returns an array of valid metadata names for tags. * * @return array * @since 1.7.0 */ function elgg_get_registered_tag_metadata_names() { global $CONFIG; $names = (isset($CONFIG->registered_tag_metadata_names)) ? $CONFIG->registered_tag_metadata_names : array(); return $names; } /** * @access private */ function _elgg_tags_init() { // register the standard tags metadata name elgg_register_tag_metadata_name('tags'); } return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) { $events->registerHandler('init', 'system', '_elgg_tags_init'); };