diff options
Diffstat (limited to 'engine/lib/annotations.php')
| -rw-r--r-- | engine/lib/annotations.php | 270 |
1 files changed, 175 insertions, 95 deletions
diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php index 130ab37ab..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; } @@ -29,7 +31,7 @@ function row_to_elggannotation($row) { * * @param int $id The id of the annotation object being retrieved. * - * @return false|ElggAnnotation + * @return ElggAnnotation|false */ function elgg_get_annotation_from_id($id) { return elgg_get_metastring_based_object_from_id($id, 'annotations'); @@ -55,14 +57,14 @@ function elgg_delete_annotation_by_id($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; @@ -94,8 +96,6 @@ $owner_guid, $access_id = ACCESS_PRIVATE) { $entity = get_entity($entity_guid); if (elgg_trigger_event('annotate', $entity->type, $entity)) { - system_log($entity, 'annotate'); - // 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 @@ -158,17 +158,13 @@ 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) { + // @todo add plugin hook that sends old and new annotation information before db access $obj = elgg_get_annotation_from_id($annotation_id); - if (elgg_trigger_event('update', 'annotation', $obj)) { - return true; - } else { - // @todo add plugin hook that sends old and new annotation information before db access - elgg_delete_annotation_by_id($annotation_id); - } + elgg_trigger_event('update', 'annotation', $obj); } return $result; @@ -182,26 +178,40 @@ function update_annotation($annotation_id, $name, $value, $value_type, $owner_gu * * @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. - * - * @return mixed + * 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 elgg_get_annotations(array $options = array()) { + + // @todo remove support for count shortcut - see #4393 + if (isset($options['__egefac']) && $options['__egefac']) { + unset($options['__egefac']); + } else { + // 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); } @@ -210,10 +220,12 @@ function elgg_get_annotations(array $options = array()) { * 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 mixed - * @since 1.8 + * @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')) { @@ -221,7 +233,7 @@ function elgg_delete_annotations(array $options) { } $options['metastring_type'] = 'annotations'; - return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback'); + return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback', false); } /** @@ -230,16 +242,20 @@ function elgg_delete_annotations(array $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 mixed - * @since 1.8 + * @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(); - $options['metastrings_type'] = 'annotations'; - return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback'); + $options['metastring_type'] = 'annotations'; + return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', $inc_offset); } /** @@ -247,9 +263,12 @@ function elgg_disable_annotations(array $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 mixed - * @since 1.8 + * @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)) { @@ -267,7 +286,7 @@ function elgg_enable_annotations(array $options) { * {@see elgg_get_annotations()} and {@see elgg_list_entities()}. * * @return string The list of entities - * @since 1.8 + * @since 1.8.0 */ function elgg_list_annotations($options) { $defaults = array( @@ -285,14 +304,12 @@ function elgg_list_annotations($options) { */ /** - * Returns entities based upon annotations. Accepts the same values as - * elgg_get_entities_from_metadata() but uses the annotations table. + * 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 * @@ -319,9 +336,7 @@ function elgg_list_annotations($options) { * * annotation_owner_guids => NULL|ARR guids for annotaiton owners * - * annotation_ids => NULL|ARR Annotation IDs - * - * @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()) { @@ -339,8 +354,6 @@ function elgg_get_entities_from_annotations(array $options = array()) { 'annotation_owner_guids' => ELGG_ENTITIES_ANY_VALUE, - 'annotation_ids' => ELGG_ENTITIES_ANY_VALUE, - 'order_by' => 'maxtime desc', 'group_by' => 'a.entity_guid' ); @@ -348,12 +361,13 @@ function elgg_get_entities_from_annotations(array $options = array()) { $options = array_merge($defaults, $options); $singulars = array('annotation_name', 'annotation_value', - 'annotation_name_value_pair', 'annotation_owner_guid', 'annotation_id'); + '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 @@ -379,28 +393,38 @@ function elgg_get_entities_from_annotations(array $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'); } /** - * Get entities ordered by a mathematical calculation + * 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 'calculated'. - * 'order_by' => The order for the sorting. Defaults to 'calculated desc'. - * - * @return mixed + * '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 elgg_get_entities_from_annotation_calculation($options) { - global $CONFIG; - + $db_prefix = elgg_get_config('dbprefix'); $defaults = array( - 'calculation' => 'sum', - 'order_by' => 'calculated desc', + 'calculation' => 'sum', + 'order_by' => 'annotation_calculation desc' ); $options = array_merge($defaults, $options); @@ -408,17 +432,23 @@ function elgg_get_entities_from_annotation_calculation($options) { $function = sanitize_string(elgg_extract('calculation', $options, 'sum', false)); // you must cast this as an int or it sorts wrong. - $options['selects'][] = "$function(cast(msv.string as signed)) as calculated"; - $options['selects'][] = "msn.string as value"; - $options['order_by'] = 'calculated desc'; + $options['selects'][] = 'e.*'; + $options['selects'][] = "$function(cast(a_msv.string as signed)) as annotation_calculation"; - // need our own join to get the values. - $db_prefix = get_config('dbprefix'); - $options['joins'][] = "JOIN {$db_prefix}annotations calc_table on e.guid = calc_table.entity_guid"; - $options['joins'][] = "JOIN {$db_prefix}metastrings msv on calc_table.value_id = msv.id"; - $options['wheres'][] = "calc_table.name_id = n_table.name_id"; + // 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"; - return elgg_get_entities_from_annotations($options); + // don't need access control because it's taken care of by elgg_get_annotations. + $options['group_by'] = 'n_table.entity_guid'; + + $options['callback'] = 'entity_row_to_elggstar'; + + // see #4393 + // @todo remove after the 'count' shortcut is removed from elgg_get_annotations() + $options['__egefac'] = true; + + return elgg_get_annotations($options); } /** @@ -431,22 +461,30 @@ function elgg_get_entities_from_annotation_calculation($options) { * @return string */ function elgg_list_entities_from_annotation_calculation($options) { + $defaults = array( + 'calculation' => 'sum', + 'order_by' => 'annotation_calculation desc' + ); + $options = array_merge($defaults, $options); + 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')); @@ -457,12 +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 = elgg_get_annotations(array( - 'guid' => $guid, - 'limit' => 0 - )); + $result = elgg_get_annotations($options); if ($result) { foreach ($result as $r) { @@ -507,15 +545,16 @@ function elgg_annotation_exists($entity_guid, $annotation_type, $owner_guid = NU 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; } @@ -523,10 +562,25 @@ 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 */ @@ -534,5 +588,31 @@ function elgg_register_annotation_url_handler($extender_name = "all", $function_ return elgg_register_extender_url_handler('annotation', $extender_name, $function_name); } -/** Register the hook */ -elgg_register_plugin_hook_handler("export", "all", "export_annotation_plugin_hook", 2); +/** + * 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'); +} + +elgg_register_event_handler('init', 'system', 'elgg_annotations_init'); |
