diff options
Diffstat (limited to 'engine/lib/annotations.php')
| -rw-r--r-- | engine/lib/annotations.php | 1166 |
1 files changed, 291 insertions, 875 deletions
diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php index 9ed9cf5f6..5e9b530de 100644 --- a/engine/lib/annotations.php +++ b/engine/lib/annotations.php @@ -13,9 +13,11 @@ * @param stdClass $row Db row result object * * @return ElggAnnotation + * @access private */ function row_to_elggannotation($row) { if (!($row instanceof stdClass)) { + // @todo should throw in this case? return $row; } @@ -23,25 +25,30 @@ function row_to_elggannotation($row) { } /** - * Get a specific annotation. + * Get a specific annotation by its id. + * If you want multiple annotation objects, use + * {@link elgg_get_annotations()}. * - * @param int $annotation_id Annotation ID + * @param int $id The id of the annotation object being retrieved. * - * @return ElggAnnotation + * @return ElggAnnotation|false */ -function get_annotation($annotation_id) { - global $CONFIG; - - $annotation_id = (int) $annotation_id; - $access = get_access_sql_suffix("a"); - - $query = "SELECT a.*, n.string as name, v.string as value" - . " from {$CONFIG->dbprefix}annotations a" - . " JOIN {$CONFIG->dbprefix}metastrings n on a.name_id = n.id" - . " JOIN {$CONFIG->dbprefix}metastrings v on a.value_id = v.id" - . " where a.id=$annotation_id and $access"; +function elgg_get_annotation_from_id($id) { + return elgg_get_metastring_based_object_from_id($id, 'annotations'); +} - return row_to_elggannotation(get_data_row($query)); +/** + * Deletes an annotation using its ID. + * + * @param int $id The annotation ID to delete. + * @return bool + */ +function elgg_delete_annotation_by_id($id) { + $annotation = elgg_get_annotation_from_id($id); + if (!$annotation) { + return false; + } + return $annotation->delete(); } /** @@ -50,14 +57,14 @@ function get_annotation($annotation_id) { * @param int $entity_guid Entity Guid * @param string $name Name of annotation * @param string $value Value of annotation - * @param string $value_type Type of value - * @param int $owner_guid Owner of annotation + * @param string $value_type Type of value (default is auto detection) + * @param int $owner_guid Owner of annotation (default is logged in user) * @param int $access_id Access level of annotation * * @return int|bool id on success or false on failure */ -function create_annotation($entity_guid, $name, $value, $value_type, -$owner_guid, $access_id = ACCESS_PRIVATE) { +function create_annotation($entity_guid, $name, $value, $value_type = '', +$owner_guid = 0, $access_id = ACCESS_PRIVATE) { global $CONFIG; $result = false; @@ -69,7 +76,7 @@ $owner_guid, $access_id = ACCESS_PRIVATE) { $owner_guid = (int)$owner_guid; if ($owner_guid == 0) { - $owner_guid = get_loggedin_userid(); + $owner_guid = elgg_get_logged_in_user_guid(); } $access_id = (int)$access_id; @@ -88,21 +95,19 @@ $owner_guid, $access_id = ACCESS_PRIVATE) { $entity = get_entity($entity_guid); - if (trigger_elgg_event('annotate', $entity->type, $entity)) { - system_log($entity, 'annotate'); - + if (elgg_trigger_event('annotate', $entity->type, $entity)) { // If ok then add it $result = insert_data("INSERT into {$CONFIG->dbprefix}annotations (entity_guid, name_id, value_id, value_type, owner_guid, time_created, access_id) VALUES ($entity_guid,'$name',$value,'$value_type', $owner_guid, $time, $access_id)"); if ($result !== false) { - $obj = get_annotation($result); - if (trigger_elgg_event('create', 'annotation', $obj)) { + $obj = elgg_get_annotation_from_id($result); + if (elgg_trigger_event('create', 'annotation', $obj)) { return $result; } else { // plugin returned false to reject annotation - delete_annotation($result); + elgg_delete_annotation_by_id($result); return FALSE; } } @@ -133,7 +138,7 @@ function update_annotation($annotation_id, $name, $value, $value_type, $owner_gu $owner_guid = (int)$owner_guid; if ($owner_guid == 0) { - $owner_guid = get_loggedin_userid(); + $owner_guid = elgg_get_logged_in_user_guid(); } $access_id = (int)$access_id; @@ -153,186 +158,158 @@ function update_annotation($annotation_id, $name, $value, $value_type, $owner_gu // If ok then add it $result = update_data("UPDATE {$CONFIG->dbprefix}annotations - set value_id='$value', value_type='$value_type', access_id=$access_id, owner_guid=$owner_guid - where id=$annotation_id and name_id='$name' and $access"); + set name_id='$name', value_id='$value', value_type='$value_type', access_id=$access_id, owner_guid=$owner_guid + where id=$annotation_id and $access"); if ($result !== false) { - $obj = get_annotation($annotation_id); - if (trigger_elgg_event('update', 'annotation', $obj)) { - return true; - } else { - // @todo add plugin hook that sends old and new annotation information before db access - delete_annotation($annotation_id); - } + // @todo add plugin hook that sends old and new annotation information before db access + $obj = elgg_get_annotation_from_id($annotation_id); + elgg_trigger_event('update', 'annotation', $obj); } return $result; } /** - * Get a list of annotations for a given object/user/annotation type. + * Returns annotations. Accepts all elgg_get_entities() options for entity + * restraints. * - * @param int|array $entity_guid GUID to return annotations of (falsey for any) - * @param string $entity_type Type of entity - * @param string $entity_subtype Subtype of entity - * @param string $name Name of annotation - * @param mixed $value Value of annotation - * @param int|array $owner_guid Owner(s) of annotation - * @param int $limit Limit - * @param int $offset Offset - * @param string $order_by Order annotations by SQL - * @param int $timelower Lower time limit - * @param int $timeupper Upper time limit - * @param int $entity_owner_guid Owner guid for the entity + * @see elgg_get_entities * - * @return array + * @param array $options Array in format: + * + * annotation_names => NULL|ARR Annotation names + * annotation_values => NULL|ARR Annotation values + * annotation_ids => NULL|ARR annotation ids + * annotation_case_sensitive => BOOL Overall Case sensitive + * annotation_owner_guids => NULL|ARR guids for annotation owners + * annotation_created_time_lower => INT Lower limit for created time. + * annotation_created_time_upper => INT Upper limit for created time. + * annotation_calculation => STR Perform the MySQL function on the annotation values returned. + * Do not confuse this "annotation_calculation" option with the + * "calculation" option to elgg_get_entities_from_annotation_calculation(). + * The "annotation_calculation" option causes this function to + * return the result of performing a mathematical calculation on + * all annotations that match the query instead of ElggAnnotation + * objects. + * See the docs for elgg_get_entities_from_annotation_calculation() + * for the proper use of the "calculation" option. + * + * + * @return ElggAnnotation[]|mixed + * @since 1.8.0 */ -function get_annotations($entity_guid = 0, $entity_type = "", $entity_subtype = "", $name = "", -$value = "", $owner_guid = 0, $limit = 10, $offset = 0, $order_by = "asc", $timelower = 0, -$timeupper = 0, $entity_owner_guid = 0) { - global $CONFIG; - - $timelower = (int) $timelower; - $timeupper = (int) $timeupper; +function elgg_get_annotations(array $options = array()) { - if (is_array($entity_guid)) { - if (sizeof($entity_guid) > 0) { - foreach ($entity_guid as $key => $val) { - $entity_guid[$key] = (int) $val; - } - } else { - $entity_guid = 0; - } + // @todo remove support for count shortcut - see #4393 + if (isset($options['__egefac']) && $options['__egefac']) { + unset($options['__egefac']); } else { - $entity_guid = (int)$entity_guid; - } - - $entity_type = sanitise_string($entity_type); - - if ($entity_subtype) { - if (!$entity_subtype = get_subtype_id($entity_type, $entity_subtype)) { - // requesting a non-existing subtype: return false - return FALSE; - } - } - - if ($name) { - $name = get_metastring_id($name); - - if ($name === false) { - $name = 0; - } - } - if ($value != "") { - $value = get_metastring_id($value); - } - - if (is_array($owner_guid)) { - if (sizeof($owner_guid) > 0) { - foreach ($owner_guid as $key => $val) { - $owner_guid[$key] = (int) $val; - } - } else { - $owner_guid = 0; - } - } else { - $owner_guid = (int)$owner_guid; - } - - if (is_array($entity_owner_guid)) { - if (sizeof($entity_owner_guid) > 0) { - foreach ($entity_owner_guid as $key => $val) { - $entity_owner_guid[$key] = (int) $val; - } - } else { - $entity_owner_guid = 0; - } - } else { - $entity_owner_guid = (int)$entity_owner_guid; - } - - $limit = (int)$limit; - $offset = (int)$offset; - if ($order_by == 'asc') { - $order_by = "a.time_created asc"; - } - - if ($order_by == 'desc') { - $order_by = "a.time_created desc"; - } - - $where = array(); - - if ($entity_guid != 0 && !is_array($entity_guid)) { - $where[] = "a.entity_guid=$entity_guid"; - } else if (is_array($entity_guid)) { - $where[] = "a.entity_guid in (" . implode(",", $entity_guid) . ")"; - } - - if ($entity_type != "") { - $where[] = "e.type='$entity_type'"; - } - - if ($entity_subtype != "") { - $where[] = "e.subtype='$entity_subtype'"; - } + // support shortcut of 'count' => true for 'annotation_calculation' => 'count' + if (isset($options['count']) && $options['count']) { + $options['annotation_calculation'] = 'count'; + unset($options['count']); + } + } + + $options['metastring_type'] = 'annotations'; + return elgg_get_metastring_based_objects($options); +} - if ($owner_guid != 0 && !is_array($owner_guid)) { - $where[] = "a.owner_guid=$owner_guid"; - } else { - if (is_array($owner_guid)) { - $where[] = "a.owner_guid in (" . implode(",", $owner_guid) . ")"; - } +/** + * Deletes annotations based on $options. + * + * @warning Unlike elgg_get_annotations() this will not accept an empty options array! + * This requires at least one constraint: annotation_owner_guid(s), + * annotation_name(s), annotation_value(s), or guid(s) must be set. + * + * @param array $options An options array. {@See elgg_get_annotations()} + * @return bool|null true on success, false on failure, null if no annotations to delete. + * @since 1.8.0 + */ +function elgg_delete_annotations(array $options) { + if (!elgg_is_valid_options_for_batch_operation($options, 'annotations')) { + return false; } - if ($entity_owner_guid != 0 && !is_array($entity_owner_guid)) { - $where[] = "e.owner_guid=$entity_owner_guid"; - } else { - if (is_array($entity_owner_guid)) { - $where[] = "e.owner_guid in (" . implode(",", $entity_owner_guid) . ")"; - } - } + $options['metastring_type'] = 'annotations'; + return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback', false); +} - if ($name !== "") { - $where[] = "a.name_id='$name'"; +/** + * Disables annotations based on $options. + * + * @warning Unlike elgg_get_annotations() this will not accept an empty options array! + * + * @param array $options An options array. {@See elgg_get_annotations()} + * @return bool|null true on success, false on failure, null if no annotations disabled. + * @since 1.8.0 + */ +function elgg_disable_annotations(array $options) { + if (!elgg_is_valid_options_for_batch_operation($options, 'annotations')) { + return false; } + + // if we can see hidden (disabled) we need to use the offset + // otherwise we risk an infinite loop if there are more than 50 + $inc_offset = access_get_show_hidden_status(); - if ($value != "") { - $where[] = "a.value_id='$value'"; - } + $options['metastring_type'] = 'annotations'; + return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', $inc_offset); +} - if ($timelower) { - $where[] = "a.time_created >= {$timelower}"; +/** + * Enables annotations based on $options. + * + * @warning Unlike elgg_get_annotations() this will not accept an empty options array! + * + * @warning In order to enable annotations, you must first use + * {@link access_show_hidden_entities()}. + * + * @param array $options An options array. {@See elgg_get_annotations()} + * @return bool|null true on success, false on failure, null if no metadata enabled. + * @since 1.8.0 + */ +function elgg_enable_annotations(array $options) { + if (!$options || !is_array($options)) { + return false; } - if ($timeupper) { - $where[] = "a.time_created <= {$timeupper}"; - } + $options['metastring_type'] = 'annotations'; + return elgg_batch_metastring_based_objects($options, 'elgg_batch_enable_callback'); +} - $query = "SELECT a.*, n.string as name, v.string as value - FROM {$CONFIG->dbprefix}annotations a - JOIN {$CONFIG->dbprefix}entities e on a.entity_guid = e.guid - JOIN {$CONFIG->dbprefix}metastrings v on a.value_id=v.id - JOIN {$CONFIG->dbprefix}metastrings n on a.name_id = n.id where "; +/** + * Returns a rendered list of annotations with pagination. + * + * @param array $options Annotation getter and display options. + * {@see elgg_get_annotations()} and {@see elgg_list_entities()}. + * + * @return string The list of entities + * @since 1.8.0 + */ +function elgg_list_annotations($options) { + $defaults = array( + 'limit' => 25, + 'offset' => (int) max(get_input('annoff', 0), 0), + ); - foreach ($where as $w) { - $query .= " $w and "; - } - $query .= get_access_sql_suffix("a"); // Add access controls - $query .= " order by $order_by limit $offset,$limit"; // Add order and limit + $options = array_merge($defaults, $options); - return get_data($query, "row_to_elggannotation"); + return elgg_list_entities($options, 'elgg_get_annotations', 'elgg_view_annotation_list'); } /** - * Returns entities based upon annotations. Accepts the same values as - * elgg_get_entities_from_metadata() but uses the annotations table. + * Entities interfaces + */ + +/** + * Returns entities based upon annotations. Also accepts all options available + * to elgg_get_entities() and elgg_get_entities_from_metadata(). * - * NB: Entity creation time is selected as max_time. To sort based upon + * Entity creation time is selected as maxtime. To sort based upon * this, pass 'order_by' => 'maxtime asc' || 'maxtime desc' * - * time_created in this case will be the time the annotation was created. - * * @see elgg_get_entities * @see elgg_get_entities_from_metadata * @@ -343,9 +320,9 @@ $timeupper = 0, $entity_owner_guid = 0) { * annotation_values => NULL|ARR annotations values * * annotation_name_value_pairs => NULL|ARR (name = 'name', value => 'value', - * 'operand' => '=', 'case_sensitive' => TRUE) entries. + * 'operator' => '=', 'case_sensitive' => TRUE) entries. * Currently if multiple values are sent via an array (value => array('value1', 'value2') - * the pair's operand will be forced to "IN". + * 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 @@ -359,7 +336,7 @@ $timeupper = 0, $entity_owner_guid = 0) { * * annotation_owner_guids => NULL|ARR guids for annotaiton owners * - * @return array + * @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()) { @@ -372,6 +349,9 @@ function elgg_get_entities_from_annotations(array $options = array()) { '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', @@ -384,9 +364,10 @@ function elgg_get_entities_from_annotations(array $options = array()) { 'annotation_name_value_pair', 'annotation_owner_guid'); $options = elgg_normalise_plural_options_array($options, $singulars); + $options = elgg_entities_get_metastrings_options('annotation', $options); - if (!$options = elgg_entities_get_metastrings_options('annotation', $options)) { - return FALSE; + if (!$options) { + return false; } // special sorting for annotations @@ -394,727 +375,116 @@ function elgg_get_entities_from_annotations(array $options = array()) { $options['selects'][] = "max(n_table.time_created) as maxtime"; $options['group_by'] = 'n_table.entity_guid'; - return elgg_get_entities($options); -} + $time_wheres = elgg_get_entity_time_where_sql('a', $options['annotation_created_time_upper'], + $options['annotation_created_time_lower']); -/** - * Get entities from annotations - * - * No longer used. - * - * @deprecated 1.7 Use elgg_get_entities_from_annotations() - * - * @param mixed $entity_type Type of entity - * @param mixed $entity_subtype Subtype of entity - * @param string $name Name of annotation - * @param string $value Value of annotation - * @param int $owner_guid Guid of owner of annotation - * @param int $group_guid Guid of group - * @param int $limit Limit - * @param int $offset Offset - * @param string $order_by SQL order by string - * @param bool $count Count or return entities - * @param int $timelower Lower time limit - * @param int $timeupper Upper time limit - * - * @return unknown_type - */ -function get_entities_from_annotations($entity_type = "", $entity_subtype = "", $name = "", -$value = "", $owner_guid = 0, $group_guid = 0, $limit = 10, $offset = 0, $order_by = "asc", -$count = false, $timelower = 0, $timeupper = 0) { - $msg = 'get_entities_from_annotations() is deprecated by elgg_get_entities_from_annotations().'; - elgg_deprecated_notice($msg, 1.7); - - $options = array(); - - $options['annotation_names'] = $name; - - if ($value) { - $options['annotation_values'] = $value; - } - - if ($entity_type) { - $options['types'] = $entity_type; - } - - if ($entity_subtype) { - $options['subtypes'] = $entity_subtype; - } - - if ($owner_guid) { - if (is_array($owner_guid)) { - $options['annotation_owner_guids'] = $owner_guid; - } else { - $options['annotation_owner_guid'] = $owner_guid; - } - } - - if ($group_guid) { - $options['container_guid'] = $group_guid; - } - - if ($limit) { - $options['limit'] = $limit; - } - - if ($offset) { - $options['offset'] = $offset; - } - - if ($order_by) { - $options['order_by'] = "maxtime $order_by"; - } - - if ($count) { - $options['count'] = $count; - } - - return elgg_get_entities_from_annotations($options); -} - -/** - * Lists entities - * - * @see elgg_view_entity_list - * - * @param string $entity_type Type of entity. - * @param string $entity_subtype Subtype of entity. - * @param string $name Name of annotation. - * @param string $value Value of annotation. - * @param int $limit Maximum number of results to return. - * @param int $owner_guid Owner. - * @param int $group_guid Group container. Currently only supported if entity_type is object - * @param boolean $asc Whether to list in ascending or descending order (default: desc) - * @param boolean $fullview Whether to display the entities in full - * @param boolean $viewtypetoggle Can 'gallery' view can be displayed (default: no) - * - * @deprecated 1.7 Use elgg_list_entities_from_annotations() - * @return string Formatted entity list - */ -function list_entities_from_annotations($entity_type = "", $entity_subtype = "", $name = "", -$value = "", $limit = 10, $owner_guid = 0, $group_guid = 0, $asc = false, $fullview = true, -$viewtypetoggle = false) { - - $msg = 'list_entities_from_annotations is deprecated by elgg_list_entities_from_annotations'; - elgg_deprecated_notice($msg, 1.8); - - $options = array(); - - if ($entity_type) { - $options['types'] = $entity_type; - } - - if ($entity_subtype) { - $options['subtypes'] = $entity_subtype; - } - - if ($name) { - $options['annotation_names'] = $name; - } - - if ($value) { - $options['annotation_values'] = $value; - } - - if ($limit) { - $options['limit'] = $limit; - } - - if ($owner_guid) { - $options['annotation_owner_guid'] = $owner_guid; - } - - if ($group_guid) { - $options['container_guid'] = $group_guid; - } - - if ($asc) { - $options['order_by'] = 'maxtime desc'; + if ($time_wheres) { + $options['wheres'] = array_merge($options['wheres'], $time_wheres); } - if ($offset = sanitise_int(get_input('offset', null))) { - $options['offset'] = $offset; - } - - $options['full_view'] = $fullview; - $options['view_type_toggle'] = $viewtypetoggle; - $options['pagination'] = $pagination; - - return elgg_list_entities_from_annotations($options); + return elgg_get_entities_from_metadata($options); } /** * Returns a viewable list of entities from annotations. * - * @param array $options - * + * @param array $options Options array + * * @see elgg_get_entities_from_annotations() * @see elgg_list_entities() * - * @return str + * @return string */ function elgg_list_entities_from_annotations($options = array()) { return elgg_list_entities($options, 'elgg_get_entities_from_annotations'); } /** - * Returns a human-readable list of annotations on a particular entity. - * - * @param int $entity_guid The entity GUID - * @param string $name The name of the kind of annotation - * @param int $limit The number of annotations to display at once - * @param true|false $asc Display annotations in ascending order. (Default: true) - * - * @return string HTML (etc) version of the annotation list - */ -function list_annotations($entity_guid, $name = "", $limit = 25, $asc = true) { - if ($asc) { - $asc = "asc"; - } else { - $asc = "desc"; - } - $count = count_annotations($entity_guid, "", "", $name); - $offset = (int) get_input("annoff", 0); - $annotations = get_annotations($entity_guid, "", "", $name, "", "", $limit, $offset, $asc); - - return elgg_view_annotation_list($annotations, $count, $offset, $limit); -} - -/** - * Return the sum of a given integer annotation. - * - * @param int $entity_guid Guid of Entity - * @param string $entity_type Type of Entity - * @param string $entity_subtype Subtype of Entity - * @param string $name Name of annotation - * @param string $value Value of annotation - * @param string $value_type Type of value - * @param int $owner_guid GUID of owner of annotation - * - * @return int - */ -function get_annotations_sum($entity_guid, $entity_type = "", $entity_subtype = "", $name = "", -$value = "", $value_type = "", $owner_guid = 0) { - - return get_annotations_calculate_x("sum", $entity_guid, $entity_type, $entity_subtype, $name, - $value, $value_type, $owner_guid); -} - -/** - * Return the max of a given integer annotation. - * - * @param int $entity_guid Guid of Entity - * @param string $entity_type Type of Entity - * @param string $entity_subtype Subtype of Entity - * @param string $name Name of annotation - * @param string $value Value of annotation - * @param string $value_type Type of value - * @param int $owner_guid GUID of owner of annotation - * - * @return int - */ -function get_annotations_max($entity_guid, $entity_type = "", $entity_subtype = "", $name = "", -$value = "", $value_type = "", $owner_guid = 0) { - - return get_annotations_calculate_x("max", $entity_guid, $entity_type, $entity_subtype, $name, - $value, $value_type, $owner_guid); -} - -/** - * Return the minumum of a given integer annotation. - * - * @param int $entity_guid Guid of Entity - * @param string $entity_type Type of Entity - * @param string $entity_subtype Subtype of Entity - * @param string $name Name of annotation - * @param string $value Value of annotation - * @param string $value_type Type of value - * @param int $owner_guid GUID of owner of annotation - * - * @return int - */ -function get_annotations_min($entity_guid, $entity_type = "", $entity_subtype = "", $name = "", -$value = "", $value_type = "", $owner_guid = 0) { - - return get_annotations_calculate_x("min", $entity_guid, $entity_type, $entity_subtype, $name, - $value, $value_type, $owner_guid); -} - -/** - * Return the average of a given integer annotation. - * - * @param int $entity_guid Guid of Entity - * @param string $entity_type Type of Entity - * @param string $entity_subtype Subtype of Entity - * @param string $name Name of annotation - * @param string $value Value of annotation - * @param string $value_type Type of value - * @param int $owner_guid GUID of owner of annotation - * - * @return int - */ -function get_annotations_avg($entity_guid, $entity_type = "", $entity_subtype = "", $name = "", -$value = "", $value_type = "", $owner_guid = 0) { - - return get_annotations_calculate_x("avg", $entity_guid, $entity_type, $entity_subtype, $name, - $value, $value_type, $owner_guid); -} - -/** - * Count the number of annotations based on search parameters - * - * @param int $entity_guid Guid of Entity - * @param string $entity_type Type of Entity - * @param string $entity_subtype Subtype of Entity - * @param string $name Name of annotation - * @param string $value Value of annotation - * @param string $value_type Type of value - * @param int $owner_guid GUID of owner of annotation - * @param int $timelower Lower time limit - * @param int $timeupper Upper time limit - * - * @return int - */ -function count_annotations($entity_guid = 0, $entity_type = "", $entity_subtype = "", -$name = "", $value = "", $value_type = "", $owner_guid = 0, $timelower = 0, -$timeupper = 0) { - return get_annotations_calculate_x("count", $entity_guid, $entity_type, $entity_subtype, - $name, $value, $value_type, $owner_guid, $timelower, $timeupper); -} - -/** - * Perform a mathmatical calculation on integer annotations. - * - * @param string $sum What sort of calculation to perform - * @param int $entity_guid Guid of Entity - * @param string $entity_type Type of Entity - * @param string $entity_subtype Subtype of Entity - * @param string $name Name of annotation - * @param string $value Value of annotation - * @param string $value_type Type of value - * @param int $owner_guid GUID of owner of annotation - * @param int $timelower Lower time limit - * @param int $timeupper Upper time limit - * - * @return int + * Get entities ordered by a mathematical calculation on annotation values + * + * @param array $options An options array: + * 'calculation' => The calculation to use. Must be a valid MySQL function. + * Defaults to sum. Result selected as 'annotation_calculation'. + * Don't confuse this "calculation" option with the + * "annotation_calculation" option to elgg_get_annotations(). + * This "calculation" option is applied to each entity's set of + * annotations and is selected as annotation_calculation for that row. + * See the docs for elgg_get_annotations() for proper use of the + * "annotation_calculation" option. + * 'order_by' => The order for the sorting. Defaults to 'annotation_calculation desc'. + * 'annotation_names' => The names of annotations on the entity. + * 'annotation_values' => The values of annotations on the entity. + * + * 'metadata_names' => The name of metadata on the entity. + * 'metadata_values' => The value of metadata on the entitiy. + * + * @return mixed If count, int. If not count, array. false on errors. */ -function get_annotations_calculate_x($sum = "avg", $entity_guid, $entity_type = "", -$entity_subtype = "", $name = "", $value = "", $value_type = "", $owner_guid = 0, -$timelower = 0, $timeupper = 0) { - - global $CONFIG; - - $sum = sanitise_string($sum); - $entity_guid = (int)$entity_guid; - $entity_type = sanitise_string($entity_type); - $timeupper = (int)$timeupper; - $timelower = (int)$timelower; - - if ($entity_subtype) { - if (!$entity_subtype = get_subtype_id($entity_type, $entity_subtype)) { - // requesting a non-existing subtype: return false - return FALSE; - } - } - - if ($name != '' AND !$name = get_metastring_id($name)) { - return 0; - } - - if ($value != '' AND !$value = get_metastring_id($value)) { - return 0; - } - $value_type = sanitise_string($value_type); - $owner_guid = (int)$owner_guid; - - // if (empty($name)) return 0; - - $where = array(); - - if ($entity_guid) { - $where[] = "e.guid=$entity_guid"; - } - - if ($entity_type != "") { - $where[] = "e.type='$entity_type'"; - } - - if ($entity_subtype) { - $where[] = "e.subtype=$entity_subtype"; - } - - if ($name != "") { - $where[] = "a.name_id='$name'"; - } - - if ($value != "") { - $where[] = "a.value_id='$value'"; - } - - if ($value_type != "") { - $where[] = "a.value_type='$value_type'"; - } - - if ($owner_guid) { - $where[] = "a.owner_guid='$owner_guid'"; - } - - if ($timelower) { - $where[] = "a.time_created >= {$timelower}"; - } - - if ($timeupper) { - $where[] = "a.time_created <= {$timeupper}"; - } - - if ($sum != "count") { - $where[] = "a.value_type='integer'"; // Limit on integer types - } - - $query = "SELECT $sum(ms.string) as sum - FROM {$CONFIG->dbprefix}annotations a - JOIN {$CONFIG->dbprefix}entities e on a.entity_guid = e.guid - JOIN {$CONFIG->dbprefix}metastrings ms on a.value_id=ms.id WHERE "; - - foreach ($where as $w) { - $query .= " $w and "; - } - - $query .= get_access_sql_suffix("a"); // now add access - $query .= ' and ' . get_access_sql_suffix("e"); // now add access - - $row = get_data_row($query); - if ($row) { - return $row->sum; - } - - return false; -} - -/** - * Get entities ordered by a mathematical calculation - * - * @param string $sum What sort of calculation to perform - * @param string $entity_type Type of Entity - * @param string $entity_subtype Subtype of Entity - * @param string $name Name of annotation - * @param string $mdname Metadata name - * @param string $mdvalue Metadata value - * @param int $owner_guid GUID of owner of annotation - * @param int $limit Limit of results - * @param int $offset Offset of results - * @param string $orderdir Order of results - * @param bool $count Return count or entities - * - * @return mixed - */ -function get_entities_from_annotations_calculate_x($sum = "sum", $entity_type = "", -$entity_subtype = "", $name = "", $mdname = '', $mdvalue = '', $owner_guid = 0, -$limit = 10, $offset = 0, $orderdir = 'desc', $count = false) { - global $CONFIG; - - $sum = sanitise_string($sum); - $entity_type = sanitise_string($entity_type); - - if ($entity_subtype) { - if (!$entity_subtype = get_subtype_id($entity_type, $entity_subtype)) { - // requesting a non-existing subtype: return false - return FALSE; - } - } - - $name = get_metastring_id($name); - $limit = (int) $limit; - $offset = (int) $offset; - $owner_guid = (int) $owner_guid; - if (!empty($mdname) && !empty($mdvalue)) { - $meta_n = get_metastring_id($mdname); - $meta_v = get_metastring_id($mdvalue); - } - - if (empty($name)) { - return 0; - } - - $where = array(); - - if ($entity_type != "") { - $where[] = "e.type='$entity_type'"; - } - - if ($owner_guid > 0) { - $where[] = "e.container_guid = $owner_guid"; - } - - if ($entity_subtype) { - $where[] = "e.subtype=$entity_subtype"; - } - - if ($name != "") { - $where[] = "a.name_id='$name'"; - } - - if (!empty($mdname) && !empty($mdvalue)) { - if ($mdname != "") { - $where[] = "m.name_id='$meta_n'"; - } - - if ($mdvalue != "") { - $where[] = "m.value_id='$meta_v'"; - } - } - - if ($sum != "count") { - // Limit on integer types - $where[] = "a.value_type='integer'"; - } - - if (!$count) { - $query = "SELECT distinct e.*, $sum(ms.string) as sum "; - } else { - $query = "SELECT count(distinct e.guid) as num, $sum(ms.string) as sum "; - } - $query .= " from {$CONFIG->dbprefix}entities e" - . " JOIN {$CONFIG->dbprefix}annotations a on a.entity_guid = e.guid" - . " JOIN {$CONFIG->dbprefix}metastrings ms on a.value_id=ms.id "; - - if (!empty($mdname) && !empty($mdvalue)) { - $query .= " JOIN {$CONFIG->dbprefix}metadata m on m.entity_guid = e.guid "; - } - - $query .= " WHERE "; - foreach ($where as $w) { - $query .= " $w and "; - } - - $query .= get_access_sql_suffix("a"); // now add access - $query .= ' and ' . get_access_sql_suffix("e"); // now add access - if (!$count) { - $query .= ' group by e.guid'; - } - - if (!$count) { - $query .= ' order by sum ' . $orderdir; - $query .= ' limit ' . $offset . ' , ' . $limit; - return get_data($query, "entity_row_to_elggstar"); - } else { - if ($row = get_data_row($query)) { - return $row->num; - } - } - return false; -} - -/** - * Returns entities ordered by the sum of an annotation - * - * @param string $entity_type Type of Entity - * @param string $entity_subtype Subtype of Entity - * @param string $name Name of annotation - * @param string $mdname Metadata name - * @param string $mdvalue Metadata value - * @param int $owner_guid GUID of owner of annotation - * @param int $limit Limit of results - * @param int $offset Offset of results - * @param string $orderdir Order of results - * @param bool $count Return count or entities - * - * @return unknown - */ -function get_entities_from_annotation_count($entity_type = "", $entity_subtype = "", $name = "", -$mdname = '', $mdvalue = '', $owner_guid = 0, $limit = 10, $offset = 0, $orderdir = 'desc', -$count = false) { - - return get_entities_from_annotations_calculate_x('sum', $entity_type, $entity_subtype, - $name, $mdname, $mdvalue, $owner_guid, $limit, $offset, $orderdir, $count); -} - -/** - * Lists entities by the totals of a particular kind of annotation - * - * @param string $entity_type Type of entity. - * @param string $entity_subtype Subtype of entity. - * @param string $name Name of annotation. - * @param int $limit Maximum number of results to return. - * @param int $owner_guid Owner. - * @param int $group_guid Group container. Currently only supported if entity_type is object - * @param boolean $asc Whether to list in ascending or descending order (default: desc) - * @param boolean $fullview Whether to display the entities in full - * @param boolean $viewtypetoggle Can the 'gallery' view can be displayed (default: no) - * @param boolean $pagination Add pagination - * @param string $orderdir Order desc or asc - * - * @return string Formatted entity list - */ -function list_entities_from_annotation_count($entity_type = "", $entity_subtype = "", $name = "", -$limit = 10, $owner_guid = 0, $group_guid = 0, $asc = false, $fullview = true, -$viewtypetoggle = false, $pagination = true, $orderdir = 'desc') { - if ($asc) { - $asc = "asc"; - } else { - $asc = "desc"; - } - - $offset = (int) get_input("offset", 0); - $count = get_entities_from_annotation_count($entity_type, $entity_subtype, $name, - '', '', $owner_guid, $limit, $offset, $orderdir, true); - - $entities = get_entities_from_annotation_count($entity_type, $entity_subtype, $name, - '', '', $owner_guid, $limit, $offset, $orderdir, false); - - return elgg_view_entity_list($entities, $count, $offset, $limit, - $fullview, $viewtypetoggle, $pagination); -} - -/** - * Lists entities by the totals of a particular kind of annotation AND - * the value of a piece of metadata - * - * @param string $entity_type Type of entity. - * @param string $entity_subtype Subtype of entity. - * @param string $name Name of annotation. - * @param string $mdname Metadata name - * @param string $mdvalue Metadata value - * @param int $limit Maximum number of results to return. - * @param int $owner_guid Owner. - * @param int $group_guid Group container. Currently only supported if entity_type is object - * @param boolean $asc Whether to list in ascending or descending order (default: desc) - * @param boolean $fullview Whether to display the entities in full - * @param boolean $viewtypetoggle Can the 'gallery' view can be displayed (default: no) - * @param boolean $pagination Display pagination - * @param string $orderdir 'desc' or 'asc' - * - * @return string Formatted entity list - */ -function list_entities_from_annotation_count_by_metadata($entity_type = "", $entity_subtype = "", -$name = "", $mdname = '', $mdvalue = '', $limit = 10, $owner_guid = 0, $group_guid = 0, -$asc = false, $fullview = true, $viewtypetoggle = false, $pagination = true, $orderdir = 'desc') { +function elgg_get_entities_from_annotation_calculation($options) { + $db_prefix = elgg_get_config('dbprefix'); + $defaults = array( + 'calculation' => 'sum', + 'order_by' => 'annotation_calculation desc' + ); - if ($asc) { - $asc = "asc"; - } else { - $asc = "desc"; - } + $options = array_merge($defaults, $options); - $offset = (int) get_input("offset", 0); - $count = get_entities_from_annotation_count($entity_type, $entity_subtype, $name, $mdname, - $mdvalue, $owner_guid, $limit, $offset, $orderdir, true); - $entities = get_entities_from_annotation_count($entity_type, $entity_subtype, $name, $mdname, - $mdvalue, $owner_guid, $limit, $offset, $orderdir, false); + $function = sanitize_string(elgg_extract('calculation', $options, 'sum', false)); - return elgg_view_entity_list($entities, $count, $offset, $limit, $fullview, - $viewtypetoggle, $pagination); -} + // you must cast this as an int or it sorts wrong. + $options['selects'][] = 'e.*'; + $options['selects'][] = "$function(cast(a_msv.string as signed)) as annotation_calculation"; -/** - * Delete a given annotation. - * - * @param int $id The annotation id - * - * @return bool - */ -function delete_annotation($id) { - global $CONFIG; + // need our own join to get the values because the lower level functions don't + // add all the joins if it's a different callback. + $options['joins'][] = "JOIN {$db_prefix}metastrings a_msv ON n_table.value_id = a_msv.id"; - $id = (int)$id; + // don't need access control because it's taken care of by elgg_get_annotations. + $options['group_by'] = 'n_table.entity_guid'; - $access = get_access_sql_suffix(); - $annotation = get_annotation($id); + $options['callback'] = 'entity_row_to_elggstar'; - if (trigger_elgg_event('delete', 'annotation', $annotation)) { - remove_from_river_by_annotation($id); - return delete_data("DELETE from {$CONFIG->dbprefix}annotations where id=$id and $access"); - } + // see #4393 + // @todo remove after the 'count' shortcut is removed from elgg_get_annotations() + $options['__egefac'] = true; - return FALSE; + return elgg_get_annotations($options); } /** - * Clear all the annotations for a given entity, assuming you have access to that metadata. + * List entities from an annotation calculation. * - * @param int $guid The entity guid - * @param string $name The name of the annotation to delete. - * - * @return int Number of annotations deleted or false if an error - */ -function clear_annotations($guid, $name = "") { - global $CONFIG; - - $guid = (int)$guid; - - if (!empty($name)) { - $name = get_metastring_id($name); - if ($name === false) { - // name doesn't exist so 0 rows were deleted - return 0; - } - } - - $entity_guid = (int) $guid; - if ($entity = get_entity($entity_guid)) { - if ($entity->canEdit()) { - $where = array(); - - if ($name != "") { - $where[] = " name_id='$name'"; - } - - $query = "DELETE from {$CONFIG->dbprefix}annotations where entity_guid=$guid "; - foreach ($where as $w) { - $query .= " and $w"; - } - - return delete_data($query); - } - } - - return FALSE; -} - -/** - * Clear all annotations belonging to a given owner_guid + * @see elgg_get_entities_from_annotation_calculation() * - * @param int $owner_guid The owner + * @param array $options An options array. * - * @return int Number of annotations deleted + * @return string */ -function clear_annotations_by_owner($owner_guid) { - global $CONFIG; - - $owner_guid = (int)$owner_guid; - - $query = "SELECT id from {$CONFIG->dbprefix}annotations WHERE owner_guid=$owner_guid"; - - $annotations = get_data($query); - $deleted = 0; - - if (!$annotations) { - return 0; - } - - foreach ($annotations as $id) { - // Is this the best way? - if (delete_annotation($id->id)) { - $deleted++; - } - } +function elgg_list_entities_from_annotation_calculation($options) { + $defaults = array( + 'calculation' => 'sum', + 'order_by' => 'annotation_calculation desc' + ); + $options = array_merge($defaults, $options); - return $deleted; + return elgg_list_entities($options, 'elgg_get_entities_from_annotation_calculation'); } /** - * Handler called by trigger_plugin_hook on the "export" event. + * Export the annotations for the specified entity * * @param string $hook 'export' - * @param string $entity_type 'all' + * @param string $type 'all' * @param mixed $returnvalue Default return value - * @param mixed $params List of params to export + * @param mixed $params Parameters determining what annotations to export * * @elgg_plugin_hook export all * - * @return mixed + * @return array + * @throws InvalidParameterException + * @access private */ -function export_annotation_plugin_hook($hook, $entity_type, $returnvalue, $params) { +function export_annotation_plugin_hook($hook, $type, $returnvalue, $params) { // Sanity check values if ((!is_array($params)) && (!isset($params['guid']))) { throw new InvalidParameterException(elgg_echo('InvalidParameterException:GUIDNotForExport')); @@ -1125,9 +495,12 @@ function export_annotation_plugin_hook($hook, $entity_type, $returnvalue, $param } $guid = (int)$params['guid']; - $name = $params['name']; + $options = array('guid' => $guid, 'limit' => 0); + if (isset($params['name'])) { + $options['annotation_name'] = $params['name']; + } - $result = get_annotations($guid); + $result = elgg_get_annotations($options); if ($result) { foreach ($result as $r) { @@ -1149,7 +522,7 @@ function export_annotation_plugin_hook($hook, $entity_type, $returnvalue, $param function get_annotation_url($id) { $id = (int)$id; - if ($extender = get_annotation($id)) { + if ($extender = elgg_get_annotation_from_id($id)) { return get_extender_url($extender); } return false; @@ -1162,24 +535,26 @@ function get_annotation_url($id) { * @param string $annotation_type Type of annotation * @param int $owner_guid Defaults to logged in user. * - * @return true | false + * @return bool + * @since 1.8.0 */ function elgg_annotation_exists($entity_guid, $annotation_type, $owner_guid = NULL) { global $CONFIG; - if (!$owner_guid && !($owner_guid = get_loggedin_userid())) { + if (!$owner_guid && !($owner_guid = elgg_get_logged_in_user_guid())) { return FALSE; } - $entity_guid = (int)$entity_guid; - $annotation_type = sanitise_string($annotation_type); + $entity_guid = sanitize_int($entity_guid); + $owner_guid = sanitize_int($owner_guid); + $annotation_type = sanitize_string($annotation_type); - $sql = "select a.id" . - " FROM {$CONFIG->dbprefix}annotations a, {$CONFIG->dbprefix}metastrings m " . - " WHERE a.owner_guid={$owner_guid} AND a.entity_guid={$entity_guid} " . - " AND a.name_id=m.id AND m.string='{$annotation_type}'"; + $sql = "SELECT a.id FROM {$CONFIG->dbprefix}annotations a" . + " JOIN {$CONFIG->dbprefix}metastrings m ON a.name_id = m.id" . + " WHERE a.owner_guid = $owner_guid AND a.entity_guid = $entity_guid" . + " AND m.string = '$annotation_type'"; - if ($check_annotation = get_data_row($sql)) { + if (get_data_row($sql)) { return TRUE; } @@ -1187,16 +562,57 @@ function elgg_annotation_exists($entity_guid, $annotation_type, $owner_guid = NU } /** + * Return the URL for a comment + * + * @param ElggAnnotation $comment The comment object + * @return string + * @access private + */ +function elgg_comment_url_handler(ElggAnnotation $comment) { + $entity = $comment->getEntity(); + if ($entity) { + return $entity->getURL() . '#item-annotation-' . $comment->id; + } + return ""; +} + +/** * Register an annotation url handler. * - * @param string $function_name The function. * @param string $extender_name The name, default 'all'. + * @param string $function_name The function. * * @return string */ -function register_annotation_url_handler($function_name, $extender_name = "all") { - return register_extender_url_handler($function_name, 'annotation', $extender_name); +function elgg_register_annotation_url_handler($extender_name = "all", $function_name) { + return elgg_register_extender_url_handler('annotation', $extender_name, $function_name); +} + +/** + * Register annotation unit tests + * + * @param string $hook + * @param string $type + * @param array $value + * @param array $params + * @return array + * @access private + */ +function annotations_test($hook, $type, $value, $params) { + global $CONFIG; + $value[] = $CONFIG->path . 'engine/tests/api/annotations.php'; + return $value; +} + +/** + * Initialize the annotation library + * @access private + */ +function elgg_annotations_init() { + elgg_register_annotation_url_handler('generic_comment', 'elgg_comment_url_handler'); + + elgg_register_plugin_hook_handler("export", "all", "export_annotation_plugin_hook", 2); + elgg_register_plugin_hook_handler('unit_test', 'system', 'annotations_test'); } -/** Register the hook */ -register_plugin_hook("export", "all", "export_annotation_plugin_hook", 2); +elgg_register_event_handler('init', 'system', 'elgg_annotations_init'); |
