diff options
Diffstat (limited to 'engine/lib/annotations.php')
| -rw-r--r-- | engine/lib/annotations.php | 1011 |
1 files changed, 594 insertions, 417 deletions
diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php index 0a06b2afe..5e9b530de 100644 --- a/engine/lib/annotations.php +++ b/engine/lib/annotations.php @@ -1,441 +1,618 @@ <?php - /** - * Elgg annotations - * Functions to manage object annotations. - * - * @package Elgg - * @subpackage Core - * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2 - * @author Marcus Povey <marcus@dushka.co.uk> - * @copyright Curverider Ltd 2008 - * @link http://elgg.org/ - */ - - require_once('extender.php'); // include the superclass - - /** - * @class ElggAnnotation - * An annotation is similar to metadata each entity can contain more than one of each annotation. - * @author Marcus Povey <marcus@dushka.co.uk> - */ - class ElggAnnotation extends ElggExtender - { - - /** - * Construct a new site object, optionally from a given id value or db row. - * - * @param mixed $id - */ - function __construct($id = null) - { - $this->attributes = array(); - - if (!empty($id)) { - if ($id instanceof stdClass) - $annotation = $id; - else - $annotation = get_annotation($id); - - if ($annotation) { - $objarray = (array) $annotation; - foreach($objarray as $key => $value) { - $this->attributes[$key] = $value; - } - } - } - } - - function __get($name) { - return $this->get($name); - } - - function __set($name, $value) { - return $this->set($name, $value); - } - - function save() - { - if ($this->id > 0) - return update_annotation($this->id, $this->name, $this->value, $this->value_type, $this->owner_guid, $this->access_id); - else - { - $this->id = create_annotation($this->entity_guid, $this->name, $this->value, $this->value_type, $this->owner_guid, $this->access_id); - if (!$this->id) throw new IOException("Unable to save new ElggAnnotation"); - return $this->id; - } - } - - /** - * Delete a given site. - */ - function delete() - { - return delete_annotation($this->id); - } +/** + * Elgg annotations + * Functions to manage object annotations. + * + * @package Elgg + * @subpackage Core + */ +/** + * Convert a database row to a new ElggAnnotation + * + * @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; } - - /** - * Convert a database row to a new ElggAnnotation - * - * @param stdClass $row - * @return stdClass or ElggAnnotation - */ - function row_to_elggannotation($row) - { - if (!($row instanceof stdClass)) - return $row; - - return new ElggAnnotation($row); + + return new ElggAnnotation($row); +} + +/** + * Get a specific annotation by its id. + * If you want multiple annotation objects, use + * {@link elgg_get_annotations()}. + * + * @param int $id The id of the annotation object being retrieved. + * + * @return ElggAnnotation|false + */ +function elgg_get_annotation_from_id($id) { + return elgg_get_metastring_based_object_from_id($id, 'annotations'); +} + +/** + * 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; } - - /** - * Detect the value_type for a given value. - * Currently this is very crude. - * - * TODO: Make better! - * - * @param mixed $value - * @param string $value_type If specified, overrides the detection. - * @return string - */ - function detect_annotation_valuetype($value, $value_type = "") - { - if ($value_type!="") - return $value_type; - - // This is crude - if (is_int($value)) return 'integer'; - - return 'tag'; + return $annotation->delete(); +} + +/** + * Create a new annotation. + * + * @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 (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 = 0, $access_id = ACCESS_PRIVATE) { + global $CONFIG; + + $result = false; + + $entity_guid = (int)$entity_guid; + //$name = sanitise_string(trim($name)); + //$value = sanitise_string(trim($value)); + $value_type = detect_extender_valuetype($value, sanitise_string(trim($value_type))); + + $owner_guid = (int)$owner_guid; + if ($owner_guid == 0) { + $owner_guid = elgg_get_logged_in_user_guid(); } - - /** - * Get a specific annotation. - * - * @param int $annotation_id - */ - function get_annotation($annotation_id) - { - global $CONFIG; - - $annotation_id = (int) $annotation_id; - $access = get_access_list(); - - return row_to_elggannotation(get_data_row("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 (a.access_id in {$access} or (a.access_id = 0 and a.owner_guid = {$_SESSION['id']}))")); + + $access_id = (int)$access_id; + $time = time(); + + // Add the metastring + $value = add_metastring($value); + if (!$value) { + return false; } - - /** - * Create a new annotation. - * - * @param int $entity_guid - * @param string $name - * @param string $value - * @param string $value_type - * @param int $owner_guid - * @param int $access_id - */ - function create_annotation($entity_guid, $name, $value, $value_type, $owner_guid, $access_id = 0) - { - global $CONFIG; - - $entity_guid = (int)$entity_guid; - $name = sanitise_string(trim($name)); - $value = sanitise_string(trim($value)); - $value_type = detect_annotation_valuetype($value, sanitise_string(trim($value_type))); - - $owner_guid = (int)$owner_guid; - if ($owner_guid==0) $owner_guid = $_SESSION['id']; - - $access_id = (int)$access_id; - - $time = time(); - - // Add the metastring - $value = add_metastring($value); - if (!$value) return false; - - $name = add_metastring($name); - if (!$name) return false; - + + $name = add_metastring($name); + if (!$name) { + return false; + } + + $entity = get_entity($entity_guid); + + if (elgg_trigger_event('annotate', $entity->type, $entity)) { // If ok then add it - return 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)"); + $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 = elgg_get_annotation_from_id($result); + if (elgg_trigger_event('create', 'annotation', $obj)) { + return $result; + } else { + // plugin returned false to reject annotation + elgg_delete_annotation_by_id($result); + return FALSE; + } + } } - - /** - * Update an annotation. - * - * @param int $annotation_id - * @param string $name - * @param string $value - * @param string $value_type - * @param int $owner_guid - * @param int $access_id - */ - function update_annotation($annotation_id, $name, $value, $value_type, $owner_guid, $access_id) - { - global $CONFIG; - - $annotation_id = (int)$annotation_id; - $name = sanitise_string(trim($name)); - $value = sanitise_string(trim($value)); - $value_type = detect_annotation_valuetype($value, sanitise_string(trim($value_type))); - - $owner_guid = (int)$owner_guid; - if ($owner_guid==0) $owner_guid = $_SESSION['id']; - - $access_id = (int)$access_id; - - $access = get_access_list(); - - // Add the metastring - $value = add_metastring($value); - if (!$value) return false; - - $name = add_metastring($name); - if (!$name) return false; - - // If ok then add it - return 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_id in {$access} or (access_id = 0 and owner_guid = {$_SESSION['id']}))"); + + return $result; +} + +/** + * Update an annotation. + * + * @param int $annotation_id Annotation ID + * @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 int $access_id Access level of annotation + * + * @return bool + */ +function update_annotation($annotation_id, $name, $value, $value_type, $owner_guid, $access_id) { + global $CONFIG; + + $annotation_id = (int)$annotation_id; + $name = (trim($name)); + $value = (trim($value)); + $value_type = detect_extender_valuetype($value, sanitise_string(trim($value_type))); + + $owner_guid = (int)$owner_guid; + if ($owner_guid == 0) { + $owner_guid = elgg_get_logged_in_user_guid(); } - - /** - * Get a list of annotations for a given object/user/annotation type. - * - * @param int $entity_guid - * @param string $entity_type - * @param string $entity_subtype - * @param string $name - * @param mixed $value - * @param int $owner_id - * @param int $limit - * @param int $offset - * @param string $order_by - */ - function get_annotations($entity_guid = 0, $entity_type = "", $entity_subtype = "", $name = "", $value = "", $owner_guid = 0, $limit = 10, $offset = 0, $order_by = "a.time_created desc") - { - global $CONFIG; - - $entity_guid = (int)$entity_guid; - $entity_type = sanitise_string($entity_type); - $entity_subtype = get_subtype_id($entity_type, $entity_subtype); - $name = get_metastring_id($name); - $value = get_metastring_id($value); - $owner_guid = (int)$owner_guid; - $limit = (int)$limit; - $offset = (int)$offset; - $order_by = sanitise_string($order_by); - - $access = get_access_list(); - - $where = array(); - - if ($entity_guid != 0) - $where[] = "a.entity_guid=$entity_guid"; - - if ($entity_type != "") - $where[] = "e.type='$entity_type'"; - - if ($entity_subtype != "") - $where[] = "e.subtype='$entity_subtype'"; - - if ($owner_guid != 0) - $where[] = "a.owner_guid=$owner_guid"; - - if ($name != "") - $where[] = "a.name_id='$name'"; - - if ($value != "") - $where[] = "a.value='$value'"; - - $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 "; - foreach ($where as $w) - $query .= " $w and "; - $query .= " (a.access_id in {$access} or (a.access_id = 0 and a.owner_guid = {$_SESSION['id']}))"; // Add access controls - $query .= " order by $order_by limit $offset,$limit"; // Add order and limit - - return get_data($query, "row_to_elggannotation"); - + + $access_id = (int)$access_id; + + $access = get_access_sql_suffix(); + + // Add the metastring + $value = add_metastring($value); + if (!$value) { + return false; } - /** - * Return the sum of a given integer annotation. - * - * @param $entity_guid int - * @param $entity_type string - * @param $entity_subtype string - * @param $name string - */ - function get_annotations_sum($entity_guid, $entity_type = "", $entity_subtype = "", $name = "") - { - return __get_annotations_calculate_x("sum", $entity_guid, $entity_type, $entity_subtype, $name); + $name = add_metastring($name); + if (!$name) { + return false; } - - /** - * Return the max of a given integer annotation. - * - * @param $entity_guid int - * @param $entity_type string - * @param $entity_subtype string - * @param $name string - */ - function get_annotations_max($entity_guid, $entity_type = "", $entity_subtype = "", $name = "") - { - return __get_annotations_calculate_x("max", $entity_guid, $entity_type, $entity_subtype, $name); + + // If ok then add it + $result = update_data("UPDATE {$CONFIG->dbprefix}annotations + 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); + elgg_trigger_event('update', 'annotation', $obj); } - - /** - * Return the minumum of a given integer annotation. - * - * @param $entity_guid int - * @param $entity_type string - * @param $entity_subtype string - * @param $name string - */ - function get_annotations_min($entity_guid, $entity_type = "", $entity_subtype = "", $name = "") - { - return __get_annotations_calculate_x("min", $entity_guid, $entity_type, $entity_subtype, $name); + + return $result; +} + +/** + * Returns annotations. Accepts all elgg_get_entities() options for entity + * restraints. + * + * @see elgg_get_entities + * + * @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 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']); + } } - /** - * Return the average of a given integer annotation. - * - * @param $entity_guid int - * @param $entity_type string - * @param $entity_subtype string - * @param $name string - */ - function get_annotations_avg($entity_guid, $entity_type = "", $entity_subtype = "", $name = "") - { - return __get_annotations_calculate_x("avg", $entity_guid, $entity_type, $entity_subtype, $name); + $options['metastring_type'] = 'annotations'; + return elgg_get_metastring_based_objects($options); +} + +/** + * 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; } - - /** - * Count the number of annotations based on search parameters - * - * @param int $entity_guid - * @param string $entity_type - * @param string $entity_subtype - * @param string $name - */ - function count_annotations($entity_guid = 0, $entity_type = "", $entity_subtype = "", $name = "", $value = "", $value_type = "", $owner_guid = 0) - { - return __get_annotations_calculate_x("count", $entity_guid, $entity_type, $entity_subtype, $name); + + $options['metastring_type'] = 'annotations'; + return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback', false); +} + +/** + * 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; } - /** - * Perform a mathmatical calculation on integer annotations. - * - * @param $sum string - * @param $entity_id int - * @param $entity_type string - * @param $entity_subtype string - * @param $name string - */ - function __get_annotations_calculate_x($sum = "avg", $entity_guid, $entity_type = "", $entity_subtype = "", $name = "") - { - global $CONFIG; - - $sum = sanitise_string($sum); - $entity_guid = (int)$entity_id; - $entity_type = sanitise_string($entity_type); - $entity_subtype = get_subtype_id($entity_type, $entity_subtype); - $name = get_metastring_id($name); - $access = get_access_list(); - - $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'"; - - $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=ms.id WHERE "; - foreach ($where as $w) - $query .= " $w and "; - $query .= " (a.access_id in {$access} or (a.access_id = 0 and a.owner_guid = {$_SESSION['id']}))"; // now add access - - $row = get_data_row($query); - - if ($row) - return $row->sum; - + // 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['metastring_type'] = 'annotations'; + return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', $inc_offset); +} + +/** + * 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; } - - /** - * Delete a given annotation. - * - * @param $id int The id - */ - function delete_annotation($id) - { - global $CONFIG; - - $id = (int)$id; - - $access = get_access_list(); - - return delete_data("DELETE from {$CONFIG->dbprefix}annotations where id=$id and (access_id in {$access} or (access_id = 0 and owner_guid = {$_SESSION['id']}))"); + + $options['metastring_type'] = 'annotations'; + return elgg_batch_metastring_based_objects($options, 'elgg_batch_enable_callback'); +} + +/** + * 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), + ); + + $options = array_merge($defaults, $options); + + return elgg_list_entities($options, 'elgg_get_annotations', 'elgg_view_annotation_list'); +} + +/** + * Entities interfaces + */ + +/** + * 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_normalise_plural_options_array($options, $singulars); + $options = elgg_entities_get_metastrings_options('annotation', $options); + + if (!$options) { + return false; } - - /** - * Clear all the annotations for a given entity, assuming you have access to that metadata. - * - * @param int $guid - */ - function clear_annotations($guid, $name = "") - { - global $CONFIG; - - $guid = (int)$guid; - $name = get_metastring_id($name); - - $where = array(); - - if ($name != "") - $where[] = " name_id='$name'"; - - $query = "DELETE from {$CONFIG->dbprefix}annotations where entity_guid=$guid and "; - foreach ($where as $w) - $query .= " $w and "; - $query .= "(access_id in {$access} or (access_id = 0 and owner_guid = {$_SESSION['id']}))"; - - return delete_data(); + + // 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); } - - /** - * Handler called by trigger_plugin_hook on the "export" event. - */ - function export_annotation_plugin_hook($hook, $entity_type, $returnvalue, $params) - { - // Sanity check values - if ((!is_array($params)) && (!isset($params['guid']))) - throw new InvalidParameterException("GUID has not been specified during export, this should never happen."); - - if (!is_array($returnvalue)) - throw new InvalidParameterException("Entity serialisation function passed a non-array returnvalue parameter"); - - $guid = (int)$params['guid']; - $name = $params['name']; - - $result = get_annotations($guid); - - if ($result) - { - foreach ($result as $r) - $returnvalue[] = $r; + + return elgg_get_entities_from_metadata($options); +} + +/** + * Returns a viewable list of entities from annotations. + * + * @param array $options Options array + * + * @see elgg_get_entities_from_annotations() + * @see elgg_list_entities() + * + * @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 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 elgg_get_entities_from_annotation_calculation($options) { + $db_prefix = elgg_get_config('dbprefix'); + $defaults = array( + 'calculation' => 'sum', + 'order_by' => 'annotation_calculation desc' + ); + + $options = array_merge($defaults, $options); + + $function = sanitize_string(elgg_extract('calculation', $options, 'sum', false)); + + // 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"; + + // 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"; + + // 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); +} + +/** + * List entities from an annotation calculation. + * + * @see elgg_get_entities_from_annotation_calculation() + * + * @param array $options An options array. + * + * @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'); +} + +/** + * Export the annotations for the specified entity + * + * @param string $hook 'export' + * @param string $type 'all' + * @param mixed $returnvalue Default return value + * @param mixed $params Parameters determining what annotations to export + * + * @elgg_plugin_hook export all + * + * @return array + * @throws InvalidParameterException + * @access private + */ +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')); + } + + if (!is_array($returnvalue)) { + throw new InvalidParameterException(elgg_echo('InvalidParameterException:NonArrayReturnValue')); + } + + $guid = (int)$params['guid']; + $options = array('guid' => $guid, 'limit' => 0); + if (isset($params['name'])) { + $options['annotation_name'] = $params['name']; + } + + $result = elgg_get_annotations($options); + + if ($result) { + foreach ($result as $r) { + $returnvalue[] = $r->export(); } - - return $returnvalue; } - - /** Register the hook */ - register_plugin_hook("export", "all", "export_annotation_plugin_hook", 2); -?>
\ No newline at end of file + + return $returnvalue; +} + +/** + * Get the URL for this item of metadata, by default this links to the + * export handler in the current view. + * + * @param int $id Annotation id + * + * @return mixed + */ +function get_annotation_url($id) { + $id = (int)$id; + + if ($extender = elgg_get_annotation_from_id($id)) { + return get_extender_url($extender); + } + return false; +} + +/** + * Check to see if a user has already created an annotation on an object + * + * @param int $entity_guid Entity guid + * @param string $annotation_type Type of annotation + * @param int $owner_guid Defaults to logged in user. + * + * @return bool + * @since 1.8.0 + */ +function elgg_annotation_exists($entity_guid, $annotation_type, $owner_guid = NULL) { + global $CONFIG; + + if (!$owner_guid && !($owner_guid = elgg_get_logged_in_user_guid())) { + return FALSE; + } + + $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" . + " 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 (get_data_row($sql)) { + return TRUE; + } + + return FALSE; +} + +/** + * 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 $extender_name The name, default 'all'. + * @param string $function_name The function. + * + * @return string + */ +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'); +} + +elgg_register_event_handler('init', 'system', 'elgg_annotations_init'); |
