/** * Returns entities based upon private settings * * Also accepts all options available to elgg_get_entities(). Supports * the singular option shortcut. * * @param array $options Array in format: * * private_setting_names => null|ARR private setting names * * private_setting_values => null|ARR metadata values * * private_setting_name_value_pairs => null|ARR ( * name => 'name', * value => 'value', * 'operand' => '=', * ) * Currently if multiple values are sent via * an array (value => array('value1', 'value2') * the pair's operand will be forced to "IN". * * private_setting_name_value_pairs_operator => null|STR The operator to * use for combining * (name = value) OPERATOR (name = value); * default AND * * private_setting_name_prefix => STR A prefix to apply to all private * settings. Used to namespace plugin user * settings or by plugins to namespace their * own settings. * * @return mixed int If count, int. If not count, array. false on errors. */ public function getEntities(array $options = array()) { $defaults = array('private_setting_names' => ELGG_ENTITIES_ANY_VALUE, 'private_setting_values' => ELGG_ENTITIES_ANY_VALUE, 'private_setting_name_value_pairs' => ELGG_ENTITIES_ANY_VALUE, 'private_setting_name_value_pairs_operator' => 'AND', 'private_setting_name_prefix' => ''); $options = array_merge($defaults, $options); $singulars = array('private_setting_name', 'private_setting_value', 'private_setting_name_value_pair'); $options = _elgg_normalize_plural_options_array($options, $singulars); $clauses = $this->getWhereSql('e', $options['private_setting_names'], $options['private_setting_values'], $options['private_setting_name_value_pairs'], $options['private_setting_name_value_pairs_operator'], $options['private_setting_name_prefix']); if ($clauses) { // merge wheres to pass to get_entities() if (isset($options['wheres']) && !is_array($options['wheres'])) { $options['wheres'] = array($options['wheres']); } elseif (!isset($options['wheres'])) { $options['wheres'] = array(); } $options['wheres'] = array_merge($options['wheres'], $clauses['wheres']); // merge joins to pass to get_entities() if (isset($options['joins']) && !is_array($options['joins'])) { $options['joins'] = array($options['joins']); } elseif (!isset($options['joins'])) { $options['joins'] = array(); } $options['joins'] = array_merge($options['joins'], $clauses['joins']); } return $this->entities->getEntities($options); }
/** * Delete river items * * @warning Does not fire permission hooks or delete, river events. * * @param array $options Parameters: * ids => INT|ARR River item id(s) * subject_guids => INT|ARR Subject guid(s) * object_guids => INT|ARR Object guid(s) * target_guids => INT|ARR Target guid(s) * annotation_ids => INT|ARR The identifier of the annotation(s) * action_types => STR|ARR The river action type(s) identifier * views => STR|ARR River view(s) * * types => STR|ARR Entity type string(s) * subtypes => STR|ARR Entity subtype string(s) * type_subtype_pairs => ARR Array of type => subtype pairs where subtype * can be an array of subtype strings * * posted_time_lower => INT The lower bound on the time posted * posted_time_upper => INT The upper bound on the time posted * * @return bool * @since 1.8.0 * @deprecated 2.3 Use elgg_get_river() and call delete() on the returned item(s) */ function elgg_delete_river(array $options = array()) { global $CONFIG; // allow core to use this in 2.x w/o warnings if (empty($options['__bypass_notice'])) { elgg_deprecated_notice(__FUNCTION__ . ' is deprecated. Use elgg_get_river() and call delete() on the returned item(s)', '2.3'); } $defaults = array('ids' => ELGG_ENTITIES_ANY_VALUE, 'subject_guids' => ELGG_ENTITIES_ANY_VALUE, 'object_guids' => ELGG_ENTITIES_ANY_VALUE, 'target_guids' => ELGG_ENTITIES_ANY_VALUE, 'annotation_ids' => ELGG_ENTITIES_ANY_VALUE, 'views' => ELGG_ENTITIES_ANY_VALUE, 'action_types' => ELGG_ENTITIES_ANY_VALUE, 'types' => ELGG_ENTITIES_ANY_VALUE, 'subtypes' => ELGG_ENTITIES_ANY_VALUE, 'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE, 'posted_time_lower' => ELGG_ENTITIES_ANY_VALUE, 'posted_time_upper' => ELGG_ENTITIES_ANY_VALUE, 'wheres' => array(), 'joins' => array()); $options = array_merge($defaults, $options); $singulars = array('id', 'subject_guid', 'object_guid', 'target_guid', 'annotation_id', 'action_type', 'view', 'type', 'subtype'); $options = _elgg_normalize_plural_options_array($options, $singulars); $wheres = $options['wheres']; $wheres[] = _elgg_get_guid_based_where_sql('rv.id', $options['ids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.subject_guid', $options['subject_guids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.object_guid', $options['object_guids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.target_guid', $options['target_guids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.annotation_id', $options['annotation_ids']); $wheres[] = _elgg_river_get_action_where_sql($options['action_types']); $wheres[] = _elgg_river_get_view_where_sql($options['views']); $wheres[] = _elgg_get_river_type_subtype_where_sql('rv', $options['types'], $options['subtypes'], $options['type_subtype_pairs']); if ($options['posted_time_lower'] && is_int($options['posted_time_lower'])) { $wheres[] = "rv.posted >= {$options['posted_time_lower']}"; } if ($options['posted_time_upper'] && is_int($options['posted_time_upper'])) { $wheres[] = "rv.posted <= {$options['posted_time_upper']}"; } // 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); $query = "DELETE rv.* FROM {$CONFIG->dbprefix}river rv "; // remove identical join clauses $joins = array_unique($options['joins']); // add joins foreach ($joins as $j) { $query .= " {$j} "; } // add wheres $query .= ' WHERE '; foreach ($wheres as $w) { $query .= " {$w} AND "; } $query .= "1=1"; return delete_data($query); }
function elgg_solr_get_entity_guids(array $options = array()) { global $CONFIG; $defaults = array('types' => ELGG_ENTITIES_ANY_VALUE, 'subtypes' => ELGG_ENTITIES_ANY_VALUE, 'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE, 'guids' => 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, 'reverse_order_by' => false, 'order_by' => 'e.time_created desc', 'group_by' => ELGG_ENTITIES_ANY_VALUE, 'limit' => 10, 'offset' => 0, 'count' => false, 'selects' => array(), 'wheres' => array(), 'joins' => array(), 'callback' => false, '__ElggBatch' => null); $options = array_merge($defaults, $options); // can't use helper function with type_subtype_pair because // it's already an array...just need to merge it if (isset($options['type_subtype_pair'])) { if (isset($options['type_subtype_pairs'])) { $options['type_subtype_pairs'] = array_merge($options['type_subtype_pairs'], $options['type_subtype_pair']); } else { $options['type_subtype_pairs'] = $options['type_subtype_pair']; } } $singulars = array('type', 'subtype', 'guid', 'owner_guid', 'container_guid', 'site_guid'); $options = _elgg_normalize_plural_options_array($options, $singulars); // evaluate where clauses if (!is_array($options['wheres'])) { $options['wheres'] = array($options['wheres']); } $wheres = $options['wheres']; $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.guid', $options['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_guid_based_where_sql('e.site_guid', $options['site_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); // evaluate join clauses if (!is_array($options['joins'])) { $options['joins'] = array($options['joins']); } // remove identical join clauses $joins = array_unique($options['joins']); foreach ($joins as $i => $join) { if ($join === false) { return false; } elseif (empty($join)) { unset($joins[$i]); } } // evalutate selects if ($options['selects']) { $selects = ''; foreach ($options['selects'] as $select) { $selects .= ", {$select}"; } } else { $selects = ''; } if (!$options['count']) { $distinct = ''; if ($options['require_distinct']) { $distinct = ' DISTINCT'; } $query = "SELECT{$distinct} e.guid{$selects} FROM {$CONFIG->dbprefix}entities e "; } else { $query = "SELECT count(DISTINCT e.guid) as total 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(); // reverse order by if ($options['reverse_order_by']) { $options['order_by'] = _elgg_sql_reverse_order_by_clause($options['order_by']); } if (!$options['count']) { if ($options['group_by']) { $query .= " GROUP BY {$options['group_by']}"; } if ($options['order_by']) { $query .= " ORDER BY {$options['order_by']}"; } if ($options['limit']) { $limit = sanitise_int($options['limit'], false); $offset = sanitise_int($options['offset'], false); $query .= " LIMIT {$offset}, {$limit}"; } if ($options['callback'] === 'entity_row_to_elggstar') { $dt = _elgg_fetch_entities_from_sql($query, $options['__ElggBatch']); } else { $dt = get_data($query, $options['callback']); } if ($dt) { // populate entity and metadata caches $guids = array(); foreach ($dt as $item) { // A custom callback could result in items that aren't ElggEntity's, so check for them if ($item instanceof ElggEntity) { _elgg_cache_entity($item); // plugins usually have only settings if (!$item instanceof ElggPlugin) { $guids[] = $item->guid; } } } // @todo Without this, recursive delete fails. See #4568 reset($dt); if ($guids) { _elgg_get_metadata_cache()->populateFromEntities($guids); } } return $dt; } else { $total = get_data_row($query); return (int) $total->total; } }
/** * Get popular tags and their frequencies * * Supports similar arguments as elgg_get_entities() * * @param array $options Array in format: * * threshold => INT minimum tag count * * tag_names => array() metadata tag names - must be registered tags * * limit => INT number of tags to return * * types => null|STR entity type (SQL: type = '$type') * * subtypes => null|STR entity subtype (SQL: subtype = '$subtype') * * type_subtype_pairs => null|ARR (array('type' => 'subtype')) * (SQL: type = '$type' AND subtype = '$subtype') pairs * * 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' => 10, '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); }
/** * Returns entities based upon metadata. Also accepts all * options available to elgg_get_entities(). Supports * the singular option shortcut. * * @note Using metadata_names and metadata_values results in a * "names IN (...) AND values IN (...)" clause. This is subtly * differently than default multiple metadata_name_value_pairs, which use * "(name = value) AND (name = value)" clauses. * * When in doubt, use name_value_pairs. * * To ask for entities that do not have a metadata value, use a custom * where clause like this: * * $options['wheres'][] = "NOT EXISTS ( * SELECT 1 FROM {$dbprefix}metadata md * WHERE md.entity_guid = e.guid * AND md.name_id = $name_metastring_id * AND md.value_id = $value_metastring_id)"; * * Note the metadata name and value has been denormalized in the above example. * * @see elgg_get_entities * * @param array $options Array in format: * * metadata_names => null|ARR metadata names * * metadata_values => null|ARR metadata values * * metadata_name_value_pairs => null|ARR ( * name => 'name', * value => 'value', * 'operand' => '=', * 'case_sensitive' => true * ) * Currently if multiple values are sent via * an array (value => array('value1', 'value2') * the pair's operand will be forced to "IN". * If passing "IN" as the operand and a string as the value, * the value must be a properly quoted and escaped string. * * metadata_name_value_pairs_operator => null|STR The operator to use for combining * (name = value) OPERATOR (name = value); default AND * * metadata_case_sensitive => BOOL Overall Case sensitive * * order_by_metadata => null|ARR array( * 'name' => 'metadata_text1', * 'direction' => ASC|DESC, * 'as' => text|integer * ) * Also supports array('name' => 'metadata_text1') * * metadata_owner_guids => null|ARR guids for metadata owners * * @return ElggEntity[]|mixed If count, int. If not count, array. false on errors. * @since 1.7.0 */ function elgg_get_entities_from_metadata(array $options = array()) { $defaults = array('metadata_names' => ELGG_ENTITIES_ANY_VALUE, 'metadata_values' => ELGG_ENTITIES_ANY_VALUE, 'metadata_name_value_pairs' => ELGG_ENTITIES_ANY_VALUE, 'metadata_name_value_pairs_operator' => 'AND', 'metadata_case_sensitive' => true, 'order_by_metadata' => array(), 'metadata_owner_guids' => ELGG_ENTITIES_ANY_VALUE); $options = array_merge($defaults, $options); $singulars = array('metadata_name', 'metadata_value', 'metadata_name_value_pair', 'metadata_owner_guid'); $options = _elgg_normalize_plural_options_array($options, $singulars); if (!($options = _elgg_entities_get_metastrings_options('metadata', $options))) { return false; } return elgg_get_entities($options); }
/** * Returns entities based upon annotations. Also accepts all options available * to elgg_get_entities() and elgg_get_entities_from_metadata(). * * Entity creation time is selected as maxtime. To sort based upon * this, pass 'order_by' => 'maxtime asc' || 'maxtime desc' * * @see elgg_get_entities * @see elgg_get_entities_from_metadata * * @param array $options Array in format: * * annotation_names => null|ARR annotations names * * annotation_values => null|ARR annotations values * * annotation_name_value_pairs => null|ARR (name = 'name', value => 'value', * 'operator' => '=', 'case_sensitive' => true) entries. * Currently if multiple values are sent via an array (value => array('value1', 'value2') * the pair's operator will be forced to "IN". * * annotation_name_value_pairs_operator => null|STR The operator to use for combining * (name = value) OPERATOR (name = value); default AND * * annotation_case_sensitive => BOOL Overall Case sensitive * * order_by_annotation => null|ARR (array('name' => 'annotation_text1', 'direction' => ASC|DESC, * 'as' => text|integer), * * Also supports array('name' => 'annotation_text1') * * annotation_owner_guids => null|ARR guids for annotaiton owners * * @return mixed If count, int. If not count, array. false on errors. * @since 1.7.0 */ function elgg_get_entities_from_annotations(array $options = array()) { $defaults = array('annotation_names' => ELGG_ENTITIES_ANY_VALUE, 'annotation_values' => ELGG_ENTITIES_ANY_VALUE, 'annotation_name_value_pairs' => ELGG_ENTITIES_ANY_VALUE, 'annotation_name_value_pairs_operator' => 'AND', 'annotation_case_sensitive' => true, 'order_by_annotation' => array(), 'annotation_created_time_lower' => ELGG_ENTITIES_ANY_VALUE, 'annotation_created_time_upper' => ELGG_ENTITIES_ANY_VALUE, 'annotation_owner_guids' => ELGG_ENTITIES_ANY_VALUE, 'order_by' => 'maxtime DESC', 'group_by' => 'a.entity_guid'); $options = array_merge($defaults, $options); $singulars = array('annotation_name', 'annotation_value', 'annotation_name_value_pair', 'annotation_owner_guid'); $options = _elgg_normalize_plural_options_array($options, $singulars); $options = _elgg_entities_get_metastrings_options('annotation', $options); if (!$options) { return false; } // special sorting for annotations //@todo overrides other sorting $options['selects'][] = "MAX(n_table.time_created) AS maxtime"; $options['group_by'] = 'n_table.entity_guid'; $time_wheres = _elgg_get_entity_time_where_sql('a', $options['annotation_created_time_upper'], $options['annotation_created_time_lower']); if ($time_wheres) { $options['wheres'] = array_merge($options['wheres'], $time_wheres); } return elgg_get_entities_from_metadata($options); }
/** * Get river items * * @note If using types and subtypes in a query, they are joined with an AND. * * @param array $options Parameters: * ids => INT|ARR River item id(s) * subject_guids => INT|ARR Subject guid(s) * object_guids => INT|ARR Object guid(s) * target_guids => INT|ARR Target guid(s) * annotation_ids => INT|ARR The identifier of the annotation(s) * action_types => STR|ARR The river action type(s) identifier * posted_time_lower => INT The lower bound on the time posted * posted_time_upper => INT The upper bound on the time posted * * types => STR|ARR Entity type string(s) * subtypes => STR|ARR Entity subtype string(s) * type_subtype_pairs => ARR Array of type => subtype pairs where subtype * can be an array of subtype strings * * relationship => STR Relationship identifier * relationship_guid => INT|ARR Entity guid(s) * inverse_relationship => BOOL Subject or object of the relationship (false) * * limit => INT Number to show per page (20) * offset => INT Offset in list (0) * count => BOOL Count the river items? (false) * order_by => STR Order by clause (rv.posted desc) * group_by => STR Group by clause * * distinct => BOOL If set to false, Elgg will drop the DISTINCT * clause from the MySQL query, which will improve * performance in some situations. Avoid setting this * option without a full understanding of the * underlying SQL query Elgg creates. (true) * * @return array|int * @since 1.8.0 */ function elgg_get_river(array $options = array()) { global $CONFIG; $defaults = array('ids' => ELGG_ENTITIES_ANY_VALUE, 'subject_guids' => ELGG_ENTITIES_ANY_VALUE, 'object_guids' => ELGG_ENTITIES_ANY_VALUE, 'target_guids' => ELGG_ENTITIES_ANY_VALUE, 'annotation_ids' => ELGG_ENTITIES_ANY_VALUE, 'action_types' => ELGG_ENTITIES_ANY_VALUE, 'relationship' => null, 'relationship_guid' => null, 'inverse_relationship' => false, 'types' => ELGG_ENTITIES_ANY_VALUE, 'subtypes' => ELGG_ENTITIES_ANY_VALUE, 'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE, 'posted_time_lower' => ELGG_ENTITIES_ANY_VALUE, 'posted_time_upper' => ELGG_ENTITIES_ANY_VALUE, 'limit' => 20, 'offset' => 0, 'count' => false, 'distinct' => true, 'order_by' => 'rv.posted desc', 'group_by' => ELGG_ENTITIES_ANY_VALUE, 'wheres' => array(), 'joins' => array()); $options = array_merge($defaults, $options); $singulars = array('id', 'subject_guid', 'object_guid', 'target_guid', 'annotation_id', 'action_type', 'type', 'subtype'); $options = _elgg_normalize_plural_options_array($options, $singulars); $wheres = $options['wheres']; $wheres[] = _elgg_get_guid_based_where_sql('rv.id', $options['ids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.subject_guid', $options['subject_guids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.object_guid', $options['object_guids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.target_guid', $options['target_guids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.annotation_id', $options['annotation_ids']); $wheres[] = _elgg_river_get_action_where_sql($options['action_types']); $wheres[] = _elgg_get_river_type_subtype_where_sql('rv', $options['types'], $options['subtypes'], $options['type_subtype_pairs']); if ($options['posted_time_lower'] && is_int($options['posted_time_lower'])) { $wheres[] = "rv.posted >= {$options['posted_time_lower']}"; } if ($options['posted_time_upper'] && is_int($options['posted_time_upper'])) { $wheres[] = "rv.posted <= {$options['posted_time_upper']}"; } if (!access_get_show_hidden_status()) { $wheres[] = "rv.enabled = 'yes'"; } $joins = $options['joins']; $dbprefix = elgg_get_config('dbprefix'); $joins[] = "JOIN {$dbprefix}entities oe ON rv.object_guid = oe.guid"; // LEFT JOIN is used because all river items do not necessarily have target $joins[] = "LEFT JOIN {$dbprefix}entities te ON rv.target_guid = te.guid"; if ($options['relationship_guid']) { $clauses = elgg_get_entity_relationship_where_sql('rv.subject_guid', $options['relationship'], $options['relationship_guid'], $options['inverse_relationship']); if ($clauses) { $wheres = array_merge($wheres, $clauses['wheres']); $joins = array_merge($joins, $clauses['joins']); } } // 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); if (!$options['count']) { $distinct = $options['distinct'] ? "DISTINCT" : ""; $query = "SELECT {$distinct} rv.* FROM {$CONFIG->dbprefix}river rv "; } else { // note: when DISTINCT unneeded, it's slightly faster to compute COUNT(*) than IDs $count_expr = $options['distinct'] ? "DISTINCT rv.id" : "*"; $query = "SELECT COUNT({$count_expr}) as total FROM {$CONFIG->dbprefix}river rv "; } // add joins foreach ($joins as $j) { $query .= " {$j} "; } // add wheres $query .= ' WHERE '; foreach ($wheres as $w) { $query .= " {$w} AND "; } // Make sure that user has access to all the entities referenced by each river item $object_access_where = _elgg_get_access_where_sql(array('table_alias' => 'oe')); $target_access_where = _elgg_get_access_where_sql(array('table_alias' => 'te')); // We use LEFT JOIN with entities table but the WHERE clauses are used // regardless if a JOIN is successfully made. The "te.guid IS NULL" is // needed because of this. $query .= "{$object_access_where} AND ({$target_access_where} OR te.guid IS NULL) "; if (!$options['count']) { $options['group_by'] = sanitise_string($options['group_by']); if ($options['group_by']) { $query .= " GROUP BY {$options['group_by']}"; } $options['order_by'] = sanitise_string($options['order_by']); $query .= " ORDER BY {$options['order_by']}"; if ($options['limit']) { $limit = sanitise_int($options['limit']); $offset = sanitise_int($options['offset'], false); $query .= " LIMIT {$offset}, {$limit}"; } $river_items = get_data($query, '_elgg_row_to_elgg_river_item'); _elgg_prefetch_river_entities($river_items); return $river_items; } else { $total = get_data_row($query); return (int) $total->total; } }
/** * Returns entities based upon annotations. Also accepts all options available * to elgg_get_entities() and elgg_get_entities_from_metadata(). * * @see elgg_get_entities * @see elgg_get_entities_from_metadata * * @param array $options Array in format: * * annotation_names => null|ARR annotations names * * annotation_values => null|ARR annotations values * * annotation_name_value_pairs => null|ARR (name = 'name', value => 'value', * 'operator' => '=', 'case_sensitive' => true) entries. * Currently if multiple values are sent via an array (value => array('value1', 'value2') * the pair's operator will be forced to "IN". * * annotation_name_value_pairs_operator => null|STR The operator to use for combining * (name = value) OPERATOR (name = value); default AND * * annotation_case_sensitive => BOOL Overall Case sensitive * * order_by_annotation => null|ARR (array('name' => 'annotation_text1', 'direction' => ASC|DESC, * 'as' => text|integer), * * Also supports array('name' => 'annotation_text1') * * annotation_owner_guids => null|ARR guids for annotaiton owners * * @return mixed If count, int. If not count, array. false on errors. */ function getEntities(array $options = array()) { $defaults = array('annotation_names' => ELGG_ENTITIES_ANY_VALUE, 'annotation_values' => ELGG_ENTITIES_ANY_VALUE, 'annotation_name_value_pairs' => ELGG_ENTITIES_ANY_VALUE, 'annotation_name_value_pairs_operator' => 'AND', 'annotation_case_sensitive' => true, 'order_by_annotation' => array(), 'annotation_created_time_lower' => ELGG_ENTITIES_ANY_VALUE, 'annotation_created_time_upper' => ELGG_ENTITIES_ANY_VALUE, 'annotation_owner_guids' => ELGG_ENTITIES_ANY_VALUE); $options = array_merge($defaults, $options); $singulars = array('annotation_name', 'annotation_value', 'annotation_name_value_pair', 'annotation_owner_guid'); $options = _elgg_normalize_plural_options_array($options, $singulars); $options = _elgg_entities_get_metastrings_options('annotation', $options); if (!$options) { return false; } // because of performance issues support for ordering by maxtime has been dropped // @see https://github.com/Elgg/Elgg/issues/6638 if (isset($options['order_by']) && preg_match('~\\bmaxtime\\b~i', $options['order_by'])) { // check if the user provided maxtime $deprecated = true; if (isset($options['selects'])) { $selects = $options['selects']; if (!is_array($selects)) { $selects = array($selects); } foreach ($selects as $select) { if (preg_match('~\\bmaxtime\\b~i', $options['order_by'])) { $deprecated = false; break; } } } // the user didn't provide maxtime if ($deprecated) { // special sorting for annotations elgg_deprecated_notice(__FUNCTION__ . ": no longer orders by annotations by default. If you order" . " by maxtime, you must provide that column via \$options['selects']. See" . " https://github.com/Elgg/Elgg/issues/6638#issuecomment-41562034", "1.10"); $options['selects'][] = "MAX(n_table.time_created) AS maxtime"; $options['group_by'] = 'n_table.entity_guid'; } } $time_wheres = _elgg_get_entity_time_where_sql('a', $options['annotation_created_time_upper'], $options['annotation_created_time_lower']); if ($time_wheres) { $options['wheres'] = array_merge($options['wheres'], $time_wheres); } return elgg_get_entities_from_metadata($options); }
/** * Gets entities based upon attributes in secondary tables. * Also accepts all options available to elgg_get_entities(), * elgg_get_entities_from_metadata(), and elgg_get_entities_from_relationship(). * * @warning requires that the entity type be specified and there can only be one * type. * * @see elgg_get_entities * @see elgg_get_entities_from_metadata * @see elgg_get_entities_from_relationship * * @param array $options Array in format: * * attribute_name_value_pairs => ARR ( * 'name' => 'name', * 'value' => 'value', * 'operand' => '=', (optional) * 'case_sensitive' => false (optional) * ) * If multiple values are sent via * an array ('value' => array('value1', 'value2') * the pair's operand will be forced to "IN". * * attribute_name_value_pairs_operator => null|STR The operator to use for combining * (name = value) OPERATOR (name = value); default is AND * * @return \ElggEntity[]|mixed If count, int. If not count, array. false on errors. * @throws InvalidArgumentException * @todo Does not support ordering by attributes or using an attribute pair shortcut like this ('title' => 'foo') */ function getEntitiesFromAttributes(array $options = array()) { $defaults = array('attribute_name_value_pairs' => ELGG_ENTITIES_ANY_VALUE, 'attribute_name_value_pairs_operator' => 'AND'); $options = array_merge($defaults, $options); $singulars = array('type', 'attribute_name_value_pair'); $options = _elgg_normalize_plural_options_array($options, $singulars); $clauses = _elgg_get_entity_attribute_where_sql($options); if ($clauses) { // merge wheres to pass to elgg_get_entities() if (isset($options['wheres']) && !is_array($options['wheres'])) { $options['wheres'] = array($options['wheres']); } elseif (!isset($options['wheres'])) { $options['wheres'] = array(); } $options['wheres'] = array_merge($options['wheres'], $clauses['wheres']); // merge joins to pass to elgg_get_entities() if (isset($options['joins']) && !is_array($options['joins'])) { $options['joins'] = array($options['joins']); } elseif (!isset($options['joins'])) { $options['joins'] = array(); } $options['joins'] = array_merge($options['joins'], $clauses['joins']); } return elgg_get_entities_from_relationship($options); }
/** * Returns entities based upon annotations. Also accepts all options available * to elgg_get_entities() and elgg_get_entities_from_metadata(). * * @see elgg_get_entities * @see elgg_get_entities_from_metadata * * @param array $options Array in format: * * annotation_names => null|ARR annotations names * * annotation_values => null|ARR annotations values * * annotation_name_value_pairs => null|ARR (name = 'name', value => 'value', * 'operator' => '=', 'case_sensitive' => true) entries. * Currently if multiple values are sent via an array (value => array('value1', 'value2') * the pair's operator will be forced to "IN". * * annotation_name_value_pairs_operator => null|STR The operator to use for combining * (name = value) OPERATOR (name = value); default AND * * annotation_case_sensitive => BOOL Overall Case sensitive * * order_by_annotation => null|ARR (array('name' => 'annotation_text1', 'direction' => ASC|DESC, * 'as' => text|integer), * * Also supports array('name' => 'annotation_text1') * * annotation_owner_guids => null|ARR guids for annotaiton owners * * @return mixed If count, int. If not count, array. false on errors. */ function getEntities(array $options = array()) { $defaults = array('annotation_names' => ELGG_ENTITIES_ANY_VALUE, 'annotation_values' => ELGG_ENTITIES_ANY_VALUE, 'annotation_name_value_pairs' => ELGG_ENTITIES_ANY_VALUE, 'annotation_name_value_pairs_operator' => 'AND', 'annotation_case_sensitive' => true, 'order_by_annotation' => array(), 'annotation_created_time_lower' => ELGG_ENTITIES_ANY_VALUE, 'annotation_created_time_upper' => ELGG_ENTITIES_ANY_VALUE, 'annotation_owner_guids' => ELGG_ENTITIES_ANY_VALUE); $options = array_merge($defaults, $options); $singulars = array('annotation_name', 'annotation_value', 'annotation_name_value_pair', 'annotation_owner_guid'); $options = _elgg_normalize_plural_options_array($options, $singulars); $options = _elgg_entities_get_metastrings_options('annotation', $options); if (!$options) { return false; } $time_wheres = _elgg_get_entity_time_where_sql('n_table', $options['annotation_created_time_upper'], $options['annotation_created_time_lower']); if ($time_wheres) { $options['wheres'][] = $time_wheres; } return elgg_get_entities_from_metadata($options); }
/** * Returns entities based upon plugin user settings. * Takes all the options for {@link elgg_get_entities_from_private_settings()} * in addition to the ones below. * * @param array $options Array in the format: * * plugin_id => STR The plugin id. Required. * * plugin_user_setting_names => null|ARR private setting names * * plugin_user_setting_values => null|ARR metadata values * * plugin_user_setting_name_value_pairs => null|ARR ( * name => 'name', * value => 'value', * 'operand' => '=', * ) * Currently if multiple values are sent via * an array (value => array('value1', 'value2') * the pair's operand will be forced to "IN". * * plugin_user_setting_name_value_pairs_operator => null|STR The operator to use for combining * (name = value) OPERATOR (name = value); default AND * * @return mixed int If count, int. If not count, array. false on errors. */ function getEntitiesFromUserSettings(array $options = array()) { if (!isset($options['plugin_id'])) { elgg_deprecated_notice("'plugin_id' is now required for elgg_get_entities_from_plugin_user_settings()", 1.9); $options['plugin_id'] = elgg_get_calling_plugin_id(); } $singulars = array('plugin_user_setting_name', 'plugin_user_setting_value', 'plugin_user_setting_name_value_pair'); $options = _elgg_normalize_plural_options_array($options, $singulars); // rewrite plugin_user_setting_name_* to the right PS ones. $map = array('plugin_user_setting_names' => 'private_setting_names', 'plugin_user_setting_values' => 'private_setting_values', 'plugin_user_setting_name_value_pairs' => 'private_setting_name_value_pairs', 'plugin_user_setting_name_value_pairs_operator' => 'private_setting_name_value_pairs_operator'); foreach ($map as $plugin => $private) { if (!isset($options[$plugin])) { continue; } if (isset($options[$private])) { if (!is_array($options[$private])) { $options[$private] = array($options[$private]); } $options[$private] = array_merge($options[$private], $options[$plugin]); } else { $options[$private] = $options[$plugin]; } } $prefix = _elgg_namespace_plugin_private_setting('user_setting', '', $options['plugin_id']); $options['private_setting_name_prefix'] = $prefix; return elgg_get_entities_from_private_settings($options); }
/** * Get river items * * @note If using types and subtypes in a query, they are joined with an AND. * * @param array $options Parameters: * ids => INT|ARR River item id(s) * subject_guids => INT|ARR Subject guid(s) * object_guids => INT|ARR Object guid(s) * target_guids => INT|ARR Target guid(s) * annotation_ids => INT|ARR The identifier of the annotation(s) * action_types => STR|ARR The river action type(s) identifier * posted_time_lower => INT The lower bound on the time posted * posted_time_upper => INT The upper bound on the time posted * * types => STR|ARR Entity type string(s) * subtypes => STR|ARR Entity subtype string(s) * type_subtype_pairs => ARR Array of type => subtype pairs where subtype * can be an array of subtype strings * * relationship => STR Relationship identifier * relationship_guid => INT|ARR Entity guid(s) * inverse_relationship => BOOL Subject or object of the relationship (false) * * limit => INT Number to show per page (20) * offset => INT Offset in list (0) * count => BOOL Count the river items? (false) * order_by => STR Order by clause (rv.posted desc) * group_by => STR Group by clause * * @return array|int * @since 1.8.0 */ function elgg_get_river(array $options = array()) { global $CONFIG; $defaults = array('ids' => ELGG_ENTITIES_ANY_VALUE, 'subject_guids' => ELGG_ENTITIES_ANY_VALUE, 'object_guids' => ELGG_ENTITIES_ANY_VALUE, 'target_guids' => ELGG_ENTITIES_ANY_VALUE, 'annotation_ids' => ELGG_ENTITIES_ANY_VALUE, 'action_types' => ELGG_ENTITIES_ANY_VALUE, 'relationship' => null, 'relationship_guid' => null, 'inverse_relationship' => false, 'types' => ELGG_ENTITIES_ANY_VALUE, 'subtypes' => ELGG_ENTITIES_ANY_VALUE, 'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE, 'posted_time_lower' => ELGG_ENTITIES_ANY_VALUE, 'posted_time_upper' => ELGG_ENTITIES_ANY_VALUE, 'limit' => 20, 'offset' => 0, 'count' => false, 'order_by' => 'rv.posted desc', 'group_by' => ELGG_ENTITIES_ANY_VALUE, 'wheres' => array(), 'joins' => array()); $options = array_merge($defaults, $options); $singulars = array('id', 'subject_guid', 'object_guid', 'target_guid', 'annotation_id', 'action_type', 'type', 'subtype'); $options = _elgg_normalize_plural_options_array($options, $singulars); $wheres = $options['wheres']; $wheres[] = _elgg_get_guid_based_where_sql('rv.id', $options['ids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.subject_guid', $options['subject_guids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.object_guid', $options['object_guids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.target_guid', $options['target_guids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.annotation_id', $options['annotation_ids']); $wheres[] = _elgg_river_get_action_where_sql($options['action_types']); $wheres[] = _elgg_get_river_type_subtype_where_sql('rv', $options['types'], $options['subtypes'], $options['type_subtype_pairs']); if ($options['posted_time_lower'] && is_int($options['posted_time_lower'])) { $wheres[] = "rv.posted >= {$options['posted_time_lower']}"; } if ($options['posted_time_upper'] && is_int($options['posted_time_upper'])) { $wheres[] = "rv.posted <= {$options['posted_time_upper']}"; } $joins = $options['joins']; if ($options['relationship_guid']) { $clauses = elgg_get_entity_relationship_where_sql('rv.subject_guid', $options['relationship'], $options['relationship_guid'], $options['inverse_relationship']); if ($clauses) { $wheres = array_merge($wheres, $clauses['wheres']); $joins = array_merge($joins, $clauses['joins']); } } // 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); if (!$options['count']) { $query = "SELECT DISTINCT rv.* FROM {$CONFIG->dbprefix}river rv "; } else { $query = "SELECT COUNT(DISTINCT rv.id) AS total FROM {$CONFIG->dbprefix}river rv "; } // add joins foreach ($joins as $j) { $query .= " {$j} "; } // add wheres $query .= ' WHERE '; foreach ($wheres as $w) { $query .= " {$w} AND "; } $query .= elgg_river_get_access_sql(); if (!$options['count']) { $options['group_by'] = sanitise_string($options['group_by']); if ($options['group_by']) { $query .= " GROUP BY {$options['group_by']}"; } $options['order_by'] = sanitise_string($options['order_by']); $query .= " ORDER BY {$options['order_by']}"; if ($options['limit']) { $limit = sanitise_int($options['limit']); $offset = sanitise_int($options['offset'], false); $query .= " LIMIT {$offset}, {$limit}"; } $river_items = get_data($query, '_elgg_row_to_elgg_river_item'); _elgg_prefetch_river_entities($river_items); return $river_items; } else { $total = get_data_row($query); return (int) $total->total; } }
/** * Returns options to pass to elgg_get_entities() for metastrings operations. * * @param string $type Metastring type: annotation or metadata * @param array $options Options * * @return array * @access private */ function _elgg_entities_get_metastrings_options($type, $options) { $valid_types = array('metadata', 'annotation'); if (!in_array($type, $valid_types)) { return false; } // the options for annotations are singular (annotation_name) but the table // is plural (elgg_annotations) so rewrite for the table name. $n_table = $type == 'annotation' ? 'annotations' : $type; $singulars = array("{$type}_name", "{$type}_value", "{$type}_name_value_pair", "{$type}_owner_guid"); $options = _elgg_normalize_plural_options_array($options, $singulars); $clauses = _elgg_get_entity_metadata_where_sql('e', $n_table, $options["{$type}_names"], $options["{$type}_values"], $options["{$type}_name_value_pairs"], $options["{$type}_name_value_pairs_operator"], $options["{$type}_case_sensitive"], $options["order_by_{$type}"], $options["{$type}_owner_guids"]); if ($clauses) { // merge wheres to pass to elgg_get_entities() if (isset($options['wheres']) && !is_array($options['wheres'])) { $options['wheres'] = array($options['wheres']); } elseif (!isset($options['wheres'])) { $options['wheres'] = array(); } $options['wheres'] = array_merge($options['wheres'], $clauses['wheres']); // merge joins to pass to elgg_get_entities() if (isset($options['joins']) && !is_array($options['joins'])) { $options['joins'] = array($options['joins']); } elseif (!isset($options['joins'])) { $options['joins'] = array(); } $options['joins'] = array_merge($options['joins'], $clauses['joins']); if ($clauses['orders']) { $order_by_metadata = implode(", ", $clauses['orders']); if (isset($options['order_by']) && $options['order_by']) { $options['order_by'] = "{$order_by_metadata}, {$options['order_by']}"; } else { $options['order_by'] = "{$order_by_metadata}, e.time_created DESC"; } } } return $options; }
function elgg_solr_get_annotation_ids($options) { $options = _elgg_normalize_metastrings_options($options); $type = 'annotations'; $callback = false; $defaults = array('types' => ELGG_ENTITIES_ANY_VALUE, 'subtypes' => ELGG_ENTITIES_ANY_VALUE, 'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE, 'guids' => ELGG_ENTITIES_ANY_VALUE, 'owner_guids' => ELGG_ENTITIES_ANY_VALUE, 'container_guids' => ELGG_ENTITIES_ANY_VALUE, 'site_guids' => get_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, 'metastring_names' => ELGG_ENTITIES_ANY_VALUE, 'metastring_values' => ELGG_ENTITIES_ANY_VALUE, 'metastring_case_sensitive' => true, 'metastring_calculation' => ELGG_ENTITIES_NO_VALUE, 'metastring_created_time_lower' => ELGG_ENTITIES_ANY_VALUE, 'metastring_created_time_upper' => ELGG_ENTITIES_ANY_VALUE, 'metastring_owner_guids' => ELGG_ENTITIES_ANY_VALUE, 'metastring_ids' => ELGG_ENTITIES_ANY_VALUE, 'order_by' => 'n_table.time_created ASC, n_table.id ASC', 'limit' => elgg_get_config('default_limit'), 'offset' => 0, 'count' => false, 'selects' => array(), 'wheres' => array(), 'joins' => array(), 'distinct' => true, 'preload_owners' => false, 'callback' => $callback); // @todo Ignore site_guid right now because of #2910 $options['site_guid'] = ELGG_ENTITIES_ANY_VALUE; $options = array_merge($defaults, $options); // can't use helper function with type_subtype_pair because // it's already an array...just need to merge it if (isset($options['type_subtype_pair'])) { if (isset($options['type_subtype_pairs'])) { $options['type_subtype_pairs'] = array_merge($options['type_subtype_pairs'], $options['type_subtype_pair']); } else { $options['type_subtype_pairs'] = $options['type_subtype_pair']; } } $singulars = array('type', 'subtype', 'type_subtype_pair', 'guid', 'owner_guid', 'container_guid', 'site_guid', 'metastring_name', 'metastring_value', 'metastring_owner_guid', 'metastring_id', 'select', 'where', 'join'); $options = _elgg_normalize_plural_options_array($options, $singulars); if (!$options) { return false; } $db_prefix = elgg_get_config('dbprefix'); // evaluate where clauses if (!is_array($options['wheres'])) { $options['wheres'] = array($options['wheres']); } $wheres = $options['wheres']; // entities $wheres[] = _elgg_services()->entityTable->getEntityTypeSubtypeWhereSql('e', $options['types'], $options['subtypes'], $options['type_subtype_pairs']); $wheres[] = _elgg_get_guid_based_where_sql('e.guid', $options['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_guid_based_where_sql('e.site_guid', $options['site_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']); $wheres[] = _elgg_get_entity_time_where_sql('n_table', $options['metastring_created_time_upper'], $options['metastring_created_time_lower'], null, null); $wheres[] = _elgg_get_guid_based_where_sql('n_table.owner_guid', $options['metastring_owner_guids']); // 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); // evaluate join clauses if (!is_array($options['joins'])) { $options['joins'] = array($options['joins']); } $joins = $options['joins']; $joins[] = "JOIN {$db_prefix}entities e ON n_table.entity_guid = e.guid"; // evaluate selects if (!is_array($options['selects'])) { $options['selects'] = array($options['selects']); } $selects = $options['selects']; // For performance reasons we don't want the joins required for metadata / annotations // unless we're going through one of their callbacks. // this means we expect the functions passing different callbacks to pass their required joins. // If we're doing a calculation $custom_callback = $options['callback'] == 'row_to_elggmetadata' || $options['callback'] == 'row_to_elggannotation'; $is_calculation = $options['metastring_calculation'] ? true : false; if ($custom_callback || $is_calculation) { $joins[] = "JOIN {$db_prefix}metastrings n on n_table.name_id = n.id"; $joins[] = "JOIN {$db_prefix}metastrings v on n_table.value_id = v.id"; $selects[] = 'n.string as name'; $selects[] = 'v.string as value'; } foreach ($joins as $i => $join) { if ($join === false) { return false; } elseif (empty($join)) { unset($joins[$i]); } } // metastrings $metastring_clauses = _elgg_get_metastring_sql('n_table', $options['metastring_names'], $options['metastring_values'], null, $options['metastring_ids'], $options['metastring_case_sensitive']); if ($metastring_clauses) { $wheres = array_merge($wheres, $metastring_clauses['wheres']); $joins = array_merge($joins, $metastring_clauses['joins']); } else { $wheres[] = _elgg_get_access_where_sql(array('table_alias' => 'n_table', 'guid_column' => 'entity_guid')); } $distinct = $options['distinct'] ? "DISTINCT " : ""; if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE && !$options['count']) { $selects = array_unique($selects); // evalutate selects $select_str = ''; if ($selects) { foreach ($selects as $select) { $select_str .= ", {$select}"; } } $query = "SELECT {$distinct} n_table.id{$select_str} FROM {$db_prefix}{$type} n_table"; } elseif ($options['count']) { // count is over the entities $query = "SELECT count({$distinct} e.guid) as calculation FROM {$db_prefix}{$type} n_table"; } else { $query = "SELECT {$options['metastring_calculation']}(v.string) as calculation FROM {$db_prefix}{$type} n_table"; } // remove identical join clauses $joins = array_unique($joins); // 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(array('table_alias' => 'e')); // reverse order by if (isset($options['reverse_order_by']) && $options['reverse_order_by']) { $options['order_by'] = _elgg_sql_reverse_order_by_clause($options['order_by']); } if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE && !$options['count']) { if (isset($options['group_by'])) { $options['group_by'] = sanitise_string($options['group_by']); $query .= " GROUP BY {$options['group_by']}"; } if (isset($options['order_by']) && $options['order_by']) { $options['order_by'] = sanitise_string($options['order_by']); $query .= " ORDER BY {$options['order_by']}, n_table.id"; } if ($options['limit']) { $limit = sanitise_int($options['limit']); $offset = sanitise_int($options['offset'], false); $query .= " LIMIT {$offset}, {$limit}"; } $dt = get_data($query, $options['callback']); return $dt; } else { $result = get_data_row($query); return $result->calculation; } }
/** * Get river items * * @note If using types and subtypes in a query, they are joined with an AND. * * @param array $options Parameters: * ids => INT|ARR River item id(s) * subject_guids => INT|ARR Subject guid(s) * object_guids => INT|ARR Object guid(s) * target_guids => INT|ARR Target guid(s) * annotation_ids => INT|ARR The identifier of the annotation(s) * action_types => STR|ARR The river action type(s) identifier * posted_time_lower => INT The lower bound on the time posted * posted_time_upper => INT The upper bound on the time posted * * types => STR|ARR Entity type string(s) * subtypes => STR|ARR Entity subtype string(s) * type_subtype_pairs => ARR Array of type => subtype pairs where subtype * can be an array of subtype strings * * relationship => STR Relationship identifier * relationship_guid => INT|ARR Entity guid(s) * inverse_relationship => BOOL Subject or object of the relationship (false) * * limit => INT Number to show per page (20) * offset => INT Offset in list (0) * count => BOOL Count the river items? (false) * order_by => STR Order by clause (rv.posted desc) * group_by => STR Group by clause * * distinct => BOOL If set to false, Elgg will drop the DISTINCT * clause from the MySQL query, which will improve * performance in some situations. Avoid setting this * option without a full understanding of the * underlying SQL query Elgg creates. (true) * * @return array|int * @since 1.8.0 */ function elgg_get_group_river(array $options = array()) { global $CONFIG; //error_log("group river"); $defaults = array('ids' => ELGG_ENTITIES_ANY_VALUE, 'subject_guids' => ELGG_ENTITIES_ANY_VALUE, 'object_guids' => ELGG_ENTITIES_ANY_VALUE, 'target_guids' => ELGG_ENTITIES_ANY_VALUE, 'annotation_ids' => ELGG_ENTITIES_ANY_VALUE, 'action_types' => ELGG_ENTITIES_ANY_VALUE, 'relationship' => null, 'relationship_guid' => null, 'inverse_relationship' => false, 'types' => ELGG_ENTITIES_ANY_VALUE, 'subtypes' => ELGG_ENTITIES_ANY_VALUE, 'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE, 'posted_time_lower' => ELGG_ENTITIES_ANY_VALUE, 'posted_time_upper' => ELGG_ENTITIES_ANY_VALUE, 'limit' => 20, 'offset' => 0, 'count' => false, 'distinct' => false, 'order_by' => 'u.posted desc', 'group_by' => ELGG_ENTITIES_ANY_VALUE, 'wheres' => array(), 'wheres1' => array(), 'wheres2' => array(), 'joins' => array()); $options = array_merge($defaults, $options); $singulars = array('id', 'subject_guid', 'object_guid', 'target_guid', 'annotation_id', 'action_type', 'type', 'subtype'); $options = _elgg_normalize_plural_options_array($options, $singulars); $wheres1 = $options['wheres1']; $wheres2 = $options['wheres2']; /* $wheres[] = _elgg_get_guid_based_where_sql('rv.id', $options['ids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.subject_guid', $options['subject_guids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.object_guid', $options['object_guids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.target_guid', $options['target_guids']); $wheres[] = _elgg_get_guid_based_where_sql('rv.annotation_id', $options['annotation_ids']); $wheres[] = _elgg_river_get_action_where_sql($options['action_types']); $wheres[] = _elgg_get_river_type_subtype_where_sql('rv', $options['types'], $options['subtypes'], $options['type_subtype_pairs']); */ /*if ($options['posted_time_lower'] && is_int($options['posted_time_lower'])) { $wheres1[] = "rv.posted >= {$options['posted_time_lower']}"; $wheres2[] = "rv.posted >= {$options['posted_time_lower']}"; } if ($options['posted_time_upper'] && is_int($options['posted_time_upper'])) { $wheres1[] = "rv.posted <= {$options['posted_time_upper']}"; $wheres2[] = "rv.posted <= {$options['posted_time_upper']}"; }*/ if (!access_get_show_hidden_status()) { $wheres1[] = "rv.enabled = 'yes'"; $wheres2[] = "rv.enabled = 'yes'"; } $dbprefix = elgg_get_config('dbprefix'); $join1 = "JOIN {$dbprefix}entities oe ON rv.object_guid = oe.guid"; // LEFT JOIN is used because all river items do not necessarily have target $join2 = "LEFT JOIN {$dbprefix}entities te ON rv.target_guid = te.guid"; // see if any functions failed // remove empty strings on successful functions /*foreach ($wheres1 as $i => $where) { if ($where === false) { return false; } elseif (empty($where)) { unset($wheres1[$i]); } } foreach ($wheres2 as $i => $where) { if ($where === false) { return false; } elseif (empty($where)) { unset($wheres2[$i]); } } // remove identical where clauses $wheres1 = array_unique($wheres1); $wheres2 = array_unique($wheres2); */ // Wheres for the 2 parts of the union query $w1 = ""; foreach ($wheres1 as $w) { $w1 .= " {$w} AND "; } $w2 = ""; foreach ($wheres2 as $w) { $w2 .= " {$w} AND "; } // Make sure that user has access to all the entities referenced by each river item $object_access_where = _elgg_get_access_where_sql(array('table_alias' => 'oe')); $target_access_where = _elgg_get_access_where_sql(array('table_alias' => 'te')); if (!$options['count']) { $GOL = ""; // Group by / order / limit $options['group_by'] = sanitise_string($options['group_by']); if ($options['group_by']) { $GOL .= " GROUP BY {$options['group_by']}"; } $options['order_by'] = sanitise_string($options['order_by']); $GOL .= " ORDER BY {$options['order_by']}"; if ($options['limit']) { $limit = sanitise_int($options['limit']); $offset = sanitise_int($options['offset'], false); $GOL .= " LIMIT {$offset}, {$limit}"; } // custom UNION - based query $query = "SELECT u.* FROM ( ( SELECT rv.* FROM {$CONFIG->dbprefix}river rv {$join1} WHERE {$w1} {$object_access_where} ) UNION " . "( SELECT rv.* FROM {$CONFIG->dbprefix}river rv {$join2} WHERE {$w2} ({$target_access_where} OR te.guid IS NULL) ) ) u {$GOL}"; $river_items = get_data($query, '_elgg_row_to_elgg_river_item'); _elgg_prefetch_river_entities($river_items); // error_log($query); return $river_items; } else { $query = "SELECT sum(count) as total FROM ( ( SELECT count(*) as count FROM {$CONFIG->dbprefix}river rv {$join1} WHERE {$w1} {$object_access_where} ) UNION " . "( SELECT count(*) as count FROM {$CONFIG->dbprefix}river rv {$join2} WHERE {$w2} ({$target_access_where} OR te.guid IS NULL) ) ) u"; // error_log($query); $total = get_data_row($query); return (int) $total->total; } }