aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>2011-02-13 22:59:36 +0000
committerbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>2011-02-13 22:59:36 +0000
commit4be522d7544b1aca0e08828bee42a9be7345bf9c (patch)
treebb1c2ce1f7f177b2de7bb9615c4e87ea58516945
parentc1c2563fc1cd451afaf735350eb1c576740be2f4 (diff)
downloadelgg-4be522d7544b1aca0e08828bee42a9be7345bf9c.tar.gz
elgg-4be522d7544b1aca0e08828bee42a9be7345bf9c.tar.bz2
Refs #2907. DRY'd up and abstracted out a lot of metadata / annotation functions so I can implement #1115 with a clean conscious.
git-svn-id: http://code.elgg.org/elgg/trunk@8207 36083f99-b078-4883-b0ff-0f9b5a30f544
-rw-r--r--engine/classes/ElggAnnotation.php22
-rw-r--r--engine/classes/ElggEntity.php5
-rw-r--r--engine/classes/ElggMetadata.php24
-rw-r--r--engine/lib/annotations.php238
-rw-r--r--engine/lib/deprecated-1.8.php169
-rw-r--r--engine/lib/elgglib.php45
-rw-r--r--engine/lib/entities.php11
-rw-r--r--engine/lib/metadata.php268
-rw-r--r--engine/lib/metastrings.php423
-rw-r--r--engine/tests/api/metastrings.php139
10 files changed, 965 insertions, 379 deletions
diff --git a/engine/classes/ElggAnnotation.php b/engine/classes/ElggAnnotation.php
index 10f4269cf..274cbb923 100644
--- a/engine/classes/ElggAnnotation.php
+++ b/engine/classes/ElggAnnotation.php
@@ -78,7 +78,27 @@ class ElggAnnotation extends ElggExtender {
* @return bool
*/
function delete() {
- return delete_annotation($this->id);
+ return elgg_delete_metastring_based_object_by_id($this->id, 'annotations');
+ }
+
+ /**
+ * Disable the annotation.
+ *
+ * @return bool
+ * @since 1.8
+ */
+ function disable() {
+ return elgg_set_metastring_based_object_enabled_by_id($this->id, 'no', 'annotations');
+ }
+
+ /**
+ * Enable the annotation.
+ *
+ * @return bool
+ * @since 1.8
+ */
+ function enable() {
+ return elgg_set_metastring_based_object_enabled_by_id($this->id, 'yes', 'annotations');
}
/**
diff --git a/engine/classes/ElggEntity.php b/engine/classes/ElggEntity.php
index ea2a329d9..4e1bc586c 100644
--- a/engine/classes/ElggEntity.php
+++ b/engine/classes/ElggEntity.php
@@ -292,9 +292,9 @@ abstract class ElggEntity extends ElggData implements
public function setMetaData($name, $value, $value_type = "", $multiple = false) {
if (is_array($value)) {
unset($this->temp_metadata[$name]);
- remove_metadata($this->getGUID(), $name);
foreach ($value as $v) {
if ((int) $this->guid > 0) {
+ elgg_delete_metadata(array('guid' => $this->guid, 'metadata_name' => $name));
$multiple = true;
if (!create_metadata($this->getGUID(), $name, $v, $value_type,
$this->getOwnerGUID(), $this->getAccessID(), $multiple)) {
@@ -349,7 +349,7 @@ abstract class ElggEntity extends ElggData implements
*
* @return mixed bool
*/
- public function clearMetaData($name = "") {
+ public function clearMetaData($name = '') {
if (empty($name)) {
return clear_metadata($this->getGUID());
} else {
@@ -357,7 +357,6 @@ abstract class ElggEntity extends ElggData implements
}
}
-
/**
* Get a piece of volatile (non-persisted) data on this entity.
*
diff --git a/engine/classes/ElggMetadata.php b/engine/classes/ElggMetadata.php
index 9c13e936e..f85bac6ce 100644
--- a/engine/classes/ElggMetadata.php
+++ b/engine/classes/ElggMetadata.php
@@ -75,12 +75,32 @@ class ElggMetadata extends ElggExtender {
}
/**
- * Delete a given metadata.
+ * Delete the metadata
*
* @return bool
*/
function delete() {
- return delete_metadata($this->id);
+ return elgg_delete_metastring_based_object_by_id($this->id, 'metadata');
+ }
+
+ /**
+ * Disable the metadata
+ *
+ * @return bool
+ * @since 1.8
+ */
+ function disable() {
+ return elgg_set_metastring_based_object_enabled_by_id($this->id, 'no', 'metadata');
+ }
+
+ /**
+ * Disable the metadata
+ *
+ * @return bool
+ * @since 1.8
+ */
+ function enable() {
+ return elgg_set_metastring_based_object_enabled_by_id($this->id, 'yes', 'metadata');
}
/**
diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php
index a14853359..9b3b49626 100644
--- a/engine/lib/annotations.php
+++ b/engine/lib/annotations.php
@@ -23,25 +23,16 @@ 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 false|ElggAnnotation
*/
-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";
-
- return row_to_elggannotation(get_data_row($query));
+function elgg_get_annotation_from_id($id) {
+ return elgg_get_metastring_based_object_by_id($id, 'annotations');
}
/**
@@ -195,29 +186,87 @@ function update_annotation($annotation_id, $name, $value, $value_type, $owner_gu
* @since 1.8.0
*/
function elgg_get_annotations(array $options = array()) {
- // map the annotation_* options to metastring_* options
- $map = array(
- 'annotation_names' => 'metastring_names',
- 'annotation_values' => 'metastring_values',
- 'annotation_case_sensitive' => 'metastring_case_sensitive',
- 'annotation_owner_guids' => 'metastring_owner_guids',
- 'annotation_created_time_lower' => 'metastring_created_time_lower',
- 'annotation_created_time_upper' => 'metastring_created_time_upper',
- 'annotation_calculation' => 'metastring_calculation'
- );
+ $options['metastring_type'] = 'annotations';
+ return elgg_get_metastring_based_objects($options);
+}
- $singulars = array('annotation_name', 'annotation_value');
- $options = elgg_normalise_plural_options_array($options, $singulars);
+/**
+ * Deletes 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 mixed
+ * @since 1.8
+ */
+function elgg_delete_annotations(array $options) {
+ if (!$options || !is_array($options)) {
+ return false;
+ }
- foreach ($map as $ann => $ms) {
- if (isset($options[$ann])) {
- $options[$ms] = $options[$ann];
- }
+ $options['metastring_type'] = 'annotations';
+ return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback');
+}
+
+/**
+ * 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 mixed
+ * @since 1.8
+ */
+function elgg_disable_annotations(array $options) {
+ if (!$options || !is_array($options)) {
+ return false;
+ }
+
+ $options['metastrings_type'] = 'annotations';
+ return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback');
+}
+
+/**
+ * Enables 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 mixed
+ * @since 1.8
+ */
+function elgg_enable_annotations(array $options) {
+ if (!$options || !is_array($options)) {
+ return false;
}
- return elgg_get_metastring_based_objects($options, 'annotations');
+ $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
+ */
+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. Accepts the same values as
@@ -254,6 +303,8 @@ function elgg_get_annotations(array $options = array()) {
*
* annotation_owner_guids => NULL|ARR guids for annotaiton owners
*
+ * annotation_ids => NULL|ARR Annotation IDs
+ *
* @return array
* @since 1.7.0
*/
@@ -272,6 +323,8 @@ 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'
);
@@ -279,7 +332,7 @@ 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_name_value_pair', 'annotation_owner_guid', 'annotation_id');
$options = elgg_normalise_plural_options_array($options, $singulars);
@@ -317,26 +370,6 @@ function elgg_list_entities_from_annotations($options = array()) {
}
/**
- * 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
- */
-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');
-}
-
-/**
* Get entities ordered by a mathematical calculation
*
* @param array $options An options array:
@@ -385,103 +418,6 @@ function elgg_list_entities_from_annotation_calculation($options) {
return elgg_list_entities($options, 'elgg_get_entities_from_annotation_calculation');
}
-
-/**
- * Delete a given annotation.
- *
- * @param int $id The annotation id
- *
- * @return bool
- */
-function delete_annotation($id) {
- global $CONFIG;
-
- $id = (int)$id;
-
- $access = get_access_sql_suffix();
- $annotation = get_annotation($id);
-
- if (elgg_trigger_event('delete', 'annotation', $annotation)) {
- remove_from_river_by_annotation($id);
- return delete_data("DELETE from {$CONFIG->dbprefix}annotations where id=$id and $access");
- }
-
- return FALSE;
-}
-
-/**
- * Clear all the annotations for a given entity, assuming you have access to that metadata.
- *
- * @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
- *
- * @param int $owner_guid The owner
- *
- * @return int Number of annotations deleted
- */
-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++;
- }
- }
-
- return $deleted;
-}
-
/**
* Handler called by trigger_plugin_hook on the "export" event.
*
diff --git a/engine/lib/deprecated-1.8.php b/engine/lib/deprecated-1.8.php
index 9bca873c5..f86d94621 100644
--- a/engine/lib/deprecated-1.8.php
+++ b/engine/lib/deprecated-1.8.php
@@ -3534,7 +3534,6 @@ function find_metadata($meta_name = "", $meta_value = "", $entity_type = "", $en
return elgg_get_metadata($options);
}
-
/**
* Get metadata objects by name.
*
@@ -3547,6 +3546,10 @@ function find_metadata($meta_name = "", $meta_value = "", $entity_type = "", $en
function get_metadata_byname($entity_guid, $meta_name) {
elgg_deprecated_notice('get_metadata_byname() is deprecated by elgg_get_metadata()', 1.8);
+ if (!$entity_guid || !$meta_name) {
+ return false;
+ }
+
$options = array(
'guid' => $entity_guid,
'metadata_name' => $meta_name,
@@ -3573,6 +3576,10 @@ function get_metadata_byname($entity_guid, $meta_name) {
function get_metadata_for_entity($entity_guid) {
elgg_deprecated_notice('get_metadata_for_entity() is deprecated by elgg_get_metadata()', 1.8);
+ if (!$entity_guid) {
+ return false;
+ }
+
$options = array(
'guid' => $entity_guid,
'limit' => 0
@@ -3590,5 +3597,165 @@ function get_metadata_for_entity($entity_guid) {
* @deprecated 1.8 Use elgg_get_metadata_from_id()
*/
function get_metadata($id) {
+ elgg_deprecated_notice('get_metadata() is deprecated by elgg_get_metadata_from_id()', 1.8);
return elgg_get_metadata_from_id($id);
}
+
+/**
+ * Clear all the metadata for a given entity, assuming you have access to that entity.
+ *
+ * @param int $guid Entity GUID
+ *
+ * @return bool
+ * @deprecated 1.8 Use elgg_delete_metadata()
+ */
+function clear_metadata($guid) {
+ elgg_deprecated_notice('clear_metadata() is deprecated by elgg_delete_metadata()', 1.8);
+ if (!$guid) {
+ return false;
+ }
+ return elgg_delete_metadata(array('guid' => $guid, 'limit' => 0));
+}
+
+/**
+ * Clear all metadata belonging to a given owner_guid
+ *
+ * @param int $owner_guid The owner
+ *
+ * @return bool
+ * @deprecated 1.8 Use elgg_delete_metadata()
+ */
+function clear_metadata_by_owner($owner_guid) {
+ elgg_deprecated_notice('clear_metadata() is deprecated by elgg_delete_metadata()', 1.8);
+ if (!$owner_guid) {
+ return false;
+ }
+ return elgg_delete_metadata(array('metadata_owner' => $owner_guid, 'limit' => 0));
+}
+
+/**
+ * Delete a piece of metadata, where the current user has access.
+ *
+ * @param int $id The id of metadata to delete.
+ *
+ * @return bool
+ * @deprecated 1.8 Use elgg_delete_metadata()
+ */
+function delete_metadata($id) {
+ elgg_deprecated_notice('delete_metadata() is deprecated by elgg_delete_metadata()', 1.8);
+ if (!$id) {
+ return false;
+ }
+ return elgg_delete_metadata(array('metadata_id' => $id));
+}
+
+/**
+ * Removes metadata on an entity with a particular name, optionally with a given value.
+ *
+ * @param int $guid The entity GUID
+ * @param string $name The name of the metadata
+ * @param string $value The value of the metadata (useful to remove a single item of a set)
+ *
+ * @return bool Depending on success
+ * @deprecated 1.8 Use elgg_delete_metadata()
+ */
+function remove_metadata($guid, $name, $value = "") {
+ elgg_deprecated_notice('delete_metadata() is deprecated by elgg_delete_metadata()', 1.8);
+
+ // prevent them from deleting everything
+ if (!$guid) {
+ return false;
+ }
+
+ $options = array(
+ 'guid' => $guid,
+ 'metadata_name' => $name,
+ 'limit' => 0
+ );
+
+ if ($value) {
+ $options['metadata_value'] = $value;
+ }
+
+ return elgg_delete_metadata($options);
+}
+
+/**
+ * Get a specific annotation.
+ *
+ * @param int $annotation_id Annotation ID
+ *
+ * @return ElggAnnotation
+ * @deprecated 1.8 Use elgg_get_annotation_from_id()
+ */
+function get_annotation($annotation_id) {
+ elgg_deprecated_notice('get_annotation() is deprecated by elgg_get_annotation_from_id()', 1.8);
+ return elgg_get_annotation_from_id($annotation_id);
+}
+
+/**
+ * Delete a given annotation.
+ *
+ * @param int $id The annotation id
+ *
+ * @return bool
+ * @deprecated 1.8 Use elgg_delete_annotations()
+ */
+function delete_annotation($id) {
+ elgg_deprecated_notice('delete_annotation() is deprecated by elgg_delete_annotations()', 1.8);
+ if (!$id) {
+ return false;
+ }
+ return elgg_delete_annotations(array('annotation_id' => $annotation_id));
+}
+
+/**
+ * Clear all the annotations for a given entity, assuming you have access to that metadata.
+ *
+ * @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
+ * @deprecated 1.8 Use elgg_delete_annotations()
+ */
+function clear_annotations($guid, $name = "") {
+ elgg_deprecated_notice('clear_annotations() is deprecated by elgg_delete_annotations()', 1.8);
+
+ if (!$guid) {
+ return false;
+ }
+
+ $options = array(
+ 'guid' => $guid,
+ 'limit' => 0
+ );
+
+ if ($name) {
+ $options['annotation_name'] = $name;
+ }
+
+ return elgg_delete_annotations($options);
+}
+
+/**
+ * Clear all annotations belonging to a given owner_guid
+ *
+ * @param int $owner_guid The owner
+ *
+ * @return int Number of annotations deleted
+ * @deprecated 1.8 Use elgg_delete_annotations()
+ */
+function clear_annotations_by_owner($owner_guid) {
+ elgg_deprecated_notice('clear_annotations_by_owner() is deprecated by elgg_delete_annotations()', 1.8);
+
+ if (!$owner_guid) {
+ return false;
+ }
+
+ $options = array(
+ 'annotation_owner_guid' => $guid,
+ 'limit' => 0
+ );
+
+ return elgg_delete_annotations($options);
+}
diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php
index 7ebf918b7..a00b21c52 100644
--- a/engine/lib/elgglib.php
+++ b/engine/lib/elgglib.php
@@ -1664,8 +1664,9 @@ function css_page_handler($page) {
*
* This is used mostly for elgg_get_entities() and other similar functions.
*
- * @access private
* @param string $order_by An order by clause
+ * @access private
+ * @return string
*/
function elgg_sql_reverse_order_by_clause($order_by) {
$order_by = strtolower($order_by);
@@ -1683,6 +1684,48 @@ function elgg_sql_reverse_order_by_clause($order_by) {
}
/**
+ * Enable objects with an enable() method.
+ *
+ * Used as a callback for ElggBatch.
+ *
+ * @param object $object The object to enable
+ * @access private
+ * @return bool
+ */
+function elgg_batch_enable_callback($object) {
+ // our db functions return the number of rows affected...
+ return $object->enable() ? true : false;
+}
+
+/**
+ * Disable objects with a disable() method.
+ *
+ * Used as a callback for ElggBatch.
+ *
+ * @param object $object The object to disable
+ * @access private
+ * @return bool
+ */
+function elgg_batch_disable_callback($object) {
+ // our db functions return the number of rows affected...
+ return $object->disable() ? true : false;
+}
+
+/**
+ * Delete objects with a delete() method.
+ *
+ * Used as a callback for ElggBatch.
+ *
+ * @param object $object The object to disable
+ * @access private
+ * @return bool
+ */
+function elgg_batch_delete_callback($object) {
+ // our db functions return the number of rows affected...
+ return $object->delete() ? true : false;
+}
+
+/**
* Intercepts the index page when Walled Garden mode is enabled.
*
* @link http://docs.elgg.org/Tutorials/WalledGarden
diff --git a/engine/lib/entities.php b/engine/lib/entities.php
index 781a744ad..4f58e96a8 100644
--- a/engine/lib/entities.php
+++ b/engine/lib/entities.php
@@ -1345,6 +1345,17 @@ function disable_entity($guid, $reason = "", $recursive = true) {
}
}
+ // disable annotations
+ // Now delete the entity itself
+// $entity->clearMetadata();
+// $entity->clearAnnotations();
+// $entity->clearRelationships();
+//
+// $res = delete_data("DELETE from {$CONFIG->dbprefix}entities where guid={$guid}");
+// if ($res) {
+// $sub_table = "";
+// }
+
$__RECURSIVE_DELETE_TOKEN = null;
}
diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php
index 6724bcb70..8a62929d5 100644
--- a/engine/lib/metadata.php
+++ b/engine/lib/metadata.php
@@ -32,56 +32,7 @@ function row_to_elggmetadata($row) {
* @return false|ElggMetadata
*/
function elgg_get_metadata_from_id($id) {
- $db_prefix = elgg_get_config('dbprefix');
-
- $id = (int)$id;
- $access = get_access_sql_suffix("e");
- $md_access = get_access_sql_suffix("m");
-
- $query = "SELECT m.*, n.string as name, v.string as value from {$db_prefix}metadata m"
- . " JOIN {$db_prefix}entities e on e.guid = m.entity_guid"
- . " JOIN {$db_prefix}metastrings v on m.value_id = v.id"
- . " JOIN {$db_prefix}metastrings n on m.name_id = n.id"
- . " where m.id=$id and $access and $md_access";
-
- return row_to_elggmetadata(get_data_row($query));
-}
-
-/**
- * Removes metadata on an entity with a particular name, optionally with a given value.
- *
- * @param int $entity_guid The entity GUID
- * @param string $name The name of the metadata
- * @param string $value The value of the metadata (useful to remove a single item of a set)
- *
- * @return bool Depending on success
- */
-function remove_metadata($entity_guid, $name, $value = "") {
- global $CONFIG;
- $entity_guid = (int) $entity_guid;
-
- $name_id = get_metastring_id($name);
- if ($name_id === FALSE) {
- // name doesn't exist
- return FALSE;
- }
-
- $query = "SELECT * from {$CONFIG->dbprefix}metadata WHERE entity_guid = '$entity_guid' and name_id = '$name_id'";
- if ($value != "") {
- $value_id = get_metastring_id($value);
- if ($value_id !== FALSE) {
- $query .= " AND value_id = '$value_id'";
- }
- }
-
- if ($existing = get_data($query)) {
- foreach ($existing as $ex) {
- delete_metadata($ex->id);
- }
- return true;
- }
-
- return false;
+ return elgg_get_metastring_based_object_by_id($id, 'metadata');
}
/**
@@ -291,38 +242,6 @@ $access_id = ACCESS_PRIVATE, $allow_multiple = false) {
}
/**
- * Delete a piece of metadata, where the current user has access.
- *
- * @param int $id The id of metadata to delete.
- *
- * @return bool
- */
-function delete_metadata($id) {
- global $CONFIG;
-
- $id = (int)$id;
- $metadata = elgg_get_metadata_from_id($id);
-
- if ($metadata) {
- // Tidy up if memcache is enabled.
- static $metabyname_memcache;
- if ((!$metabyname_memcache) && (is_memcache_available())) {
- $metabyname_memcache = new ElggMemcache('metabyname_memcache');
- }
-
- if ($metabyname_memcache) {
- $metabyname_memcache->delete("{$metadata->entity_guid}:{$metadata->name_id}");
- }
-
- if (($metadata->canEdit()) && (elgg_trigger_event('delete', 'metadata', $metadata))) {
- return delete_data("DELETE from {$CONFIG->dbprefix}metadata where id=$id");
- }
- }
-
- return false;
-}
-
-/**
* Returns metadata. Accepts all elgg_get_entities() options for entity
* restraints.
*
@@ -353,31 +272,70 @@ function delete_metadata($id) {
* @return mixed
* @since 1.8.0
*/
-function elgg_get_metadata($options) {
- // map the metadata_* options to metastring_* options
- $map = array(
- 'metadata_names' => 'metastring_names',
- 'metadata_values' => 'metastring_values',
- 'metadata_case_sensitive' => 'metastring_case_sensitive',
- 'metadata_owner_guids' => 'metastring_owner_guids',
- 'metadata_created_time_lower' => 'metastring_created_time_lower',
- 'metadata_created_time_upper' => 'metastring_created_time_upper',
- 'metadata_calculation' => 'metastring_calculation'
- );
+function elgg_get_metadata(array $options = array()) {
+ $options['metastring_type'] = 'metadata';
+ return elgg_get_metastring_based_objects($options);
+}
- $singulars = array('metadata_name', 'metadata_value');
- $options = elgg_normalise_plural_options_array($options, $singulars);
+/**
+ * Deletes metadata based on $options.
+ *
+ * @warning Unlike elgg_get_metadata() this will not accept an empty options array!
+ *
+ * @param array $options An options array. {@See elgg_get_metadata()}
+ * @return mixed
+ * @since 1.8
+ */
+function elgg_delete_metadata(array $options) {
+ if (!$options || !is_array($options)) {
+ return false;
+ }
- foreach ($map as $ann => $ms) {
- if (isset($options[$ann])) {
- $options[$ms] = $options[$ann];
- }
+ $options['metastring_type'] = 'metadata';
+ return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback');
+}
+
+/**
+ * Disables metadata based on $options.
+ *
+ * @warning Unlike elgg_get_metadata() this will not accept an empty options array!
+ *
+ * @param array $options An options array. {@See elgg_get_metadata()}
+ * @return mixed
+ * @since 1.8
+ */
+function elgg_disable_metadata(array $options) {
+ if (!$options || !is_array($options)) {
+ return false;
}
- return elgg_get_metastring_based_objects($options, 'metadata');
+ $options['metastrings_type'] = 'metadata';
+ return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback');
}
/**
+ * Enables metadata based on $options.
+ *
+ * @warning Unlike elgg_get_metadata() this will not accept an empty options array!
+ *
+ * @param array $options An options array. {@See elgg_get_metadata()}
+ * @return mixed
+ * @since 1.8
+ */
+function elgg_enable_metadata(array $options) {
+ if (!$options || !is_array($options)) {
+ return false;
+ }
+
+ $options['metastring_type'] = 'metadata';
+ return elgg_batch_metastring_based_objects($options, 'elgg_batch_enable_callback');
+}
+
+/**
+ * ElggEntities interfaces
+ */
+
+/**
* Returns entities based upon metadata. Also accepts all
* options available to elgg_get_entities(). Supports
* the singular option shortcut.
@@ -453,66 +411,6 @@ function elgg_get_entities_from_metadata(array $options = array()) {
}
/**
- * Returns options to pass to elgg_get_entities() for metastrings operations.
- *
- * @param string $type Metastring type: annotations or metadata
- * @param array $options Options
- *
- * @return array
- * @since 1.7.0
- */
-function elgg_entities_get_metastrings_options($type, $options) {
- $valid_types = array('metadata', 'annotation');
- if (!in_array($type, $valid_types)) {
- return FALSE;
- }
-
- // the options for annotations are singular (annotation_name) but the table
- // is plural (elgg_annotations) so rewrite for the table name.
- $n_table = ($type == 'annotation') ? 'annotations' : $type;
-
- $singulars = array("{$type}_name", "{$type}_value",
- "{$type}_name_value_pair", "{$type}_owner_guid");
- $options = elgg_normalise_plural_options_array($options, $singulars);
-
- $clauses = elgg_get_entity_metadata_where_sql('e', $n_table, $options["{$type}_names"],
- $options["{$type}_values"], $options["{$type}_name_value_pairs"],
- $options["{$type}_name_value_pairs_operator"], $options["{$type}_case_sensitive"],
- $options["order_by_{$type}"], $options["{$type}_owner_guids"]);
-
- if ($clauses) {
- // merge wheres to pass to get_entities()
- if (isset($options['wheres']) && !is_array($options['wheres'])) {
- $options['wheres'] = array($options['wheres']);
- } elseif (!isset($options['wheres'])) {
- $options['wheres'] = array();
- }
-
- $options['wheres'] = array_merge($options['wheres'], $clauses['wheres']);
-
- // merge joins to pass to get_entities()
- if (isset($options['joins']) && !is_array($options['joins'])) {
- $options['joins'] = array($options['joins']);
- } elseif (!isset($options['joins'])) {
- $options['joins'] = array();
- }
-
- $options['joins'] = array_merge($options['joins'], $clauses['joins']);
-
- if ($clauses['orders']) {
- $order_by_metadata = implode(", ", $clauses['orders']);
- if (isset($options['order_by']) && $options['order_by']) {
- $options['order_by'] = "$order_by_metadata, {$options['order_by']}";
- } else {
- $options['order_by'] = "$order_by_metadata, e.time_created DESC";
- }
- }
- }
-
- return $options;
-}
-
-/**
* Returns metadata name and value SQL where for entities.
* NB: $names and $values are not paired. Use $pairs for this.
* Pairs default to '=' operand.
@@ -789,50 +687,8 @@ function elgg_list_entities_from_metadata($options) {
}
/**
- * Clear all the metadata for a given entity, assuming you have access to that metadata.
- *
- * @param int $entity_guid Entity GUID
- *
- * @return bool
+ * Other functions
*/
-function clear_metadata($entity_guid) {
- global $CONFIG;
-
- $entity_guid = (int)$entity_guid;
- if ($entity = get_entity($entity_guid)) {
- if ($entity->canEdit()) {
- return delete_data("DELETE from {$CONFIG->dbprefix}metadata where entity_guid={$entity_guid}");
- }
- }
- return false;
-}
-
-/**
- * Clear all annotations belonging to a given owner_guid
- *
- * @param int $owner_guid The owner
- *
- * @return bool
- */
-function clear_metadata_by_owner($owner_guid) {
- global $CONFIG;
-
- $owner_guid = (int)$owner_guid;
-
- $metas = get_data("SELECT id from {$CONFIG->dbprefix}metadata WHERE owner_guid=$owner_guid");
- $deleted = 0;
-
- if (is_array($metas)) {
- foreach ($metas as $id) {
- // Is this the best way?
- if (delete_metadata($id->id)) {
- $deleted++;
- }
- }
- }
-
- return $deleted;
-}
/**
* Handler called by trigger_plugin_hook on the "export" event.
@@ -983,10 +839,10 @@ function is_metadata_independent($type, $subtype) {
function metadata_update($event, $object_type, $object) {
if ($object instanceof ElggEntity) {
if (!is_metadata_independent($object->getType(), $object->getSubtype())) {
- global $CONFIG;
+ $db_prefix = elgg_get_config('dbprefix');
$access_id = (int) $object->access_id;
$guid = (int) $object->getGUID();
- $query = "update {$CONFIG->dbprefix}metadata set access_id = {$access_id} where entity_guid = {$guid}";
+ $query = "update {$db_prefix}metadata set access_id = {$access_id} where entity_guid = {$guid}";
update_data($query);
}
}
@@ -1028,4 +884,4 @@ function metadata_test($hook, $type, $value, $params) {
global $CONFIG;
$value[] = $CONFIG->path . 'engine/tests/objects/metadata.php';
return $value;
-}
+} \ No newline at end of file
diff --git a/engine/lib/metastrings.php b/engine/lib/metastrings.php
index 23724b979..bcb15c338 100644
--- a/engine/lib/metastrings.php
+++ b/engine/lib/metastrings.php
@@ -15,6 +15,8 @@ $METASTRINGS_CACHE = array();
global $METASTRINGS_DEADNAME_CACHE;
$METASTRINGS_DEADNAME_CACHE = array();
+
+
/**
* Return the meta string id for a given tag, or false.
*
@@ -201,14 +203,13 @@ function delete_orphaned_metastrings() {
return delete_data($query);
}
-
/**
* Returns an array of either ElggAnnotation or ElggMetadata objects.
* Accepts all elgg_get_entities() options for entity restraints.
*
* @see elgg_get_entities
*
- * @param array $options Array in format:
+ * @param array $options Array in format:
*
* metastring_names => NULL|ARR metastring names
*
@@ -224,16 +225,35 @@ function delete_orphaned_metastrings() {
*
* metastring_calculation => STR Perform the MySQL function on the metastring values returned.
*
- * @param string $type Either metadata or annotations
+ * metastring_type => STR metadata or annotation(s)
+ *
* @return mixed
* @access private
*/
-function elgg_get_metastring_based_objects($options, $type = 'metadata') {
+function elgg_get_metastring_based_objects($options) {
- if ($type != 'metadata' && $type != 'annotations') {
+ if (!isset($options['metastring_type'])) {
return false;
}
+ switch ($options['metastring_type']) {
+ case 'metadata':
+ $type = 'metadata';
+ $callback = 'row_to_elggmetadata';
+ break;
+
+ case 'annotations':
+ case 'annotation':
+ $type = 'annotations';
+ $callback = 'row_to_elggannotation';
+ break;
+
+ default:
+ return false;
+ }
+
+ $options = elgg_normalize_metastrings_options($options);
+
$defaults = array(
// entities
'types' => ELGG_ENTITIES_ANY_VALUE,
@@ -265,6 +285,8 @@ function elgg_get_metastring_based_objects($options, $type = 'metadata') {
'metastring_owner_guids' => ELGG_ENTITIES_ANY_VALUE,
+ 'metastring_ids' => ELGG_ENTITIES_ANY_VALUE,
+
// sql
'order_by' => 'n_table.time_created asc',
'limit' => 10,
@@ -274,9 +296,12 @@ function elgg_get_metastring_based_objects($options, $type = 'metadata') {
'wheres' => array(),
'joins' => array(),
- 'callback' => ($type == 'annotations') ? 'row_to_elggannotation' : 'row_to_elggmetadata'
+ 'callback' => $callback
);
+ // @todo Ignore site_guid right now because of #2910
+ $options['site_guid'] = ELGG_ENTITIES_ANY_VALUE;
+
$options = array_merge($defaults, $options);
// can't use helper function with type_subtype_pair because
@@ -291,7 +316,7 @@ function elgg_get_metastring_based_objects($options, $type = 'metadata') {
}
$singulars = array('type', 'subtype', 'guid', 'owner_guid', 'container_guid', 'site_guid',
- 'metastring_name', 'metastring_value'
+ 'metastring_name', 'metastring_value', 'metastring_id'
);
$options = elgg_normalise_plural_options_array($options, $singulars);
@@ -324,7 +349,8 @@ function elgg_get_metastring_based_objects($options, $type = 'metadata') {
$wheres[] = elgg_get_entity_time_where_sql('n_table', $options['metastring_created_time_upper'],
$options['metastring_created_time_lower'], null, null);
- $wheres[] = elgg_get_guid_based_where_sql('n_table.owner_guid', $options['metastring_owner_guids']);
+ $wheres[] = elgg_get_guid_based_where_sql('n_table.owner_guid',
+ $options['metastring_owner_guids']);
// remove identical where clauses
$wheres = array_unique($wheres);
@@ -364,7 +390,8 @@ function elgg_get_metastring_based_objects($options, $type = 'metadata') {
// metastrings
$metastring_clauses = elgg_get_metastring_sql('n_table', $options['metastring_names'],
- $options['metastring_values'], $options['metastring_case_sensitive']);
+ $options['metastring_values'], null, $options['metastring_ids'],
+ $options['metastring_case_sensitive']);
if ($metastring_clauses) {
$wheres = array_merge($wheres, $metastring_clauses['wheres']);
@@ -377,9 +404,11 @@ function elgg_get_metastring_based_objects($options, $type = 'metadata') {
}
if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE) {
- $query = "SELECT DISTINCT n_table.*, n.string as name, v.string as value FROM {$db_prefix}$type n_table";
+ $query = "SELECT DISTINCT n_table.*, n.string as name,
+ v.string as value FROM {$db_prefix}$type n_table";
} else {
- $query = "SELECT DISTINCT v.string as value, {$options['metastring_calculation']}(v.string) as calculation FROM {$db_prefix}$type n_table";
+ $query = "SELECT DISTINCT v.string as value,
+ {$options['metastring_calculation']}(v.string) as calculation FROM {$db_prefix}$type n_table";
}
// add joins
@@ -399,7 +428,8 @@ function elgg_get_metastring_based_objects($options, $type = 'metadata') {
// reverse order by
if ($options['reverse_order_by']) {
- $options['order_by'] = elgg_sql_reverse_order_by_clause($options['order_by'], $defaults['order_by']);
+ $options['order_by'] = elgg_sql_reverse_order_by_clause($options['order_by'],
+ $defaults['order_by']);
}
if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE) {
@@ -425,7 +455,6 @@ function elgg_get_metastring_based_objects($options, $type = 'metadata') {
}
}
-
/**
* Returns an array of joins and wheres for use in metastrings.
*
@@ -435,15 +464,17 @@ function elgg_get_metastring_based_objects($options, $type = 'metadata') {
* @param array $names An array of names
* @param array $values An array of values
* @param array $pairs Name / value pairs. Not currently used.
+ * @param array $ids Metastring IDs
* @param bool $case_sensitive Should name and values be case sensitive?
*
* @return array
*/
function elgg_get_metastring_sql($table, $names = null, $values = null,
- $pairs = null, $case_sensitive = false) {
+ $pairs = null, $ids = null, $case_sensitive = false) {
if ((!$names && $names !== 0)
&& (!$values && $values !== 0)
+ && !$ids
&& (!$pairs && $pairs !== 0)) {
return '';
@@ -512,6 +543,18 @@ function elgg_get_metastring_sql($table, $names = null, $values = null,
}
}
+ if ($ids !== NULL) {
+ if (!is_array($ids)) {
+ $ids = array($ids);
+ }
+
+ $ids_str = implode(',', $ids);
+
+ if ($ids_str) {
+ $wheres[] = "n_table.id IN ($ids_str)";
+ }
+ }
+
if ($names_where && $values_where) {
$wheres[] = "($names_where AND $values_where AND $access)";
} elseif ($names_where) {
@@ -526,3 +569,355 @@ function elgg_get_metastring_sql($table, $names = null, $values = null,
return $return;
}
+
+/**
+ * Normalizes metadata / annotation option names to their
+ * corresponding metastrings name.
+ *
+ * @param array $options An options array
+ * @since 1.8
+ * @access private
+ * @return array
+ */
+function elgg_normalize_metastrings_options(array $options = array()) {
+ $prefixes = array('metadata_', 'annotation_');
+
+ // map the metadata_* options to metastring_* options
+ $map = array(
+ 'names' => 'metastring_names',
+ 'values' => 'metastring_values',
+ 'case_sensitive' => 'metastring_case_sensitive',
+ 'owner_guids' => 'metastring_owner_guids',
+ 'created_time_lower' => 'metastring_created_time_lower',
+ 'created_time_upper' => 'metastring_created_time_upper',
+ 'calculation' => 'metastring_calculation'
+ );
+
+ foreach ($prefixes as $prefix) {
+ $singulars = array("{$prefix}name", "{$prefix}value", "{$prefix}owner_guid");
+ $options = elgg_normalise_plural_options_array($options, $singulars);
+
+ foreach ($map as $specific => $normalized) {
+ $key = $prefix . $specific;
+ if (isset($options[$key])) {
+ $options[$normalized] = $options[$key];
+ }
+ }
+ }
+
+ return $options;
+}
+
+/**
+ * Enables or disables a metastrings-based object by its id.
+ *
+ * @warning To enable disabled metastrings you must first use
+ * {@link access_show_hidden_entities()}.
+ *
+ * @param int $id The object's ID
+ * @param string $enabled Value to set to: yes or no
+ * @param string $type The type of table to use: metadata or anntations
+ *
+ * @return bool
+ * @since 1.8
+ * @access private
+ */
+function elgg_set_metastring_based_object_enabled_by_id($id, $enabled, $type) {
+ $id = (int)$id;
+ $db_prefix = elgg_get_config('dbprefix');
+
+ $object = elgg_get_metastring_based_object_by_id($id, $type);
+
+ switch($type) {
+ case 'annotation':
+ case 'annotations':
+ $table = "{$db_prefix}annotations";
+ break;
+
+ case 'metadata':
+ $table = "{$db_prefix}metadata";
+ break;
+ }
+
+ if ($enabled === 'yes' || $enabled === 1 || $enabled === true) {
+ $enabled = 'yes';
+ $event = 'enable';
+ } elseif ($enabled === 'no' || $enabled === 0 || $enabled === false) {
+ $enabled = 'no';
+ $event = 'disable';
+ } else {
+ return false;
+ }
+
+ $return = false;
+
+ if ($object) {
+ // don't set it if it's already set.
+ if ($object->enabled == $enabled) {
+ $return = false;
+ } elseif ($object->canEdit() && (elgg_trigger_event($event, $type, $object))) {
+ $return = update_data("UPDATE $table SET enabled = '$enabled' where id = $id");
+ }
+ }
+
+ return $return;
+}
+
+/**
+ * Enables or disables a metastrings-based objects by their entity_guid.
+ *
+ * @param int $guid The object's ID
+ * @param string $enabled Value to set to: yes or no
+ * @param string $type The type of table to use: metadata or anntations
+ * @param string $name Optional metastring name. If not set, affects all metadata.
+ *
+ * @return bool
+ */
+function elgg_set_metastring_based_object_enabled_by_guid($guid, $enabled, $type, $name = null) {
+ $valid_types = array('annotations', 'annotation', 'metadata');
+ $guid = (int)$guid;
+ $entity = get_entity($guid);
+
+ if (!in_array($type, $valid_types)) {
+ return false;
+ }
+
+ if (!$entity || !$entity->canEdit()) {
+ return false;
+ }
+
+ switch($enabled) {
+ case true:
+ case 1:
+ case 'yes':
+ $callback = 'elgg_batch_enable_callback';
+ break;
+
+ case false:
+ case 0:
+ case 'no':
+ $callback = 'elgg_batch_disable_callback';
+ break;
+ }
+
+ $ashe = access_get_show_hidden_status();
+ access_show_hidden_entities(true);
+
+ switch($type) {
+ case 'annotation':
+ case 'annotations':
+ $getter = 'elgg_get_annotations';
+ if ($name) {
+ $options['annotation_name'] = $name;
+ }
+ break;
+
+ case 'metadata':
+ $getter = 'elgg_get_metadata';
+ if ($name) {
+ $options['metadata_name'] = $name;
+ }
+ break;
+ }
+
+ $options = array(
+ 'guid' => $guid,
+ 'limit' => 0
+ );
+
+ $batch = new ElggBatch('elgg_get_metadata', $options, 'elgg_batch_disable_callback');
+ $r = $batch->callbackResult;
+
+ access_show_hidden_entities($ashe);
+
+ return $r;
+}
+
+/**
+ * Runs metastrings-based objects found using $options through $callback
+ *
+ * @warning Unlike elgg_get_metastring_based_objects() this will not accept an
+ * empty options array!
+ *
+ * @param array $options An options array. {@See elgg_get_metastring_based_objects()}
+ * @param string $callback The callback to pass each result through
+ * @return mixed
+ * @access private
+ * @since 1.8
+ */
+function elgg_batch_metastring_based_objects(array $options, $callback) {
+ if (!$options || !is_array($options)) {
+ return false;
+ }
+
+ $batch = new ElggBatch('elgg_get_metastring_based_objects', $options, $callback);
+ $r = $batch->callbackResult;
+
+ return $r;
+}
+
+/**
+ * Returns a singular metastring-based object by its ID.
+ *
+ * @param int $id The metastring-based object's ID
+ * @param string $type The type: annotation or metadata
+ * @return mixed
+ *
+ * @since 1.8
+ * @access private
+ */
+function elgg_get_metastring_based_object_by_id($id, $type) {
+ $id = (int)$id;
+ if (!$id) {
+ return false;
+ }
+
+ $options = array(
+ 'metastring_type' => $type,
+ 'metastring_id' => $id
+ );
+
+ $obj = elgg_get_metastring_based_objects($options);
+
+ if ($obj && count($obj) == 1) {
+ return $obj[0];
+ }
+
+ return false;
+}
+
+/**
+ * Deletes a metastring-based object by its id
+ *
+ * @param int $id The object's ID
+ * @param string $type The object's metastring type: annotation or metadata
+ * @return bool
+ *
+ * @since 1.8
+ * @access private
+ */
+function elgg_delete_metastring_based_object_by_id($id, $type) {
+ $id = (int)$id;
+ $db_prefix = elgg_get_config('dbprefix');
+
+ switch ($type) {
+ case 'annotation':
+ case 'annotations':
+ $type = 'annotations';
+ break;
+
+ case 'metadata':
+ $type = 'metadata';
+ break;
+
+ default:
+ return false;
+ }
+
+ $obj = elgg_get_metastring_based_object_by_id($id, $type);
+ $table = $db_prefix . $type;
+
+ if ($obj) {
+ // Tidy up if memcache is enabled.
+ // @todo only metadata is supported
+ if ($type == 'metadata') {
+ static $metabyname_memcache;
+ if ((!$metabyname_memcache) && (is_memcache_available())) {
+ $metabyname_memcache = new ElggMemcache('metabyname_memcache');
+ }
+
+ if ($metabyname_memcache) {
+ $metabyname_memcache->delete("{$obj->entity_guid}:{$obj->name_id}");
+ }
+ }
+
+ if (($obj->canEdit()) && (elgg_trigger_event('delete', $type, $obj))) {
+ return delete_data("DELETE from $table where id=$id");
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Entities interface helpers
+ */
+
+/**
+ * Returns options to pass to elgg_get_entities() for metastrings operations.
+ *
+ * @param string $type Metastring type: annotations or metadata
+ * @param array $options Options
+ *
+ * @return array
+ * @since 1.7.0
+ */
+function elgg_entities_get_metastrings_options($type, $options) {
+ $valid_types = array('metadata', 'annotation');
+ if (!in_array($type, $valid_types)) {
+ return FALSE;
+ }
+
+ // the options for annotations are singular (annotation_name) but the table
+ // is plural (elgg_annotations) so rewrite for the table name.
+ $n_table = ($type == 'annotation') ? 'annotations' : $type;
+
+ $singulars = array("{$type}_name", "{$type}_value",
+ "{$type}_name_value_pair", "{$type}_owner_guid");
+ $options = elgg_normalise_plural_options_array($options, $singulars);
+
+ $clauses = elgg_get_entity_metadata_where_sql('e', $n_table, $options["{$type}_names"],
+ $options["{$type}_values"], $options["{$type}_name_value_pairs"],
+ $options["{$type}_name_value_pairs_operator"], $options["{$type}_case_sensitive"],
+ $options["order_by_{$type}"], $options["{$type}_owner_guids"]);
+
+ if ($clauses) {
+ // merge wheres to pass to get_entities()
+ if (isset($options['wheres']) && !is_array($options['wheres'])) {
+ $options['wheres'] = array($options['wheres']);
+ } elseif (!isset($options['wheres'])) {
+ $options['wheres'] = array();
+ }
+
+ $options['wheres'] = array_merge($options['wheres'], $clauses['wheres']);
+
+ // merge joins to pass to get_entities()
+ if (isset($options['joins']) && !is_array($options['joins'])) {
+ $options['joins'] = array($options['joins']);
+ } elseif (!isset($options['joins'])) {
+ $options['joins'] = array();
+ }
+
+ $options['joins'] = array_merge($options['joins'], $clauses['joins']);
+
+ if ($clauses['orders']) {
+ $order_by_metadata = implode(", ", $clauses['orders']);
+ if (isset($options['order_by']) && $options['order_by']) {
+ $options['order_by'] = "$order_by_metadata, {$options['order_by']}";
+ } else {
+ $options['order_by'] = "$order_by_metadata, e.time_created DESC";
+ }
+ }
+ }
+
+ return $options;
+}
+
+// unit testing
+elgg_register_plugin_hook_handler('unit_test', 'system', 'metastrings_test');
+
+/**
+ * Metadata unit test
+ *
+ * @param string $hook unit_test
+ * @param string $type system
+ * @param mixed $value Array of other tests
+ * @param mixed $params Params
+ *
+ * @return array
+ */
+function metastrings_test($hook, $type, $value, $params) {
+ global $CONFIG;
+ $value[] = $CONFIG->path . 'engine/tests/api/metastrings.php';
+ return $value;
+}
diff --git a/engine/tests/api/metastrings.php b/engine/tests/api/metastrings.php
new file mode 100644
index 000000000..c18e42eb8
--- /dev/null
+++ b/engine/tests/api/metastrings.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Elgg Metastrings test
+ *
+ * @package Elgg.Core
+ * @subpackage Metastrings.Test
+ */
+class ElggCoreMetastringsTest extends ElggCoreUnitTest {
+
+ public $metastringTypes = array('metadata', 'annotations');
+
+ /**
+ * Called before each test object.
+ */
+ public function __construct() {
+ parent::__construct();
+
+ $this->metastrings = array();
+ $this->object = new ElggObject();
+ $this->object->save();
+ }
+
+ public function createAnnotations($max = 1) {
+ $annotations = array();
+ for ($i=0; $i<$max; $i++) {
+ $name = 'test_annotation_name' . rand();
+ $value = 'test_annotation_value' . rand();
+ $id = create_annotation($this->object->guid, $name, $value);
+ $annotations[] = $id;
+ }
+
+ return $annotations;
+ }
+
+ public function createMetadata($max = 1) {
+ $metadata = array();
+ for ($i=0; $i<$max; $i++) {
+ $name = 'test_metadata_name' . rand();
+ $value = 'test_metadata_value' . rand();
+ $id = create_metadata($this->object->guid, $name, $value);
+ $metadata[] = $id;
+ }
+
+ return $metadata;
+ }
+
+ /**
+ * Called before each test method.
+ */
+ public function setUp() {
+
+ }
+
+ /**
+ * Called after each test method.
+ */
+ public function tearDown() {
+ // do not allow SimpleTest to interpret Elgg notices as exceptions
+ $this->swallowErrors();
+ }
+
+ /**
+ * Called after each test object.
+ */
+ public function __destruct() {
+ $this->object->delete();
+
+ parent::__destruct();
+ }
+
+ /**
+ * A basic test that will be called and fail.
+ */
+ public function testDeleteByID() {
+ $db_prefix = elgg_get_config('dbprefix');
+ $annotations = $this->createAnnotations(1);
+ $metadata = $this->createMetadata(1);
+
+ foreach ($this->metastringTypes as $type) {
+ $id = ${$type}[0];
+ $table = $db_prefix . $type;
+ $q = "SELECT * FROM $table WHERE id = $id";
+ $test = get_data($q);
+
+ $this->assertEqual($test[0]->id, $id);
+ $this->assertTrue(elgg_delete_metastring_based_object_by_id($id, $type));
+ $this->assertFalse(get_data($q));
+ }
+ }
+
+ public function testGetMetastringObjectByID() {
+ $db_prefix = elgg_get_config('dbprefix');
+ $annotations = $this->createAnnotations(1);
+ $metadata = $this->createMetadata(1);
+
+ foreach ($this->metastringTypes as $type) {
+ $id = ${$type}[0];
+ $test = elgg_get_metastring_based_object_by_id($id, $type);
+
+ $this->assertEqual($id, $test->id);
+ }
+ }
+
+ /**
+ * A basic test that will be called and fail.
+ */
+ public function testEnableDisableByID() {
+ $db_prefix = elgg_get_config('dbprefix');
+ $annotations = $this->createAnnotations(1);
+ $metadata = $this->createMetadata(1);
+
+ foreach ($this->metastringTypes as $type) {
+ $id = ${$type}[0];
+ $table = $db_prefix . $type;
+ $q = "SELECT * FROM $table WHERE id = $id";
+ $test = get_data($q);
+
+ // disable
+ $this->assertEqual($test[0]->enabled, 'yes');
+ $this->assertTrue(elgg_set_metastring_based_object_enabled_by_id($id, 'no', $type));
+
+ $test = get_data($q);
+ $this->assertEqual($test[0]->enabled, 'no');
+
+ // enable
+ $ashe = access_get_show_hidden_status();
+ access_show_hidden_entities(true);
+ flush();
+ $this->assertTrue(elgg_set_metastring_based_object_enabled_by_id($id, 'yes', $type));
+
+ $test = get_data($q);
+ $this->assertEqual($test[0]->enabled, 'yes');
+
+ access_show_hidden_entities($ashe);
+ }
+ }
+
+
+}