aboutsummaryrefslogtreecommitdiff
path: root/engine/lib/entities.php
diff options
context:
space:
mode:
Diffstat (limited to 'engine/lib/entities.php')
-rw-r--r--engine/lib/entities.php2302
1 files changed, 1018 insertions, 1284 deletions
diff --git a/engine/lib/entities.php b/engine/lib/entities.php
index 534b61e19..4fcf1c657 100644
--- a/engine/lib/entities.php
+++ b/engine/lib/entities.php
@@ -13,41 +13,71 @@
* @global array $ENTITY_CACHE
* @access private
*/
-$ENTITY_CACHE = NULL;
+global $ENTITY_CACHE;
+$ENTITY_CACHE = array();
/**
- * Cache subtypes and related class names once loaded.
+ * GUIDs of entities banned from the entity cache (during this request)
*
- * @global array $SUBTYPE_CACHE
+ * @global array $ENTITY_CACHE_DISABLED_GUIDS
* @access private
*/
-$SUBTYPE_CACHE = NULL;
+global $ENTITY_CACHE_DISABLED_GUIDS;
+$ENTITY_CACHE_DISABLED_GUIDS = array();
/**
- * Initialise the entity cache.
- * @todo remove this.
+ * Cache subtypes and related class names.
+ *
+ * @global array|null $SUBTYPE_CACHE array once populated from DB, initially null
* @access private
*/
-function initialise_entity_cache() {
- global $ENTITY_CACHE;
+global $SUBTYPE_CACHE;
+$SUBTYPE_CACHE = null;
- if (!$ENTITY_CACHE) {
- $ENTITY_CACHE = array();
- }
+/**
+ * Remove this entity from the entity cache and make sure it is not re-added
+ *
+ * @param int $guid The entity guid
+ *
+ * @access private
+ * @todo this is a workaround until #5604 can be implemented
+ */
+function _elgg_disable_caching_for_entity($guid) {
+ global $ENTITY_CACHE_DISABLED_GUIDS;
+
+ _elgg_invalidate_cache_for_entity($guid);
+ $ENTITY_CACHE_DISABLED_GUIDS[$guid] = true;
+}
+
+/**
+ * Allow this entity to be stored in the entity cache
+ *
+ * @param int $guid The entity guid
+ *
+ * @access private
+ */
+function _elgg_enable_caching_for_entity($guid) {
+ global $ENTITY_CACHE_DISABLED_GUIDS;
+
+ unset($ENTITY_CACHE_DISABLED_GUIDS[$guid]);
}
/**
* Invalidate this class's entry in the cache.
*
* @param int $guid The entity guid
+ *
+ * @return void
* @access private
*/
-function invalidate_cache_for_entity($guid) {
+function _elgg_invalidate_cache_for_entity($guid) {
global $ENTITY_CACHE;
$guid = (int)$guid;
unset($ENTITY_CACHE[$guid]);
+
+ elgg_get_metadata_cache()->clear($guid);
}
/**
@@ -56,29 +86,57 @@ function invalidate_cache_for_entity($guid) {
* Stores an entity in $ENTITY_CACHE;
*
* @param ElggEntity $entity Entity to cache
- * @see retrieve_cached_entity()
- * @see invalidate_cache_for_entity()
+ *
+ * @return void
+ * @see _elgg_retrieve_cached_entity()
+ * @see _elgg_invalidate_cache_for_entity()
* @access private
+ * @todo Use an ElggCache object
*/
-function cache_entity(ElggEntity $entity) {
- global $ENTITY_CACHE;
+function _elgg_cache_entity(ElggEntity $entity) {
+ global $ENTITY_CACHE, $ENTITY_CACHE_DISABLED_GUIDS;
- $ENTITY_CACHE[$entity->guid] = $entity;
+ // Don't cache non-plugin entities while access control is off, otherwise they could be
+ // exposed to users who shouldn't see them when control is re-enabled.
+ if (!($entity instanceof ElggPlugin) && elgg_get_ignore_access()) {
+ return;
+ }
+
+ $guid = $entity->getGUID();
+ if (isset($ENTITY_CACHE_DISABLED_GUIDS[$guid])) {
+ return;
+ }
+
+ // Don't store too many or we'll have memory problems
+ // @todo Pick a less arbitrary limit
+ if (count($ENTITY_CACHE) > 256) {
+ $random_guid = array_rand($ENTITY_CACHE);
+
+ unset($ENTITY_CACHE[$random_guid]);
+
+ // Purge separate metadata cache. Original idea was to do in entity destructor, but that would
+ // have caused a bunch of unnecessary purges at every shutdown. Doing it this way we have no way
+ // to know that the expunged entity will be GCed (might be another reference living), but that's
+ // OK; the metadata will reload if necessary.
+ elgg_get_metadata_cache()->clear($random_guid);
+ }
+
+ $ENTITY_CACHE[$guid] = $entity;
}
/**
* Retrieve a entity from the cache.
*
* @param int $guid The guid
- * @see cache_entity()
- * @see invalidate_cache_for_entity()
+ *
+ * @return ElggEntity|bool false if entity not cached, or not fully loaded
+ * @see _elgg_cache_entity()
+ * @see _elgg_invalidate_cache_for_entity()
* @access private
*/
-function retrieve_cached_entity($guid) {
+function _elgg_retrieve_cached_entity($guid) {
global $ENTITY_CACHE;
- $guid = (int)$guid;
-
if (isset($ENTITY_CACHE[$guid])) {
if ($ENTITY_CACHE[$guid]->isFullyLoaded()) {
return $ENTITY_CACHE[$guid];
@@ -89,29 +147,6 @@ function retrieve_cached_entity($guid) {
}
/**
- * As retrieve_cached_entity, but returns the result as a stdClass (compatible with load functions that
- * expect a database row.)
- *
- * @param int $guid The guid
- * @todo unused
- * @access private
- */
-function retrieve_cached_entity_row($guid) {
- $obj = retrieve_cached_entity($guid);
- if ($obj) {
- $tmp = new stdClass;
-
- foreach ($obj as $k => $v) {
- $tmp->$k = $v;
- }
-
- return $tmp;
- }
-
- return false;
-}
-
-/**
* Return the id for a given subtype.
*
* ElggEntity objects have a type and a subtype. Subtypes
@@ -127,147 +162,159 @@ function retrieve_cached_entity_row($guid) {
* @internal Subtypes are stored in the entity_subtypes table. There is a foreign
* key in the entities table.
*
- * @todo Move to a nicer place?
+ * @param string $type Type
+ * @param string $subtype Subtype
*
- * @param string $type
- * @param string $subtype
* @return int Subtype ID
* @link http://docs.elgg.org/DataModel/Entities/Subtypes
* @see get_subtype_from_id()
* @access private
*/
function get_subtype_id($type, $subtype) {
- global $CONFIG, $SUBTYPE_CACHE;
-
- $type = sanitise_string($type);
- $subtype = sanitise_string($subtype);
+ global $SUBTYPE_CACHE;
- if ($subtype=="") {
- return FALSE;
+ if (!$subtype) {
+ return false;
}
- // Todo: cache here? Or is looping less efficient that going to the db each time?
- $result = get_data_row("SELECT * from {$CONFIG->dbprefix}entity_subtypes
- where type='$type' and subtype='$subtype'");
-
- if ($result) {
- if (!$SUBTYPE_CACHE) {
- $SUBTYPE_CACHE = array();
- }
+ if ($SUBTYPE_CACHE === null) {
+ _elgg_populate_subtype_cache();
+ }
- $SUBTYPE_CACHE[$result->id] = $result;
+ // use the cache before hitting database
+ $result = _elgg_retrieve_cached_subtype($type, $subtype);
+ if ($result !== null) {
return $result->id;
}
- return FALSE;
+ return false;
}
/**
* Return string name for a given subtype ID.
*
- * @todo Move to a nicer place?
+ * @param int $subtype_id Subtype ID
*
- * @param int $subtype_id
- * @return string Subtype name
+ * @return string|false Subtype name, false if subtype not found
* @link http://docs.elgg.org/DataModel/Entities/Subtypes
* @see get_subtype_from_id()
* @access private
*/
function get_subtype_from_id($subtype_id) {
- global $CONFIG, $SUBTYPE_CACHE;
-
- $subtype_id = (int)$subtype_id;
+ global $SUBTYPE_CACHE;
if (!$subtype_id) {
return false;
}
+ if ($SUBTYPE_CACHE === null) {
+ _elgg_populate_subtype_cache();
+ }
+
if (isset($SUBTYPE_CACHE[$subtype_id])) {
return $SUBTYPE_CACHE[$subtype_id]->subtype;
}
- $result = get_data_row("SELECT * from {$CONFIG->dbprefix}entity_subtypes where id=$subtype_id");
- if ($result) {
- if (!$SUBTYPE_CACHE) {
- $SUBTYPE_CACHE = array();
- }
+ return false;
+}
+
+/**
+ * Retrieve subtype from the cache.
+ *
+ * @param string $type
+ * @param string $subtype
+ * @return stdClass|null
+ *
+ * @access private
+ */
+function _elgg_retrieve_cached_subtype($type, $subtype) {
+ global $SUBTYPE_CACHE;
- $SUBTYPE_CACHE[$subtype_id] = $result;
- return $result->subtype;
+ if ($SUBTYPE_CACHE === null) {
+ _elgg_populate_subtype_cache();
}
- return false;
+ foreach ($SUBTYPE_CACHE as $obj) {
+ if ($obj->type === $type && $obj->subtype === $subtype) {
+ return $obj;
+ }
+ }
+ return null;
}
/**
- * Return a classname for a registered type and subtype.
+ * Fetch all suptypes from DB to local cache.
+ *
+ * @access private
+ */
+function _elgg_populate_subtype_cache() {
+ global $CONFIG, $SUBTYPE_CACHE;
+
+ $results = get_data("SELECT * FROM {$CONFIG->dbprefix}entity_subtypes");
+
+ $SUBTYPE_CACHE = array();
+ foreach ($results as $row) {
+ $SUBTYPE_CACHE[$row->id] = $row;
+ }
+}
+
+/**
+ * Return the class name for a registered type and subtype.
*
* Entities can be registered to always be loaded as a certain class
- * with {@link register_entity_subtype()}. This function returns
- * the class name if found, and NULL if not.
+ * with add_subtype() or update_subtype(). This function returns the class
+ * name if found and NULL if not.
*
- * @param string $type The type
+ * @param string $type The type
* @param string $subtype The subtype
+ *
* @return string|null a class name or null
* @see get_subtype_from_id()
* @see get_subtype_class_from_id()
* @access private
*/
function get_subtype_class($type, $subtype) {
- global $CONFIG, $SUBTYPE_CACHE;
-
- $type = sanitise_string($type);
- $subtype = sanitise_string($subtype);
-
- // Todo: cache here? Or is looping less efficient that going to the db each time?
- $result = get_data_row("SELECT * from {$CONFIG->dbprefix}entity_subtypes
- where type='$type' and subtype='$subtype'");
+ global $SUBTYPE_CACHE;
- if ($result) {
- if (!$SUBTYPE_CACHE) {
- $SUBTYPE_CACHE = array();
- }
-
- $SUBTYPE_CACHE[$result->id] = $result;
- return $result->class;
+ if ($SUBTYPE_CACHE === null) {
+ _elgg_populate_subtype_cache();
+ }
+
+ // use the cache before going to the database
+ $obj = _elgg_retrieve_cached_subtype($type, $subtype);
+ if ($obj) {
+ return $obj->class;
}
- return NULL;
+ return null;
}
/**
- * Returns the classname for a subtype id.
+ * Returns the class name for a subtype id.
*
* @param int $subtype_id The subtype id
+ *
* @return string|null
* @see get_subtype_class()
* @see get_subtype_from_id()
* @access private
*/
function get_subtype_class_from_id($subtype_id) {
- global $CONFIG, $SUBTYPE_CACHE;
-
- $subtype_id = (int)$subtype_id;
+ global $SUBTYPE_CACHE;
if (!$subtype_id) {
- return false;
+ return null;
}
+ if ($SUBTYPE_CACHE === null) {
+ _elgg_populate_subtype_cache();
+ }
+
if (isset($SUBTYPE_CACHE[$subtype_id])) {
return $SUBTYPE_CACHE[$subtype_id]->class;
}
- $result = get_data_row("SELECT * from {$CONFIG->dbprefix}entity_subtypes where id=$subtype_id");
-
- if ($result) {
- if (!$SUBTYPE_CACHE) {
- $SUBTYPE_CACHE = array();
- }
- $SUBTYPE_CACHE[$subtype_id] = $result;
- return $result->class;
- }
-
- return NULL;
+ return null;
}
/**
@@ -278,9 +325,14 @@ function get_subtype_class_from_id($subtype_id) {
* it will be loaded as that class automatically when retrieved from the database with
* {@link get_entity()}.
*
- * @param string $type The type you're subtyping (site, user, object, or group)
+ * @warning This function cannot be used to change the class for a type-subtype pair.
+ * Use update_subtype() for that.
+ *
+ * @param string $type The type you're subtyping (site, user, object, or group)
* @param string $subtype The subtype
- * @param string $class Optional class name for the object
+ * @param string $class Optional class name for the object
+ *
+ * @return int
* @link http://docs.elgg.org/Tutorials/Subclasses
* @link http://docs.elgg.org/DataModel/Entities
* @see update_subtype()
@@ -288,20 +340,32 @@ function get_subtype_class_from_id($subtype_id) {
* @see get_entity()
*/
function add_subtype($type, $subtype, $class = "") {
- global $CONFIG;
- $type = sanitise_string($type);
- $subtype = sanitise_string($subtype);
- $class = sanitise_string($class);
+ global $CONFIG, $SUBTYPE_CACHE;
- // Short circuit if no subtype is given
- if ($subtype == "") {
+ if (!$subtype) {
return 0;
}
$id = get_subtype_id($type, $subtype);
- if ($id==0) {
- return insert_data("insert into {$CONFIG->dbprefix}entity_subtypes (type, subtype, class) values ('$type','$subtype','$class')");
+ if (!$id) {
+ // In cache we store non-SQL-escaped strings because that's what's returned by query
+ $cache_obj = (object) array(
+ 'type' => $type,
+ 'subtype' => $subtype,
+ 'class' => $class,
+ );
+
+ $type = sanitise_string($type);
+ $subtype = sanitise_string($subtype);
+ $class = sanitise_string($class);
+
+ $id = insert_data("INSERT INTO {$CONFIG->dbprefix}entity_subtypes"
+ . " (type, subtype, class) VALUES ('$type', '$subtype', '$class')");
+
+ // add entry to cache
+ $cache_obj->id = $id;
+ $SUBTYPE_CACHE[$id] = $cache_obj;
}
return $id;
@@ -310,8 +374,14 @@ function add_subtype($type, $subtype, $class = "") {
/**
* Removes a registered ElggEntity type, subtype, and classname.
*
- * @param string $type
- * @param string $subtype
+ * @warning You do not want to use this function. If you want to unregister
+ * a class for a subtype, use update_subtype(). Using this function will
+ * permanently orphan all the objects created with the specified subtype.
+ *
+ * @param string $type Type
+ * @param string $subtype Subtype
+ *
+ * @return bool
* @see add_subtype()
* @see update_subtype()
*/
@@ -321,29 +391,47 @@ function remove_subtype($type, $subtype) {
$type = sanitise_string($type);
$subtype = sanitise_string($subtype);
- return delete_data("DELETE FROM {$CONFIG->dbprefix}entity_subtypes WHERE type = '$type' AND subtype = '$subtype'");
+ return delete_data("DELETE FROM {$CONFIG->dbprefix}entity_subtypes"
+ . " WHERE type = '$type' AND subtype = '$subtype'");
}
/**
- * Update a registered ElggEntity type, subtype, and classname
+ * Update a registered ElggEntity type, subtype, and class name
*
- * @param string $type
- * @param string $subtype
- * @param string $class
+ * @param string $type Type
+ * @param string $subtype Subtype
+ * @param string $class Class name to use when loading this entity
+ *
+ * @return bool
*/
function update_subtype($type, $subtype, $class = '') {
- global $CONFIG;
+ global $CONFIG, $SUBTYPE_CACHE;
- if (!$id = get_subtype_id($type, $subtype)) {
- return FALSE;
+ $id = get_subtype_id($type, $subtype);
+ if (!$id) {
+ return false;
+ }
+
+ if ($SUBTYPE_CACHE === null) {
+ _elgg_populate_subtype_cache();
}
+
+ $unescaped_class = $class;
+
$type = sanitise_string($type);
$subtype = sanitise_string($subtype);
-
- return update_data("UPDATE {$CONFIG->dbprefix}entity_subtypes
+ $class = sanitise_string($class);
+
+ $success = update_data("UPDATE {$CONFIG->dbprefix}entity_subtypes
SET type = '$type', subtype = '$subtype', class = '$class'
WHERE id = $id
");
+
+ if ($success && isset($SUBTYPE_CACHE[$id])) {
+ $SUBTYPE_CACHE[$id]->class = $unescaped_class;
+ }
+
+ return $success;
}
/**
@@ -354,15 +442,17 @@ function update_subtype($type, $subtype, $class = '') {
*
* @warning Plugin authors should never call this directly. Use ->save() instead.
*
- * @param int $guid
- * @param int $owner_guid
- * @param int $access_id
- * @param int $container_guid
+ * @param int $guid The guid of the entity to update
+ * @param int $owner_guid The new owner guid
+ * @param int $access_id The new access id
+ * @param int $container_guid The new container guid
+ * @param int $time_created The time creation timestamp
+ *
* @return bool
- * @link http://docs.elgg.org/DataModel/Entities
+ * @throws InvalidParameterException
* @access private
*/
-function update_entity($guid, $owner_guid, $access_id, $container_guid = null) {
+function update_entity($guid, $owner_guid, $access_id, $container_guid = null, $time_created = null) {
global $CONFIG, $ENTITY_CACHE;
$guid = (int)$guid;
@@ -376,12 +466,25 @@ function update_entity($guid, $owner_guid, $access_id, $container_guid = null) {
$entity = get_entity($guid);
+ if ($time_created == null) {
+ $time_created = $entity->time_created;
+ } else {
+ $time_created = (int) $time_created;
+ }
+
+ if ($access_id == ACCESS_DEFAULT) {
+ throw new InvalidParameterException('ACCESS_DEFAULT is not a valid access level. See its documentation in elgglib.h');
+ }
+
if ($entity && $entity->canEdit()) {
- if (trigger_elgg_event('update', $entity->type, $entity)) {
- $ret = update_data("UPDATE {$CONFIG->dbprefix}entities set owner_guid='$owner_guid', access_id='$access_id', container_guid='$container_guid', time_updated='$time' WHERE guid=$guid");
+ if (elgg_trigger_event('update', $entity->type, $entity)) {
+ $ret = update_data("UPDATE {$CONFIG->dbprefix}entities
+ set owner_guid='$owner_guid', access_id='$access_id',
+ container_guid='$container_guid', time_created='$time_created',
+ time_updated='$time' WHERE guid=$guid");
if ($entity instanceof ElggObject) {
- update_river_access_by_object($guid,$access_id);
+ update_river_access_by_object($guid, $access_id);
}
// If memcache is available then delete this entry from the cache
@@ -390,11 +493,11 @@ function update_entity($guid, $owner_guid, $access_id, $container_guid = null) {
$newentity_cache = new ElggMemcache('new_entity_cache');
}
if ($newentity_cache) {
- $new_entity = $newentity_cache->delete($guid);
+ $newentity_cache->delete($guid);
}
// Handle cases where there was no error BUT no rows were updated!
- if ($ret===false) {
+ if ($ret === false) {
return false;
}
@@ -404,7 +507,7 @@ function update_entity($guid, $owner_guid, $access_id, $container_guid = null) {
}
/**
- * Determine if a given user is can write to an entity container.
+ * Determine if a given user can write to an entity container.
*
* An entity can be a container for any other entity by setting the
* container_guid. container_guid can differ from owner_guid.
@@ -412,27 +515,30 @@ function update_entity($guid, $owner_guid, $access_id, $container_guid = null) {
* A plugin hook container_permissions_check:$entity_type is emitted to allow granular
* access controls in plugins.
*
- * @param int $user_guid The user guid, or 0 for get_loggedin_userid()
- * @param int $container_guid The container, or 0 for the current page owner.
+ * @param int $user_guid The user guid, or 0 for logged in user
+ * @param int $container_guid The container, or 0 for the current page owner.
+ * @param string $type The type of entity we're looking to write
+ * @param string $subtype The subtype of the entity we're looking to write
+ *
* @return bool
* @link http://docs.elgg.org/DataModel/Containers
*/
-function can_write_to_container($user_guid = 0, $container_guid = 0, $entity_type = 'all') {
- global $CONFIG;
-
+function can_write_to_container($user_guid = 0, $container_guid = 0, $type = 'all', $subtype = 'all') {
$user_guid = (int)$user_guid;
$user = get_entity($user_guid);
if (!$user) {
- $user = get_loggedin_user();
+ $user = elgg_get_logged_in_user_entity();
}
$container_guid = (int)$container_guid;
if (!$container_guid) {
- $container_guid = page_owner();
+ $container_guid = elgg_get_page_owner_guid();
}
+ $return = false;
+
if (!$container_guid) {
- $return = TRUE;
+ $return = true;
}
$container = get_entity($container_guid);
@@ -440,23 +546,29 @@ function can_write_to_container($user_guid = 0, $container_guid = 0, $entity_typ
if ($container) {
// If the user can edit the container, they can also write to it
if ($container->canEdit($user_guid)) {
- $return = TRUE;
+ $return = true;
}
- // Basics, see if the user is a member of the group.
- // @todo this should be moved to the groups plugin
- if ($user && $container instanceof ElggGroup) {
- if (!$container->isMember($user)) {
- $return = FALSE;
- } else {
- $return = TRUE;
+ // If still not approved, see if the user is a member of the group
+ // @todo this should be moved to the groups plugin/library
+ if (!$return && $user && $container instanceof ElggGroup) {
+ /* @var ElggGroup $container */
+ if ($container->isMember($user)) {
+ $return = true;
}
}
}
// See if anyone else has anything to say
- return trigger_plugin_hook('container_permissions_check', $entity_type,
- array('container' => $container, 'user' => $user), $return);
+ return elgg_trigger_plugin_hook(
+ 'container_permissions_check',
+ $type,
+ array(
+ 'container' => $container,
+ 'user' => $user,
+ 'subtype' => $subtype
+ ),
+ $return);
}
/**
@@ -470,23 +582,26 @@ function can_write_to_container($user_guid = 0, $container_guid = 0, $entity_typ
* @warning Entities must have an entry in both the entities table and their type table
* or they will throw an exception when loaded.
*
- * @param string $type The type of the entity (site, user, object, group).
- * @param string $subtype The subtype of the entity.
- * @param int $owner_guid The GUID of the object's owner.
- * @param int $access_id The access control group to create the entity with.
- * @param int $site_guid The site to add this entity to. Leave as 0 (default) for the current site.
+ * @param string $type The type of the entity (site, user, object, group).
+ * @param string $subtype The subtype of the entity.
+ * @param int $owner_guid The GUID of the object's owner.
+ * @param int $access_id The access control group to create the entity with.
+ * @param int $site_guid The site to add this entity to. 0 for current.
+ * @param int $container_guid The container GUID
+ *
* @return int|false The new entity's GUID, or false on failure
* @throws InvalidParameterException
- * @access private
* @link http://docs.elgg.org/DataModel/Entities
+ * @access private
*/
-function create_entity($type, $subtype, $owner_guid, $access_id, $site_guid = 0, $container_guid = 0) {
+function create_entity($type, $subtype, $owner_guid, $access_id, $site_guid = 0,
+$container_guid = 0) {
+
global $CONFIG;
$type = sanitise_string($type);
- $subtype = add_subtype($type, $subtype);
+ $subtype_id = add_subtype($type, $subtype);
$owner_guid = (int)$owner_guid;
- $access_id = (int)$access_id;
$time = time();
if ($site_guid == 0) {
$site_guid = $CONFIG->site_guid;
@@ -495,23 +610,30 @@ function create_entity($type, $subtype, $owner_guid, $access_id, $site_guid = 0,
if ($container_guid == 0) {
$container_guid = $owner_guid;
}
+ $access_id = (int)$access_id;
+ if ($access_id == ACCESS_DEFAULT) {
+ throw new InvalidParameterException('ACCESS_DEFAULT is not a valid access level. See its documentation in elgglib.h');
+ }
- $user = get_loggedin_user();
- if (!can_write_to_container($user->guid, $owner_guid, $type)) {
+ $user_guid = elgg_get_logged_in_user_guid();
+ if (!can_write_to_container($user_guid, $owner_guid, $type, $subtype)) {
return false;
}
if ($owner_guid != $container_guid) {
- if (!can_write_to_container($user->guid, $container_guid, $type)) {
+ if (!can_write_to_container($user_guid, $container_guid, $type, $subtype)) {
return false;
}
}
- if ($type=="") {
+ if ($type == "") {
throw new InvalidParameterException(elgg_echo('InvalidParameterException:EntityTypeNotSet'));
}
return insert_data("INSERT into {$CONFIG->dbprefix}entities
- (type, subtype, owner_guid, site_guid, container_guid, access_id, time_created, time_updated, last_action) values
- ('$type',$subtype, $owner_guid, $site_guid, $container_guid, $access_id, $time, $time, $time)");
+ (type, subtype, owner_guid, site_guid, container_guid,
+ access_id, time_created, time_updated, last_action)
+ values
+ ('$type',$subtype_id, $owner_guid, $site_guid, $container_guid,
+ $access_id, $time, $time, $time)");
}
/**
@@ -523,6 +645,7 @@ function create_entity($type, $subtype, $owner_guid, $access_id, $site_guid = 0,
* see {@link get_access_sql_suffix()}.
*
* @param int $guid The GUID of the object to extract
+ *
* @return stdClass|false
* @link http://docs.elgg.org/DataModel/Entities
* @see entity_row_to_elggstar()
@@ -546,13 +669,16 @@ function get_entity_as_row($guid) {
*
* Handles loading all tables into the correct class.
*
- * @param stdClass The row of the entry in the entities table.
- * @return object|false
+ * @param stdClass $row The row of the entry in the entities table.
+ *
+ * @return ElggEntity|false
* @link http://docs.elgg.org/DataModel/Entities
* @see get_entity_as_row()
* @see add_subtype()
* @see get_entity()
* @access private
+ *
+ * @throws ClassException|InstallationException
*/
function entity_row_to_elggstar($row) {
if (!($row instanceof stdClass)) {
@@ -579,19 +705,21 @@ function entity_row_to_elggstar($row) {
// load class for entity if one is registered
$classname = get_subtype_class_from_id($row->subtype);
- if ($classname!="") {
+ if ($classname != "") {
if (class_exists($classname)) {
$new_entity = new $classname($row);
if (!($new_entity instanceof ElggEntity)) {
- throw new ClassException(sprintf(elgg_echo('ClassException:ClassnameNotClass'), $classname, 'ElggEntity'));
+ $msg = elgg_echo('ClassException:ClassnameNotClass', array($classname, 'ElggEntity'));
+ throw new ClassException($msg);
}
} else {
- error_log(sprintf(elgg_echo('ClassNotFoundException:MissingClass'), $classname));
+ error_log(elgg_echo('ClassNotFoundException:MissingClass', array($classname)));
}
}
if (!$new_entity) {
+ //@todo Make this into a function
switch ($row->type) {
case 'object' :
$new_entity = new ElggObject($row);
@@ -606,7 +734,8 @@ function entity_row_to_elggstar($row) {
$new_entity = new ElggSite($row);
break;
default:
- throw new InstallationException(sprintf(elgg_echo('InstallationException:TypeNotSupported'), $row->type));
+ $msg = elgg_echo('InstallationException:TypeNotSupported', array($row->type));
+ throw new InstallationException($msg);
}
}
@@ -622,32 +751,92 @@ function entity_row_to_elggstar($row) {
* Loads and returns an entity object from a guid.
*
* @param int $guid The GUID of the entity
- * @return object The correct Elgg or custom object based upon entity type and subtype
+ *
+ * @return ElggEntity The correct Elgg or custom object based upon entity type and subtype
* @link http://docs.elgg.org/DataModel/Entities
*/
function get_entity($guid) {
- static $newentity_cache;
- $new_entity = false;
+ // This should not be a static local var. Notice that cache writing occurs in a completely
+ // different instance outside this function.
+ // @todo We need a single Memcache instance with a shared pool of namespace wrappers. This function would pull an instance from the pool.
+ static $shared_cache;
+
+ // We could also use: if (!(int) $guid) { return FALSE },
+ // but that evaluates to a false positive for $guid = TRUE.
+ // This is a bit slower, but more thorough.
+ if (!is_numeric($guid) || $guid === 0 || $guid === '0') {
+ return false;
+ }
+
+ // Check local cache first
+ $new_entity = _elgg_retrieve_cached_entity($guid);
+ if ($new_entity) {
+ return $new_entity;
+ }
- if (!is_numeric($guid)) {
- return FALSE;
+ // Check shared memory cache, if available
+ if (null === $shared_cache) {
+ if (is_memcache_available()) {
+ $shared_cache = new ElggMemcache('new_entity_cache');
+ } else {
+ $shared_cache = false;
+ }
}
- if ((!$newentity_cache) && (is_memcache_available())) {
- $newentity_cache = new ElggMemcache('new_entity_cache');
+ // until ACLs in memcache, DB query is required to determine access
+ $entity_row = get_entity_as_row($guid);
+ if (!$entity_row) {
+ return false;
}
- if ($newentity_cache) {
- $new_entity = $newentity_cache->load($guid);
+ if ($shared_cache) {
+ $cached_entity = $shared_cache->load($guid);
+ // @todo store ACLs in memcache https://github.com/elgg/elgg/issues/3018#issuecomment-13662617
+ if ($cached_entity) {
+ // @todo use ACL and cached entity access_id to determine if user can see it
+ return $cached_entity;
+ }
}
- if ($new_entity) {
- return $new_entity;
+ // don't let incomplete entities cause fatal exceptions
+ try {
+ $new_entity = entity_row_to_elggstar($entity_row);
+ } catch (IncompleteEntityException $e) {
+ return false;
}
- return entity_row_to_elggstar(get_entity_as_row($guid));
+ if ($new_entity) {
+ _elgg_cache_entity($new_entity);
+ }
+ return $new_entity;
}
+/**
+ * Does an entity exist?
+ *
+ * This function checks for the existence of an entity independent of access
+ * permissions. It is useful for situations when a user cannot access an entity
+ * and it must be determined whether entity has been deleted or the access level
+ * has changed.
+ *
+ * @param int $guid The GUID of the entity
+ *
+ * @return bool
+ * @since 1.8.0
+ */
+function elgg_entity_exists($guid) {
+ global $CONFIG;
+
+ $guid = sanitize_int($guid);
+
+ $query = "SELECT count(*) as total FROM {$CONFIG->dbprefix}entities WHERE guid = $guid";
+ $result = get_data_row($query);
+ if ($result->total == 0) {
+ return false;
+ } else {
+ return true;
+ }
+}
/**
* Returns an array of entities with optional filtering.
@@ -665,21 +854,28 @@ function get_entity($guid) {
*
* @param array $options Array in format:
*
- * types => NULL|STR entity type (SQL: type IN ('type1', 'type2') Joined with subtypes by AND...see below)
+ * types => NULL|STR entity type (type IN ('type1', 'type2')
+ * Joined with subtypes by AND. See below)
*
* subtypes => NULL|STR entity subtype (SQL: subtype IN ('subtype1', 'subtype2))
+ * Use ELGG_ENTITIES_NO_VALUE for no subtype.
*
- * type_subtype_pairs => NULL|ARR (array('type' => 'subtype')) (SQL: type = '$type' AND subtype = '$subtype') pairs
+ * type_subtype_pairs => NULL|ARR (array('type' => 'subtype'))
+ * (type = '$type' AND subtype = '$subtype') pairs
*
- * owner_guids => NULL|INT entity guid
+ * guids => NULL|ARR Array of entity guids
*
- * container_guids => NULL|INT container_guid
+ * owner_guids => NULL|ARR Array of owner guids
*
- * site_guids => NULL (current_site)|INT site_guid
+ * container_guids => NULL|ARR Array of container_guids
+ *
+ * site_guids => NULL (current_site)|ARR Array of site_guid
*
* order_by => NULL (time_created desc)|STR SQL order by clause
*
- * limit => NULL (10)|INT SQL limit clause
+ * reverse_order_by => BOOL Reverse the default order by clause
+ *
+ * limit => NULL (10)|INT SQL limit clause (0 means no limit)
*
* offset => NULL (0)|INT SQL offset clause
*
@@ -697,7 +893,9 @@ function get_entity($guid) {
*
* joins => array() Additional joins
*
- * @return mixed int if count is true, an array of entity objects, or false on failure
+ * callback => string A callback function to pass each row through
+ *
+ * @return mixed If count, int. If not count, array. false on errors.
* @since 1.7.0
* @see elgg_get_entities_from_metadata()
* @see elgg_get_entities_from_relationship()
@@ -714,6 +912,7 @@ function elgg_get_entities(array $options = array()) {
'subtypes' => ELGG_ENTITIES_ANY_VALUE,
'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE,
+ 'guids' => ELGG_ENTITIES_ANY_VALUE,
'owner_guids' => ELGG_ENTITIES_ANY_VALUE,
'container_guids' => ELGG_ENTITIES_ANY_VALUE,
'site_guids' => $CONFIG->site_guid,
@@ -723,6 +922,7 @@ function elgg_get_entities(array $options = array()) {
'created_time_lower' => ELGG_ENTITIES_ANY_VALUE,
'created_time_upper' => ELGG_ENTITIES_ANY_VALUE,
+ 'reverse_order_by' => false,
'order_by' => 'e.time_created desc',
'group_by' => ELGG_ENTITIES_ANY_VALUE,
'limit' => 10,
@@ -730,21 +930,27 @@ function elgg_get_entities(array $options = array()) {
'count' => FALSE,
'selects' => array(),
'wheres' => array(),
- 'joins' => array()
+ 'joins' => array(),
+
+ 'callback' => 'entity_row_to_elggstar',
+
+ '__ElggBatch' => null,
);
$options = array_merge($defaults, $options);
- // can't use helper function with type_subtype_pair because it's already an array...just need to merge it
+ // can't use helper function with type_subtype_pair because
+ // it's already an array...just need to merge it
if (isset($options['type_subtype_pair'])) {
if (isset($options['type_subtype_pairs'])) {
- $options['type_subtype_pairs'] = array_merge($options['type_subtype_pairs'], $options['type_subtype_pair']);
+ $options['type_subtype_pairs'] = array_merge($options['type_subtype_pairs'],
+ $options['type_subtype_pair']);
} else {
$options['type_subtype_pairs'] = $options['type_subtype_pair'];
}
}
- $singulars = array('type', 'subtype', 'owner_guid', 'container_guid', 'site_guid');
+ $singulars = array('type', 'subtype', 'guid', 'owner_guid', 'container_guid', 'site_guid');
$options = elgg_normalise_plural_options_array($options, $singulars);
// evaluate where clauses
@@ -754,16 +960,17 @@ function elgg_get_entities(array $options = array()) {
$wheres = $options['wheres'];
- $wheres[] = elgg_get_entity_type_subtype_where_sql('e', $options['types'], $options['subtypes'], $options['type_subtype_pairs']);
- $wheres[] = elgg_get_entity_site_where_sql('e', $options['site_guids']);
- $wheres[] = elgg_get_entity_owner_where_sql('e', $options['owner_guids']);
- $wheres[] = elgg_get_entity_container_where_sql('e', $options['container_guids']);
+ $wheres[] = elgg_get_entity_type_subtype_where_sql('e', $options['types'],
+ $options['subtypes'], $options['type_subtype_pairs']);
+
+ $wheres[] = elgg_get_guid_based_where_sql('e.guid', $options['guids']);
+ $wheres[] = elgg_get_guid_based_where_sql('e.owner_guid', $options['owner_guids']);
+ $wheres[] = elgg_get_guid_based_where_sql('e.container_guid', $options['container_guids']);
+ $wheres[] = elgg_get_guid_based_where_sql('e.site_guid', $options['site_guids']);
+
$wheres[] = elgg_get_entity_time_where_sql('e', $options['created_time_upper'],
$options['created_time_lower'], $options['modified_time_upper'], $options['modified_time_lower']);
- // remove identical where clauses
- $wheres = array_unique($wheres);
-
// see if any functions failed
// remove empty strings on successful functions
foreach ($wheres as $i => $where) {
@@ -774,6 +981,9 @@ function elgg_get_entities(array $options = array()) {
}
}
+ // remove identical where clauses
+ $wheres = array_unique($wheres);
+
// evaluate join clauses
if (!is_array($options['joins'])) {
$options['joins'] = array($options['joins']);
@@ -794,7 +1004,7 @@ function elgg_get_entities(array $options = array()) {
if ($options['selects']) {
$selects = '';
foreach ($options['selects'] as $select) {
- $selects = ", $select";
+ $selects .= ", $select";
}
} else {
$selects = '';
@@ -820,24 +1030,53 @@ function elgg_get_entities(array $options = array()) {
// Add access controls
$query .= get_access_sql_suffix('e');
+
+ // reverse order by
+ if ($options['reverse_order_by']) {
+ $options['order_by'] = elgg_sql_reverse_order_by_clause($options['order_by']);
+ }
+
if (!$options['count']) {
- if ($options['group_by'] = sanitise_string($options['group_by'])) {
+ if ($options['group_by']) {
$query .= " GROUP BY {$options['group_by']}";
}
- if ($options['order_by'] = sanitise_string($options['order_by'])) {
+ if ($options['order_by']) {
$query .= " ORDER BY {$options['order_by']}";
}
if ($options['limit']) {
- $limit = sanitise_int($options['limit']);
- $offset = sanitise_int($options['offset']);
+ $limit = sanitise_int($options['limit'], false);
+ $offset = sanitise_int($options['offset'], false);
$query .= " LIMIT $offset, $limit";
}
- $dt = get_data($query, "entity_row_to_elggstar");
+ if ($options['callback'] === 'entity_row_to_elggstar') {
+ $dt = _elgg_fetch_entities_from_sql($query, $options['__ElggBatch']);
+ } else {
+ $dt = get_data($query, $options['callback']);
+ }
+
+ if ($dt) {
+ // populate entity and metadata caches
+ $guids = array();
+ foreach ($dt as $item) {
+ // A custom callback could result in items that aren't ElggEntity's, so check for them
+ if ($item instanceof ElggEntity) {
+ _elgg_cache_entity($item);
+ // plugins usually have only settings
+ if (!$item instanceof ElggPlugin) {
+ $guids[] = $item->guid;
+ }
+ }
+ }
+ // @todo Without this, recursive delete fails. See #4568
+ reset($dt);
- //@todo normalize this to array()
+ if ($guids) {
+ elgg_get_metadata_cache()->populateFromEntities($guids);
+ }
+ }
return $dt;
} else {
$total = get_data_row($query);
@@ -846,99 +1085,111 @@ function elgg_get_entities(array $options = array()) {
}
/**
- * @deprecated 1.7. Use elgg_get_entities().
- * @param $type
- * @param $subtype
- * @param $owner_guid
- * @param $order_by
- * @param $limit
- * @param $offset
- * @param $count
- * @param $site_guid
- * @param $container_guid
- * @param $timelower
- * @param $timeupper
- * @return unknown_type
+ * Return entities from an SQL query generated by elgg_get_entities.
+ *
+ * @param string $sql
+ * @param ElggBatch $batch
+ * @return ElggEntity[]
+ *
+ * @access private
+ * @throws LogicException
*/
-function get_entities($type = "", $subtype = "", $owner_guid = 0, $order_by = "", $limit = 10, $offset = 0,
-$count = false, $site_guid = 0, $container_guid = null, $timelower = 0, $timeupper = 0) {
- elgg_deprecated_notice('get_entities() was deprecated by elgg_get_entities().', 1.7);
-
- // rewrite owner_guid to container_guid to emulate old functionality
- if ($owner_guid != "") {
- if (is_null($container_guid)) {
- $container_guid = $owner_guid;
- $owner_guid = NULL;
- }
+function _elgg_fetch_entities_from_sql($sql, ElggBatch $batch = null) {
+ static $plugin_subtype;
+ if (null === $plugin_subtype) {
+ $plugin_subtype = get_subtype_id('object', 'plugin');
}
- $options = array();
- if ($type) {
- if (is_array($type)) {
- $options['types'] = $type;
- } else {
- $options['type'] = $type;
- }
- }
+ // Keys are types, values are columns that, if present, suggest that the secondary
+ // table is already JOINed
+ $types_to_optimize = array(
+ 'object' => 'title',
+ 'user' => 'password',
+ 'group' => 'name',
+ );
- if ($subtype) {
- if (is_array($subtype)) {
- $options['subtypes'] = $subtype;
- } else {
- $options['subtype'] = $subtype;
+ $rows = get_data($sql);
+
+ // guids to look up in each type
+ $lookup_types = array();
+ // maps GUIDs to the $rows key
+ $guid_to_key = array();
+
+ if (isset($rows[0]->type, $rows[0]->subtype)
+ && $rows[0]->type === 'object'
+ && $rows[0]->subtype == $plugin_subtype) {
+ // Likely the entire resultset is plugins, which have already been optimized
+ // to JOIN the secondary table. In this case we allow retrieving from cache,
+ // but abandon the extra queries.
+ $types_to_optimize = array();
+ }
+
+ // First pass: use cache where possible, gather GUIDs that we're optimizing
+ foreach ($rows as $i => $row) {
+ if (empty($row->guid) || empty($row->type)) {
+ throw new LogicException('Entity row missing guid or type');
+ }
+ if ($entity = _elgg_retrieve_cached_entity($row->guid)) {
+ $rows[$i] = $entity;
+ continue;
+ }
+ if (isset($types_to_optimize[$row->type])) {
+ // check if row already looks JOINed.
+ if (isset($row->{$types_to_optimize[$row->type]})) {
+ // Row probably already contains JOINed secondary table. Don't make another query just
+ // to pull data that's already there
+ continue;
+ }
+ $lookup_types[$row->type][] = $row->guid;
+ $guid_to_key[$row->guid] = $i;
+ }
+ }
+ // Do secondary queries and merge rows
+ if ($lookup_types) {
+ $dbprefix = elgg_get_config('dbprefix');
+
+ foreach ($lookup_types as $type => $guids) {
+ $set = "(" . implode(',', $guids) . ")";
+ $sql = "SELECT * FROM {$dbprefix}{$type}s_entity WHERE guid IN $set";
+ $secondary_rows = get_data($sql);
+ if ($secondary_rows) {
+ foreach ($secondary_rows as $secondary_row) {
+ $key = $guid_to_key[$secondary_row->guid];
+ // cast to arrays to merge then cast back
+ $rows[$key] = (object)array_merge((array)$rows[$key], (array)$secondary_row);
+ }
+ }
}
}
-
- if ($owner_guid) {
- if (is_array($owner_guid)) {
- $options['owner_guids'] = $owner_guid;
+ // Second pass to finish conversion
+ foreach ($rows as $i => $row) {
+ if ($row instanceof ElggEntity) {
+ continue;
} else {
- $options['owner_guid'] = $owner_guid;
+ try {
+ $rows[$i] = entity_row_to_elggstar($row);
+ } catch (IncompleteEntityException $e) {
+ // don't let incomplete entities throw fatal errors
+ unset($rows[$i]);
+
+ // report incompletes to the batch process that spawned this query
+ if ($batch) {
+ $batch->reportIncompleteEntity($row);
+ }
+ }
}
}
-
- if ($order_by) {
- $options['order_by'] = $order_by;
- }
-
- // need to pass 0 for all option
- $options['limit'] = $limit;
-
- if ($offset) {
- $options['offset'] = $offset;
- }
-
- if ($count) {
- $options['count'] = $count;
- }
-
- if ($site_guid) {
- $options['site_guids'] = $site_guid;
- }
-
- if ($container_guid) {
- $options['container_guids'] = $container_guid;
- }
-
- if ($timeupper) {
- $options['created_time_upper'] = $timeupper;
- }
-
- if ($timelower) {
- $options['created_time_lower'] = $timelower;
- }
-
- $r = elgg_get_entities($options);
- return $r;
+ return $rows;
}
/**
* Returns SQL where clause for type and subtype on main entity table
*
- * @param string $table entity table prefix as defined in SELECT ... FROM prefix_entities $table
- * @param NULL|$types
- * @param NULL|array $subtypes
- * @param NULL|array $pairs
+ * @param string $table Entity table prefix as defined in SELECT...FROM entities $table
+ * @param NULL|array $types Array of types or NULL if none.
+ * @param NULL|array $subtypes Array of subtypes or NULL if none
+ * @param NULL|array $pairs Array of pairs of types and subtypes
+ *
* @return FALSE|string
* @since 1.7.0
* @access private
@@ -955,8 +1206,8 @@ function elgg_get_entity_type_subtype_where_sql($table, $types, $subtypes, $pair
return '';
}
- // these are the only valid types for entities in elgg as defined in the DB.
- $valid_types = array('object', 'user', 'group', 'site');
+ // these are the only valid types for entities in elgg
+ $valid_types = elgg_get_config('entity_types');
// pairs override
$wheres = array();
@@ -982,7 +1233,7 @@ function elgg_get_entity_type_subtype_where_sql($table, $types, $subtypes, $pair
foreach ($types as $type) {
if (!in_array($type, $valid_types)) {
$valid_types_count--;
- unset ($types[array_search($type, $types)]);
+ unset($types[array_search($type, $types)]);
} else {
// do the checking (and decrementing) in the subtype section.
$valid_subtypes_count += count($subtypes);
@@ -1000,13 +1251,24 @@ function elgg_get_entity_type_subtype_where_sql($table, $types, $subtypes, $pair
$subtype_ids = array();
if ($subtypes) {
foreach ($subtypes as $subtype) {
- // check that the subtype is valid (with ELGG_ENTITIES_NO_VALUE being a valid subtype)
- if (ELGG_ENTITIES_NO_VALUE === $subtype || $subtype_id = get_subtype_id($type, $subtype)) {
- $subtype_ids[] = (ELGG_ENTITIES_NO_VALUE === $subtype) ? ELGG_ENTITIES_NO_VALUE : $subtype_id;
- } else {
- $valid_subtypes_count--;
- elgg_log("Type-subtype $type:$subtype' does not exist!", 'WARNING');
+ // check that the subtype is valid
+ if (!$subtype && ELGG_ENTITIES_NO_VALUE === $subtype) {
+ // subtype value is 0
+ $subtype_ids[] = ELGG_ENTITIES_NO_VALUE;
+ } elseif (!$subtype) {
+ // subtype is ignored.
+ // this handles ELGG_ENTITIES_ANY_VALUE, '', and anything falsy that isn't 0
continue;
+ } else {
+ $subtype_id = get_subtype_id($type, $subtype);
+
+ if ($subtype_id) {
+ $subtype_ids[] = $subtype_id;
+ } else {
+ $valid_subtypes_count--;
+ elgg_log("Type-subtype '$type:$subtype' does not exist!", 'NOTICE');
+ continue;
+ }
}
}
@@ -1034,7 +1296,7 @@ function elgg_get_entity_type_subtype_where_sql($table, $types, $subtypes, $pair
foreach ($pairs as $paired_type => $paired_subtypes) {
if (!in_array($paired_type, $valid_types)) {
$valid_pairs_count--;
- unset ($pairs[array_search($paired_type, $pairs)]);
+ unset($pairs[array_search($paired_type, $pairs)]);
} else {
if ($paired_subtypes && !is_array($paired_subtypes)) {
$pairs[$paired_type] = array($paired_subtypes);
@@ -1052,11 +1314,14 @@ function elgg_get_entity_type_subtype_where_sql($table, $types, $subtypes, $pair
if (is_array($paired_subtypes)) {
$paired_subtype_ids = array();
foreach ($paired_subtypes as $paired_subtype) {
- if (ELGG_ENTITIES_NO_VALUE === $paired_subtype || ($paired_subtype_id = get_subtype_id($paired_type, $paired_subtype))) {
- $paired_subtype_ids[] = (ELGG_ENTITIES_NO_VALUE === $paired_subtype) ? ELGG_ENTITIES_NO_VALUE : $paired_subtype_id;
+ if (ELGG_ENTITIES_NO_VALUE === $paired_subtype
+ || ($paired_subtype_id = get_subtype_id($paired_type, $paired_subtype))) {
+
+ $paired_subtype_ids[] = (ELGG_ENTITIES_NO_VALUE === $paired_subtype) ?
+ ELGG_ENTITIES_NO_VALUE : $paired_subtype_id;
} else {
$valid_pairs_subtypes_count--;
- elgg_log("Type-subtype $paired_type:$paired_subtype' does not exist!", 'WARNING');
+ elgg_log("Type-subtype '$paired_type:$paired_subtype' does not exist!", 'NOTICE');
// return false if we're all invalid subtypes in the only valid type
continue;
}
@@ -1069,7 +1334,8 @@ function elgg_get_entity_type_subtype_where_sql($table, $types, $subtypes, $pair
if ($paired_subtype_ids_str = implode(',', $paired_subtype_ids)) {
- $wheres[] = "({$table}.type = '$paired_type' AND {$table}.subtype IN ($paired_subtype_ids_str))";
+ $wheres[] = "({$table}.type = '$paired_type'"
+ . " AND {$table}.subtype IN ($paired_subtype_ids_str))";
}
} else {
$wheres[] = "({$table}.type = '$paired_type')";
@@ -1089,77 +1355,44 @@ function elgg_get_entity_type_subtype_where_sql($table, $types, $subtypes, $pair
/**
* Returns SQL where clause for owner and containers.
*
- * @todo Probably DRY up once things are settled.
- * @param string $table entity table prefix as defined in SELECT ... FROM prefix_entities $table
- * @param NULL|array $owner_guids
- * @return FALSE|str
- * @since 1.7.0
+ * @param string $column Column name the guids should be checked against. Usually
+ * best to provide in table.column format.
+ * @param NULL|array $guids Array of GUIDs.
+ *
+ * @return false|string
+ * @since 1.8.0
* @access private
*/
-function elgg_get_entity_owner_where_sql($table, $owner_guids) {
+function elgg_get_guid_based_where_sql($column, $guids) {
// short circuit if nothing requested
- // 0 is a valid owner_guid.
- if (!$owner_guids && $owner_guids !== 0) {
+ // 0 is a valid guid
+ if (!$guids && $guids !== 0) {
return '';
}
// normalize and sanitise owners
- if (!is_array($owner_guids)) {
- $owner_guids = array($owner_guids);
+ if (!is_array($guids)) {
+ $guids = array($guids);
}
- $owner_guids_sanitised = array();
- foreach ($owner_guids as $owner_guid) {
- if (($owner_guid != sanitise_int($owner_guid))) {
- return FALSE;
- }
- $owner_guids_sanitised[] = $owner_guid;
- }
-
- $where = '';
-
- // implode(',', 0) returns 0.
- if (($owner_str = implode(',', $owner_guids_sanitised)) && ($owner_str !== FALSE) && ($owner_str !== '')) {
- $where = "({$table}.owner_guid IN ($owner_str))";
- }
+ $guids_sanitized = array();
+ foreach ($guids as $guid) {
+ if ($guid !== ELGG_ENTITIES_NO_VALUE) {
+ $guid = sanitise_int($guid);
- return $where;
-}
-
-/**
- * Returns SQL where clause for containers.
- *
- * @param string $table entity table prefix as defined in SELECT ... FROM prefix_entities $table
- * @param NULL|array $container_guids
- * @return FALSE|string
- * @since 1.7.0
- * @access private
- */
-function elgg_get_entity_container_where_sql($table, $container_guids) {
- // short circuit if nothing is requested.
- // 0 is a valid container_guid.
- if (!$container_guids && $container_guids !== 0) {
- return '';
- }
-
- // normalize and sanitise containers
- if (!is_array($container_guids)) {
- $container_guids = array($container_guids);
- }
-
- $container_guids_sanitised = array();
- foreach ($container_guids as $container_guid) {
- if (($container_guid != sanitise_int($container_guid))) {
- return FALSE;
+ if (!$guid) {
+ return false;
+ }
}
- $container_guids_sanitised[] = $container_guid;
+ $guids_sanitized[] = $guid;
}
$where = '';
+ $guid_str = implode(',', $guids_sanitized);
// implode(',', 0) returns 0.
- if (FALSE !== $container_str = implode(',', $container_guids_sanitised)) {
- $where = "({$table}.container_guid IN ($container_str))";
+ if ($guid_str !== FALSE && $guid_str !== '') {
+ $where = "($column IN ($guid_str))";
}
return $where;
@@ -1168,17 +1401,19 @@ function elgg_get_entity_container_where_sql($table, $container_guids) {
/**
* Returns SQL where clause for entity time limits.
*
- * @param string $table entity table prefix as defined in SELECT ... FROM prefix_entities $table
- * @param NULL|int $time_created_upper
- * @param NULL|int $time_created_lower
- * @param NULL|int $time_updated_upper
- * @param NULL|int $time_updated_lower
- * @return FALSE|str FALSE on fail, string on success.
+ * @param string $table Entity table prefix as defined in
+ * SELECT...FROM entities $table
+ * @param NULL|int $time_created_upper Time created upper limit
+ * @param NULL|int $time_created_lower Time created lower limit
+ * @param NULL|int $time_updated_upper Time updated upper limit
+ * @param NULL|int $time_updated_lower Time updated lower limit
+ *
+ * @return FALSE|string FALSE on fail, string on success.
* @since 1.7.0
* @access private
*/
-function elgg_get_entity_time_where_sql($table, $time_created_upper = NULL, $time_created_lower = NULL,
- $time_updated_upper = NULL, $time_updated_lower = NULL) {
+function elgg_get_entity_time_where_sql($table, $time_created_upper = NULL,
+$time_created_lower = NULL, $time_updated_upper = NULL, $time_updated_lower = NULL) {
$wheres = array();
@@ -1208,40 +1443,6 @@ function elgg_get_entity_time_where_sql($table, $time_created_upper = NULL, $tim
}
/**
- * Returns SQL where clause for site entities
- *
- * @param string $table entity table prefix as defined in SELECT ... FROM prefix_entities $table
- * @param NULL|array $site_guids
- * @return FALSE|string
- * @since 1.7.0
- * @access private
- */
-function elgg_get_entity_site_where_sql($table, $site_guids) {
- // short circuit if nothing requested
- if (!$site_guids) {
- return '';
- }
-
- if (!is_array($site_guids)) {
- $site_guids = array($site_guids);
- }
-
- $site_guids_sanitised = array();
- foreach ($site_guids as $site_guid) {
- if (!$site_guid || ($site_guid != sanitise_int($site_guid))) {
- return FALSE;
- }
- $site_guids_sanitised[] = $site_guid;
- }
-
- if ($site_guids_str = implode(',', $site_guids_sanitised)) {
- return "({$table}.site_guid IN ($site_guids_str))";
- }
-
- return '';
-}
-
-/**
* Returns a string of parsed entities.
*
* Displays list of entities with formatting specified
@@ -1249,104 +1450,55 @@ function elgg_get_entity_site_where_sql($table, $site_guids) {
*
* @tip Pagination is handled automatically.
*
- * @param array $options Any elgg_get_entity() options plus:
+ * @internal This also provides the views for elgg_view_annotation().
*
- * full_view => BOOL Display full view entities
- *
- * view_type_toggle => BOOL Display gallery / list switch
+ * @param array $options Any options from $getter options plus:
+ * full_view => BOOL Display full view entities
+ * list_type => STR 'list' or 'gallery'
+ * list_type_toggle => BOOL Display gallery / list switch
+ * pagination => BOOL Display pagination links
*
- * pagination => BOOL Display pagination links
+ * @param mixed $getter The entity getter function to use to fetch the entities
+ * @param mixed $viewer The function to use to view the entity list.
*
- * @return str
- * @since 1.7.0
- * @see elgg_view_entity_list()
+ * @return string
+ * @since 1.7
* @see elgg_get_entities()
+ * @see elgg_view_entity_list()
* @link http://docs.elgg.org/Entities/Output
*/
-function elgg_list_entities($options) {
+function elgg_list_entities(array $options = array(), $getter = 'elgg_get_entities',
+ $viewer = 'elgg_view_entity_list') {
+
+ global $autofeed;
+ $autofeed = true;
+
+ $offset_key = isset($options['offset_key']) ? $options['offset_key'] : 'offset';
+
$defaults = array(
- 'offset' => (int) max(get_input('offset', 0), 0),
+ 'offset' => (int) max(get_input($offset_key, 0), 0),
'limit' => (int) max(get_input('limit', 10), 0),
'full_view' => TRUE,
- 'view_type_toggle' => FALSE,
- 'pagination' => TRUE
+ 'list_type_toggle' => FALSE,
+ 'pagination' => TRUE,
);
- $options = array_merge($defaults, $options);
- $count = elgg_get_entities(array_merge(array('count' => TRUE), $options));
- $entities = elgg_get_entities($options);
-
- return elgg_view_entity_list($entities, $count, $options['offset'],
- $options['limit'], $options['full_view'], $options['view_type_toggle'], $options['pagination']);
-}
-
-/**
- * @deprecated 1.7. Use elgg_list_entities().
- * @param $type
- * @param $subtype
- * @param $owner_guid
- * @param $limit
- * @param $fullview
- * @param $viewtypetoggle
- * @param $pagination
- * @return unknown_type
- */
-function list_entities($type= "", $subtype = "", $owner_guid = 0, $limit = 10, $fullview = true, $viewtypetoggle = false, $pagination = true) {
- elgg_deprecated_notice('list_entities() was deprecated by elgg_list_entities()!', 1.7);
-
- $options = array();
-
- // rewrite owner_guid to container_guid to emulate old functionality
- if ($owner_guid) {
- $options['container_guids'] = $owner_guid;
- }
-
- if ($type) {
- $options['types'] = $type;
- }
-
- if ($subtype) {
- $options['subtypes'] = $subtype;
- }
+ $options = array_merge($defaults, $options);
- if ($limit) {
- $options['limit'] = $limit;
+ //backwards compatibility
+ if (isset($options['view_type_toggle'])) {
+ $options['list_type_toggle'] = $options['view_type_toggle'];
}
- if ($offset = sanitise_int(get_input('offset', null))) {
- $options['offset'] = $offset;
- }
+ $options['count'] = TRUE;
+ $count = $getter($options);
- $options['full_view'] = $fullview;
- $options['view_type_toggle'] = $viewtypetoggle;
- $options['pagination'] = $pagination;
+ $options['count'] = FALSE;
+ $entities = $getter($options);
- return elgg_list_entities($options);
-}
+ $options['count'] = $count;
-/**
- * Lists entities that belong to a group.
- *
- * @warning This function is largely redundant. The preferred
- * method of listing group entities is by setting the container
- * guid option in {@link elgg_list_entities()}.
- *
- * @param string $subtype The arbitrary subtype of the entity
- * @param int $owner_guid The GUID of the owning user
- * @param int $container_guid The GUID of the containing group
- * @param int $limit The number of entities to display per page (default: 10)
- * @param true|false $fullview Whether or not to display the full view (default: true)
- * @param true|false $viewtypetoggle Whether or not to allow gallery view (default: true)
- * @param true|false $pagination Whether to display pagination (default: true)
- * @return string List of parsed entities
- * @see elgg_list_entities()
- */
-function list_entities_groups($subtype = "", $owner_guid = 0, $container_guid = 0, $limit = 10, $fullview = true, $viewtypetoggle = true, $pagination = true) {
- $offset = (int) get_input('offset');
- $count = get_objects_in_group($container_guid, $subtype, $owner_guid, 0, "", $limit, $offset, true);
- $entities = get_objects_in_group($container_guid, $subtype, $owner_guid, 0, "", $limit, $offset);
-
- return elgg_view_entity_list($entities, $count, $offset, $limit, $fullview, $viewtypetoggle, $pagination);
+ return $viewer($entities, $options);
}
/**
@@ -1354,16 +1506,21 @@ function list_entities_groups($subtype = "", $owner_guid = 0, $container_guid =
*
* @tip Use this to generate a list of archives by month for when entities were added or updated.
*
+ * @todo document how to pass in array for $subtype
+ *
* @warning Months are returned in the form YYYYMM.
*
- * @param string $type The type of entity
- * @param string $subtype The subtype of entity
- * @param int $container_guid The container GUID that the entinties belong to
- * @param int $site_guid The site GUID
- * @param str order_by SQL order by clause
+ * @param string $type The type of entity
+ * @param string $subtype The subtype of entity
+ * @param int $container_guid The container GUID that the entities belong to
+ * @param int $site_guid The site GUID
+ * @param string $order_by Order_by SQL order by clause
+ *
* @return array|false Either an array months as YYYYMM, or false on failure
*/
-function get_entity_dates($type = '', $subtype = '', $container_guid = 0, $site_guid = 0, $order_by = 'time_created') {
+function get_entity_dates($type = '', $subtype = '', $container_guid = 0, $site_guid = 0,
+$order_by = 'time_created') {
+
global $CONFIG;
$site_guid = (int) $site_guid;
@@ -1380,16 +1537,19 @@ function get_entity_dates($type = '', $subtype = '', $container_guid = 0, $site_
if (is_array($subtype)) {
$tempwhere = "";
if (sizeof($subtype)) {
- foreach($subtype as $typekey => $subtypearray) {
- foreach($subtypearray as $subtypeval) {
+ foreach ($subtype as $typekey => $subtypearray) {
+ foreach ($subtypearray as $subtypeval) {
$typekey = sanitise_string($typekey);
if (!empty($subtypeval)) {
- if (!$subtypeval = (int) get_subtype_id($typekey, $subtypeval))
+ if (!$subtypeval = (int) get_subtype_id($typekey, $subtypeval)) {
return false;
+ }
} else {
$subtypeval = 0;
}
- if (!empty($tempwhere)) $tempwhere .= " or ";
+ if (!empty($tempwhere)) {
+ $tempwhere .= " or ";
+ }
$tempwhere .= "(type = '{$typekey}' and subtype = {$subtypeval})";
}
}
@@ -1409,10 +1569,10 @@ function get_entity_dates($type = '', $subtype = '', $container_guid = 0, $site_
if ($container_guid !== 0) {
if (is_array($container_guid)) {
- foreach($container_guid as $key => $val) {
+ foreach ($container_guid as $key => $val) {
$container_guid[$key] = (int) $val;
}
- $where[] = "container_guid in (" . implode(",",$container_guid) . ")";
+ $where[] = "container_guid in (" . implode(",", $container_guid) . ")";
} else {
$container_guid = (int) $container_guid;
$where[] = "container_guid = {$container_guid}";
@@ -1435,7 +1595,7 @@ function get_entity_dates($type = '', $subtype = '', $container_guid = 0, $site_
$sql .= "1=1 ORDER BY $order_by";
if ($result = get_data($sql)) {
$endresult = array();
- foreach($result as $res) {
+ foreach ($result as $res) {
$endresult[] = $res->yearmonth;
}
return $endresult;
@@ -1456,13 +1616,14 @@ function get_entity_dates($type = '', $subtype = '', $container_guid = 0, $site_
*
* @note Use ElggEntity::disable() instead.
*
- * @param int $guid The guid
- * @param string $reason Optional reason
- * @param bool $recursive Recursively disable all entities owned or contained by $guid?
+ * @param int $guid The guid
+ * @param string $reason Optional reason
+ * @param bool $recursive Recursively disable all entities owned or contained by $guid?
+ *
* @return bool
- * @access private
* @see access_show_hidden_entities()
* @link http://docs.elgg.org/Entities
+ * @access private
*/
function disable_entity($guid, $reason = "", $recursive = true) {
global $CONFIG;
@@ -1471,36 +1632,41 @@ function disable_entity($guid, $reason = "", $recursive = true) {
$reason = sanitise_string($reason);
if ($entity = get_entity($guid)) {
- if (trigger_elgg_event('disable',$entity->type,$entity)) {
+ if (elgg_trigger_event('disable', $entity->type, $entity)) {
if ($entity->canEdit()) {
if ($reason) {
create_metadata($guid, 'disable_reason', $reason, '', 0, ACCESS_PUBLIC);
}
if ($recursive) {
- // Temporary token overriding access controls
- // @todo Do this better.
- static $__RECURSIVE_DELETE_TOKEN;
- // Make it slightly harder to guess
- $__RECURSIVE_DELETE_TOKEN = md5(get_loggedin_userid());
-
- $sub_entities = get_data("SELECT * from {$CONFIG->dbprefix}entities
- WHERE container_guid=$guid
- or owner_guid=$guid
- or site_guid=$guid", 'entity_row_to_elggstar');
+ $hidden = access_get_show_hidden_status();
+ access_show_hidden_entities(true);
+ $ia = elgg_set_ignore_access(true);
+
+ $sub_entities = get_data("SELECT * FROM {$CONFIG->dbprefix}entities
+ WHERE (
+ container_guid = $guid
+ OR owner_guid = $guid
+ OR site_guid = $guid
+ ) AND enabled='yes'", 'entity_row_to_elggstar');
if ($sub_entities) {
foreach ($sub_entities as $e) {
+ add_entity_relationship($e->guid, 'disabled_with', $entity->guid);
$e->disable($reason);
}
}
-
- $__RECURSIVE_DELETE_TOKEN = null;
+ access_show_hidden_entities($hidden);
+ elgg_set_ignore_access($ia);
}
+ $entity->disableMetadata();
+ $entity->disableAnnotations();
+ _elgg_invalidate_cache_for_entity($guid);
+
$res = update_data("UPDATE {$CONFIG->dbprefix}entities
- set enabled='no'
- where guid={$guid}");
+ SET enabled = 'no'
+ WHERE guid = $guid");
return $res;
}
@@ -1512,39 +1678,55 @@ function disable_entity($guid, $reason = "", $recursive = true) {
/**
* Enable an entity.
*
- * @warning In order to enable an entity using ElggEntity::enable(),
- * you must first use {@link access_show_hidden_entities()}.
+ * @warning In order to enable an entity, you must first use
+ * {@link access_show_hidden_entities()}.
+ *
+ * @param int $guid GUID of entity to enable
+ * @param bool $recursive Recursively enable all entities disabled with the entity?
*
- * @param int $guid
* @return bool
*/
-function enable_entity($guid) {
+function enable_entity($guid, $recursive = true) {
global $CONFIG;
$guid = (int)$guid;
// Override access only visible entities
- $access_status = access_get_show_hidden_status();
+ $old_access_status = access_get_show_hidden_status();
access_show_hidden_entities(true);
+ $result = false;
if ($entity = get_entity($guid)) {
- if (trigger_elgg_event('enable',$entity->type,$entity)) {
+ if (elgg_trigger_event('enable', $entity->type, $entity)) {
if ($entity->canEdit()) {
- access_show_hidden_entities($access_status);
-
$result = update_data("UPDATE {$CONFIG->dbprefix}entities
- set enabled='yes'
- where guid={$guid}");
- $entity->clearMetaData('disable_reason');
+ SET enabled = 'yes'
+ WHERE guid = $guid");
- return $result;
+ $entity->deleteMetadata('disable_reason');
+ $entity->enableMetadata();
+ $entity->enableAnnotations();
+
+ if ($recursive) {
+ $disabled_with_it = elgg_get_entities_from_relationship(array(
+ 'relationship' => 'disabled_with',
+ 'relationship_guid' => $entity->guid,
+ 'inverse_relationship' => true,
+ 'limit' => 0,
+ ));
+
+ foreach ($disabled_with_it as $e) {
+ $e->enable();
+ remove_entity_relationship($e->guid, 'disabled_with', $entity->guid);
+ }
+ }
}
}
}
- access_show_hidden_entities($access_status);
- return false;
+ access_show_hidden_entities($old_access_status);
+ return $result;
}
/**
@@ -1561,8 +1743,11 @@ function enable_entity($guid) {
* the entity. That means that if the container_guid = $guid, the item will be deleted
* regardless of who owns it.
*
- * @param int $guid
- * @param bool $recursive If true (default) then all entities which are owned or contained by $guid will also be deleted.
+ * @param int $guid The guid of the entity to delete
+ * @param bool $recursive If true (default) then all entities which are
+ * owned or contained by $guid will also be deleted.
+ *
+ * @return bool
* @access private
*/
function delete_entity($guid, $recursive = true) {
@@ -1570,12 +1755,21 @@ function delete_entity($guid, $recursive = true) {
$guid = (int)$guid;
if ($entity = get_entity($guid)) {
- if (trigger_elgg_event('delete', $entity->type, $entity)) {
+ if (elgg_trigger_event('delete', $entity->type, $entity)) {
if ($entity->canEdit()) {
// delete cache
if (isset($ENTITY_CACHE[$guid])) {
- invalidate_cache_for_entity($guid);
+ _elgg_invalidate_cache_for_entity($guid);
+ }
+
+ // If memcache is available then delete this entry from the cache
+ static $newentity_cache;
+ if ((!$newentity_cache) && (is_memcache_available())) {
+ $newentity_cache = new ElggMemcache('new_entity_cache');
+ }
+ if ($newentity_cache) {
+ $newentity_cache->delete($guid);
}
// Delete contained owned and otherwise releated objects (depth first)
@@ -1584,28 +1778,53 @@ function delete_entity($guid, $recursive = true) {
// @todo Do this better.
static $__RECURSIVE_DELETE_TOKEN;
// Make it slightly harder to guess
- $__RECURSIVE_DELETE_TOKEN = md5(get_loggedin_userid());
-
- $sub_entities = get_data("SELECT * from {$CONFIG->dbprefix}entities
- WHERE container_guid=$guid
- or owner_guid=$guid
- or site_guid=$guid", 'entity_row_to_elggstar');
- if ($sub_entities) {
- foreach ($sub_entities as $e) {
- $e->delete();
- }
+ $__RECURSIVE_DELETE_TOKEN = md5(elgg_get_logged_in_user_guid());
+
+ $entity_disable_override = access_get_show_hidden_status();
+ access_show_hidden_entities(true);
+ $ia = elgg_set_ignore_access(true);
+
+ // @todo there was logic in the original code that ignored
+ // entities with owner or container guids of themselves.
+ // this should probably be prevented in ElggEntity instead of checked for here
+ $options = array(
+ 'wheres' => array(
+ "((container_guid = $guid OR owner_guid = $guid OR site_guid = $guid)"
+ . " AND guid != $guid)"
+ ),
+ 'limit' => 0
+ );
+
+ $batch = new ElggBatch('elgg_get_entities', $options);
+ $batch->setIncrementOffset(false);
+
+ foreach ($batch as $e) {
+ $e->delete(true);
}
+ access_show_hidden_entities($entity_disable_override);
$__RECURSIVE_DELETE_TOKEN = null;
+ elgg_set_ignore_access($ia);
}
+ $entity_disable_override = access_get_show_hidden_status();
+ access_show_hidden_entities(true);
+ $ia = elgg_set_ignore_access(true);
+
// Now delete the entity itself
- $entity->clearMetadata();
- $entity->clearAnnotations();
- $entity->clearRelationships();
- remove_from_river_by_subject($guid);
- remove_from_river_by_object($guid);
+ $entity->deleteMetadata();
+ $entity->deleteOwnedMetadata();
+ $entity->deleteAnnotations();
+ $entity->deleteOwnedAnnotations();
+ $entity->deleteRelationships();
+
+ access_show_hidden_entities($entity_disable_override);
+ elgg_set_ignore_access($ia);
+
+ elgg_delete_river(array('subject_guid' => $guid));
+ elgg_delete_river(array('object_guid' => $guid));
remove_all_private_settings($guid);
+
$res = delete_data("DELETE from {$CONFIG->dbprefix}entities where guid={$guid}");
if ($res) {
$sub_table = "";
@@ -1631,7 +1850,7 @@ function delete_entity($guid, $recursive = true) {
}
}
- return $res;
+ return (bool)$res;
}
}
}
@@ -1640,28 +1859,14 @@ function delete_entity($guid, $recursive = true) {
}
/**
- * Delete multiple entities that match a given query.
- * This function iterates through and calls delete_entity on each one, this is somewhat inefficient but lets
- * the 'delete' even be called for each entity.
- *
- * @deprecated 1.7. This is a dangerous function as it defaults to deleting everything.
- * @param string $type The type of entity (eg "user", "object" etc)
- * @param string $subtype The arbitrary subtype of the entity
- * @param int $owner_guid The GUID of the owning user
- */
-function delete_entities($type = "", $subtype = "", $owner_guid = 0) {
- elgg_deprecated_notice('delete_entities() was deprecated because no one should use it.', 1.7);
- return false;
-}
-
-/**
* Exports attributes generated on the fly (volatile) about an entity.
*
- * @param unknown_type $hook
- * @param unknown_type $entity_type
- * @param unknown_type $returnvalue
- * @param unknown_type $params The parameters, passed 'guid' and 'varname'
- * @return null
+ * @param string $hook volatile
+ * @param string $entity_type metadata
+ * @param string $returnvalue Return value from previous hook
+ * @param array $params The parameters, passed 'guid' and 'varname'
+ *
+ * @return ElggMetadata|null
* @elgg_plugin_hook_handler volatile metadata
* @todo investigate more.
* @access private
@@ -1698,8 +1903,16 @@ function volatile_data_export_plugin_hook($hook, $entity_type, $returnvalue, $pa
*
* @warning Only exports fields in the entity and entity type tables.
*
+ * @param string $hook export
+ * @param string $entity_type all
+ * @param mixed $returnvalue Previous hook return value
+ * @param array $params Parameters
+ *
* @elgg_event_handler export all
- * @todo document
+ * @return mixed
+ * @access private
+ *
+ * @throws InvalidParameterException|InvalidClassException
*/
function export_entity_plugin_hook($hook, $entity_type, $returnvalue, $params) {
// Sanity check values
@@ -1716,7 +1929,8 @@ function export_entity_plugin_hook($hook, $entity_type, $returnvalue, $params) {
// Get the entity
$entity = get_entity($guid);
if (!($entity instanceof ElggEntity)) {
- throw new InvalidClassException(sprintf(elgg_echo('InvalidClassException:NotValidElggStar'), $guid, get_class()));
+ $msg = elgg_echo('InvalidClassException:NotValidElggStar', array($guid, get_class()));
+ throw new InvalidClassException($msg);
}
$export = $entity->export();
@@ -1733,11 +1947,16 @@ function export_entity_plugin_hook($hook, $entity_type, $returnvalue, $params) {
}
/**
- * Utility function used by import_entity_plugin_hook() to process an ODDEntity into an unsaved ElggEntity.
+ * Utility function used by import_entity_plugin_hook() to
+ * process an ODDEntity into an unsaved ElggEntity.
*
* @param ODDEntity $element The OpenDD element
+ *
* @return ElggEntity the unsaved entity which should be populated by items.
* @todo Remove this.
+ * @access private
+ *
+ * @throws ClassException|InstallationException|ImportException
*/
function oddentity_to_elggentity(ODDEntity $element) {
$class = $element->getAttribute('class');
@@ -1749,18 +1968,18 @@ function oddentity_to_elggentity(ODDEntity $element) {
if (!$tmp) {
// Construct new class with owner from session
$classname = get_subtype_class($class, $subclass);
- if ($classname!="") {
+ if ($classname) {
if (class_exists($classname)) {
$tmp = new $classname();
if (!($tmp instanceof ElggEntity)) {
- throw new ClassException(sprintf(elgg_echo('ClassException:ClassnameNotClass', $classname, get_class())));
+ $msg = elgg_echo('ClassException:ClassnameNotClass', array($classname, get_class()));
+ throw new ClassException($msg);
}
+ } else {
+ error_log(elgg_echo('ClassNotFoundException:MissingClass', array($classname)));
}
- else
- error_log(sprintf(elgg_echo('ClassNotFoundException:MissingClass'), $classname));
- }
- else {
+ } else {
switch ($class) {
case 'object' :
$tmp = new ElggObject($row);
@@ -1775,14 +1994,16 @@ function oddentity_to_elggentity(ODDEntity $element) {
$tmp = new ElggSite($row);
break;
default:
- throw new InstallationException(sprintf(elgg_echo('InstallationException:TypeNotSupported'), $class));
+ $msg = elgg_echo('InstallationException:TypeNotSupported', array($class));
+ throw new InstallationException($msg);
}
}
}
if ($tmp) {
if (!$tmp->import($element)) {
- throw new ImportException(sprintf(elgg_echo('ImportException:ImportFailed'), $element->getAttribute('uuid')));
+ $msg = elgg_echo('ImportException:ImportFailed', array($element->getAttribute('uuid')));
+ throw new ImportException($msg);
}
return $tmp;
@@ -1794,16 +2015,26 @@ function oddentity_to_elggentity(ODDEntity $element) {
/**
* Import an entity.
*
- * This function checks the passed XML doc (as array) to see if it is a user, if so it constructs a new
- * elgg user and returns "true" to inform the importer that it's been handled.
+ * This function checks the passed XML doc (as array) to see if it is
+ * a user, if so it constructs a new elgg user and returns "true"
+ * to inform the importer that it's been handled.
*
+ * @param string $hook import
+ * @param string $entity_type all
+ * @param mixed $returnvalue Value from previous hook
+ * @param mixed $params Array of params
+ *
+ * @return mixed
* @elgg_plugin_hook_handler import all
* @todo document
+ * @access private
+ *
+ * @throws ImportException
*/
function import_entity_plugin_hook($hook, $entity_type, $returnvalue, $params) {
$element = $params['element'];
- $tmp = NULL;
+ $tmp = null;
if ($element instanceof ODDEntity) {
$tmp = oddentity_to_elggentity($element);
@@ -1811,7 +2042,8 @@ function import_entity_plugin_hook($hook, $entity_type, $returnvalue, $params) {
if ($tmp) {
// Make sure its saved
if (!$tmp->save()) {
- throw new ImportException(sprintf(elgg_echo('ImportException:ProblemSaving'), $element->getAttribute('uuid')));
+ $msg = elgg_echo('ImportException:ProblemSaving', array($element->getAttribute('uuid')));
+ throw new ImportException($msg);
}
// Belts and braces
@@ -1838,25 +2070,24 @@ function import_entity_plugin_hook($hook, $entity_type, $returnvalue, $params) {
* @tip Use ElggEntity::canEdit() instead.
*
* @param int $entity_guid The GUID of the entity
- * @param int $user_guid The GUID of the user
+ * @param int $user_guid The GUID of the user
+ *
* @return bool
* @link http://docs.elgg.org/Entities/AccessControl
*/
function can_edit_entity($entity_guid, $user_guid = 0) {
- global $CONFIG;
-
$user_guid = (int)$user_guid;
$user = get_entity($user_guid);
if (!$user) {
- $user = get_loggedin_user();
+ $user = elgg_get_logged_in_user_entity();
}
+ $return = false;
if ($entity = get_entity($entity_guid)) {
- $return = false;
// Test user if possible - should default to false unless a plugin hook says otherwise
if ($user) {
- if ($entity->getOwner() == $user->getGUID()) {
+ if ($entity->getOwnerGUID() == $user->getGUID()) {
$return = true;
}
if ($entity->container_guid == $user->getGUID()) {
@@ -1871,13 +2102,10 @@ function can_edit_entity($entity_guid, $user_guid = 0) {
}
}
}
+ }
- return trigger_plugin_hook('permissions_check', $entity->type,
+ return elgg_trigger_plugin_hook('permissions_check', $entity->type,
array('entity' => $entity, 'user' => $user), $return);
-
- } else {
- return false;
- }
}
/**
@@ -1888,26 +2116,33 @@ function can_edit_entity($entity_guid, $user_guid = 0) {
*
* @warning If a $user_guid isn't specified, the currently logged in user is used.
*
- * @param int $entity_guid The GUID of the entity
- * @param int $user_guid The GUID of the user
- * @param ElggMetadata $metadata The metadata to specifically check (if any; default null)
+ * @param int $entity_guid The GUID of the entity
+ * @param int $user_guid The GUID of the user
+ * @param ElggMetadata $metadata The metadata to specifically check (if any; default null)
+ *
* @return bool
- * @see register_plugin_hook()
+ * @see elgg_register_plugin_hook_handler()
*/
function can_edit_entity_metadata($entity_guid, $user_guid = 0, $metadata = null) {
if ($entity = get_entity($entity_guid)) {
$return = null;
- if ($metadata->owner_guid == 0) {
+ if ($metadata && ($metadata->owner_guid == 0)) {
$return = true;
}
if (is_null($return)) {
$return = can_edit_entity($entity_guid, $user_guid);
}
- $user = get_entity($user_guid);
- $return = trigger_plugin_hook('permissions_check:metadata',$entity->type,array('entity' => $entity, 'user' => $user, 'metadata' => $metadata),$return);
+ if ($user_guid) {
+ $user = get_entity($user_guid);
+ } else {
+ $user = elgg_get_logged_in_user_entity();
+ }
+
+ $params = array('entity' => $entity, 'user' => $user, 'metadata' => $metadata);
+ $return = elgg_trigger_plugin_hook('permissions_check:metadata', $entity->type, $params, $return);
return $return;
} else {
return false;
@@ -1915,82 +2150,12 @@ function can_edit_entity_metadata($entity_guid, $user_guid = 0, $metadata = null
}
/**
- * Return the icon URL for an entity.
- *
- * @tip Can be overridden by registering a plugin hook for entity:icon:url, $entity_type.
- *
- * @internal This is passed an entity rather than a guid to handle non-created entities.
- *
- * @param ElggEntity $entity The entity
- * @param string $size
- * @return string URL to the entity icon.
- */
-function get_entity_icon_url(ElggEntity $entity, $size = 'medium') {
- global $CONFIG;
-
- $size = sanitise_string($size);
- switch (strtolower($size)) {
- case 'master':
- $size = 'master';
- break;
-
- case 'large' :
- $size = 'large';
- break;
-
- case 'topbar' :
- $size = 'topbar';
- break;
-
- case 'tiny' :
- $size = 'tiny';
- break;
-
- case 'small' :
- $size = 'small';
- break;
-
- case 'medium' :
- default:
- $size = 'medium';
- }
-
- $url = false;
-
- $viewtype = elgg_get_viewtype();
-
- // Step one, see if anyone knows how to render this in the current view
- $url = trigger_plugin_hook('entity:icon:url', $entity->getType(), array('entity' => $entity, 'viewtype' => $viewtype, 'size' => $size), $url);
-
- // Fail, so use default
- if (!$url) {
- $type = $entity->getType();
- $subtype = $entity->getSubtype();
-
- if (!empty($subtype)) {
- $overrideurl = elgg_view("icon/{$type}/{$subtype}/{$size}",array('entity' => $entity));
- if (!empty($overrideurl)) {
- return $overrideurl;
- }
- }
-
- $overrideurl = elgg_view("icon/{$type}/default/{$size}",array('entity' => $entity));
- if (!empty($overrideurl)) {
- return $overrideurl;
- }
-
- $url = $CONFIG->url . "_graphics/icons/default/$size.png";
- }
-
- return $url;
-}
-
-/**
* Returns the URL for an entity.
*
* @tip Can be overridden with {@link register_entity_url_handler()}.
*
* @param int $entity_guid The GUID of the entity
+ *
* @return string The URL of the entity
* @see register_entity_url_handler()
*/
@@ -2001,27 +2166,27 @@ function get_entity_url($entity_guid) {
$url = "";
if (isset($CONFIG->entity_url_handler[$entity->getType()][$entity->getSubType()])) {
- $function = $CONFIG->entity_url_handler[$entity->getType()][$entity->getSubType()];
+ $function = $CONFIG->entity_url_handler[$entity->getType()][$entity->getSubType()];
if (is_callable($function)) {
- $url = $function($entity);
+ $url = call_user_func($function, $entity);
}
} elseif (isset($CONFIG->entity_url_handler[$entity->getType()]['all'])) {
- $function = $CONFIG->entity_url_handler[$entity->getType()]['all'];
+ $function = $CONFIG->entity_url_handler[$entity->getType()]['all'];
if (is_callable($function)) {
- $url = $function($entity);
+ $url = call_user_func($function, $entity);
}
} elseif (isset($CONFIG->entity_url_handler['all']['all'])) {
- $function = $CONFIG->entity_url_handler['all']['all'];
+ $function = $CONFIG->entity_url_handler['all']['all'];
if (is_callable($function)) {
- $url = $function($entity);
+ $url = call_user_func($function, $entity);
}
}
if ($url == "") {
- $url = $CONFIG->url . "pg/view/" . $entity_guid;
+ $url = "view/" . $entity_guid;
}
- return $url;
+ return elgg_normalize_url($url);
}
return false;
@@ -2030,17 +2195,19 @@ function get_entity_url($entity_guid) {
/**
* Sets the URL handler for a particular entity type and subtype
*
- * @param string $function_name The function to register
- * @param string $entity_type The entity type
+ * @param string $entity_type The entity type
* @param string $entity_subtype The entity subtype
- * @return true|false Depending on success
+ * @param string $function_name The function to register
+ *
+ * @return bool Depending on success
* @see get_entity_url()
* @see ElggEntity::getURL()
+ * @since 1.8.0
*/
-function register_entity_url_handler($function_name, $entity_type = "all", $entity_subtype = "all") {
+function elgg_register_entity_url_handler($entity_type, $entity_subtype, $function_name) {
global $CONFIG;
- if (!is_callable($function_name)) {
+ if (!is_callable($function_name, true)) {
return false;
}
@@ -2058,95 +2225,101 @@ function register_entity_url_handler($function_name, $entity_type = "all", $enti
}
/**
- * Default Icon handler for entities.
+ * Registers an entity type and subtype as a public-facing entity that should
+ * be shown in search and by {@link elgg_list_registered_entities()}.
+ *
+ * @warning Entities that aren't registered here will not show up in search.
*
- * @tip This will attempt to find a default entity for the current view and return a url.
- * This is registered at a high priority so that other handlers will pick it up first.
+ * @tip Add a language string item:type:subtype to make sure the items are display properly.
+ *
+ * @param string $type The type of entity (object, site, user, group)
+ * @param string $subtype The subtype to register (may be blank)
*
- * @param unknown_type $hook
- * @param unknown_type $entity_type
- * @param unknown_type $returnvalue
- * @param unknown_type $params
- * @elgg_plugin_hook_handler entity:icon:url all
+ * @return bool Depending on success
+ * @see get_registered_entity_types()
+ * @link http://docs.elgg.org/Search
+ * @link http://docs.elgg.org/Tutorials/Search
*/
-function default_entity_icon_hook($hook, $entity_type, $returnvalue, $params) {
+function elgg_register_entity_type($type, $subtype = null) {
global $CONFIG;
- if ((!$returnvalue) && ($hook == 'entity:icon:url')) {
- $entity = $params['entity'];
- $type = $entity->type;
- $subtype = get_subtype_from_id($entity->subtype);
- $viewtype = $params['viewtype'];
- $size = $params['size'];
-
- $url = "views/$viewtype/graphics/icons/$type/$subtype/$size.png";
+ $type = strtolower($type);
+ if (!in_array($type, $CONFIG->entity_types)) {
+ return FALSE;
+ }
- if (!@file_exists($CONFIG->path . $url)) {
- $url = "views/$viewtype/graphics/icons/$type/default/$size.png";
- }
+ if (!isset($CONFIG->registered_entities)) {
+ $CONFIG->registered_entities = array();
+ }
- if(!@file_exists($CONFIG->path . $url)) {
- $url = "views/$viewtype/graphics/icons/default/$size.png";
- }
+ if (!isset($CONFIG->registered_entities[$type])) {
+ $CONFIG->registered_entities[$type] = array();
+ }
- if (@file_exists($CONFIG->path . $url)) {
- return $CONFIG->url . $url;
- }
+ if ($subtype) {
+ $CONFIG->registered_entities[$type][] = $subtype;
}
+
+ return TRUE;
}
/**
- * Registers an entity type and subtype as a public-facing entity that should
- * be shown in search and by {@link elgg_list_registered_entities()}.
+ * Unregisters an entity type and subtype as a public-facing entity.
*
- * @warning Entities that aren't registered here will not show up in search.
+ * @warning With a blank subtype, it unregisters that entity type including
+ * all subtypes. This must be called after all subtypes have been registered.
*
- * @tip Add a language string item:type:subtype to make sure the items are display properly.
- *
- * @param string $type The type of entity (object, site, user, group)
+ * @param string $type The type of entity (object, site, user, group)
* @param string $subtype The subtype to register (may be blank)
- * @return true|false Depending on success
- * @see get_registered_entity_types()
- * @link http://docs.elgg.org/Search
- * @link http://docs.elgg.org/Tutorials/Search
+ *
+ * @return bool Depending on success
+ * @see elgg_register_entity_type()
*/
-function register_entity_type($type, $subtype) {
+function unregister_entity_type($type, $subtype) {
global $CONFIG;
$type = strtolower($type);
- if (!in_array($type, array('object','site','group','user'))) {
- return false;
+ if (!in_array($type, $CONFIG->entity_types)) {
+ return FALSE;
}
if (!isset($CONFIG->registered_entities)) {
- $CONFIG->registered_entities = array();
+ return FALSE;
}
if (!isset($CONFIG->registered_entities[$type])) {
- $CONFIG->registered_entities[$type] = array();
+ return FALSE;
}
if ($subtype) {
- $CONFIG->registered_entities[$type][] = $subtype;
+ if (in_array($subtype, $CONFIG->registered_entities[$type])) {
+ $key = array_search($subtype, $CONFIG->registered_entities[$type]);
+ unset($CONFIG->registered_entities[$type][$key]);
+ } else {
+ return FALSE;
+ }
+ } else {
+ unset($CONFIG->registered_entities[$type]);
}
- return true;
+ return TRUE;
}
/**
* Returns registered entity types and subtypes
*
* @param string $type The type of entity (object, site, user, group) or blank for all
+ *
* @return array|false Depending on whether entities have been registered
- * @see register_entity_type()
+ * @see elgg_register_entity_type()
*/
-function get_registered_entity_types($type = '') {
+function get_registered_entity_types($type = null) {
global $CONFIG;
if (!isset($CONFIG->registered_entities)) {
return false;
}
- if (!empty($type)) {
+ if ($type) {
$type = strtolower($type);
}
if (!empty($type) && empty($CONFIG->registered_entities[$type])) {
@@ -2161,75 +2334,51 @@ function get_registered_entity_types($type = '') {
}
/**
- * Returns if the entity type and subtype have been registered with {@see register_entity_type()}.
+ * Returns if the entity type and subtype have been registered with {@see elgg_register_entity_type()}.
*
- * @param string $type The type of entity (object, site, user, group)
+ * @param string $type The type of entity (object, site, user, group)
* @param string $subtype The subtype (may be blank)
- * @return true|false Depending on whether or not the type has been registered
+ *
+ * @return bool Depending on whether or not the type has been registered
*/
-function is_registered_entity_type($type, $subtype) {
+function is_registered_entity_type($type, $subtype = null) {
global $CONFIG;
if (!isset($CONFIG->registered_entities)) {
return false;
}
+
$type = strtolower($type);
- if (empty($CONFIG->registered_entities[$type])) {
+
+ // @todo registering a subtype implicitly registers the type.
+ // see #2684
+ if (!isset($CONFIG->registered_entities[$type])) {
return false;
}
- if (in_array($subtype, $CONFIG->registered_entities[$type])) {
- return true;
+
+ if ($subtype && !in_array($subtype, $CONFIG->registered_entities[$type])) {
+ return false;
}
+ return true;
}
/**
* Page handler for generic entities view system
*
* @param array $page Page elements from pain page handler
+ *
+ * @return bool
* @elgg_page_handler view
+ * @access private
*/
function entities_page_handler($page) {
if (isset($page[0])) {
global $CONFIG;
- set_input('guid',$page[0]);
+ set_input('guid', $page[0]);
include($CONFIG->path . "pages/entities/index.php");
+ return true;
}
-}
-
-/**
- * @deprecated 1.7. Use elgg_list_registered_entities().
- * @param $owner_guid
- * @param $limit
- * @param $fullview
- * @param $viewtypetoggle
- * @param $allowedtypes
- * @return unknown_type
- */
-function list_registered_entities($owner_guid = 0, $limit = 10, $fullview = true, $viewtypetoggle = false, $allowedtypes = true) {
- elgg_deprecated_notice('list_registered_entities() was deprecated by elgg_list_registered_entities().', 1.7);
-
- $options = array();
-
- // don't want to send anything if not being used.
- if ($owner_guid) {
- $options['owner_guid'] = $owner_guid;
- }
-
- if ($limit) {
- $options['limit'] = $limit;
- }
-
- if ($allowedtypes) {
- $options['allowed_types'] = $allowedtypes;
- }
-
- // need to send because might be BOOL
- $options['full_view'] = $fullview;
- $options['view_type_toggle'] = $viewtypetoggle;
-
- $options['offset'] = get_input('offset', 0);
-
- return elgg_list_registered_entities($options);
+ return false;
}
/**
@@ -2241,7 +2390,7 @@ function list_registered_entities($owner_guid = 0, $limit = 10, $fullview = true
*
* full_view => BOOL Display full view entities
*
- * view_type_toggle => BOOL Display gallery / list switch
+ * list_type_toggle => BOOL Display gallery / list switch
*
* allowed_types => TRUE|ARRAY True to show all types or an array of valid types.
*
@@ -2250,482 +2399,56 @@ function list_registered_entities($owner_guid = 0, $limit = 10, $fullview = true
* @return string A viewable list of entities
* @since 1.7.0
*/
-function elgg_list_registered_entities($options) {
+function elgg_list_registered_entities(array $options = array()) {
+ global $autofeed;
+ $autofeed = true;
+
$defaults = array(
'full_view' => TRUE,
'allowed_types' => TRUE,
- 'view_type_toggle' => FALSE,
+ 'list_type_toggle' => FALSE,
'pagination' => TRUE,
- 'offset' => 0
+ 'offset' => 0,
+ 'types' => array(),
+ 'type_subtype_pairs' => array()
);
$options = array_merge($defaults, $options);
- $typearray = array();
-
- if ($object_types = get_registered_entity_types()) {
- foreach($object_types as $object_type => $subtype_array) {
- if (in_array($object_type, $options['allowed_types']) || $options['allowed_types'] === TRUE) {
- $typearray[$object_type] = array();
-
- if (is_array($subtype_array) && count($subtype_array)) {
- foreach ($subtype_array as $subtype) {
- $typearray[$object_type][] = $subtype;
- }
- }
- }
- }
- }
-
- $options['type_subtype_pairs'] = $typearray;
-
- $count = elgg_get_entities(array_merge(array('count' => TRUE), $options));
- $entities = elgg_get_entities($options);
- return elgg_view_entity_list($entities, $count, $options['offset'],
- $options['limit'], $options['full_view'], $options['view_type_toggle'], $options['pagination']);
-}
-
-/**
- * Get entities based on their private data.
- *
- * @param string $name The name of the setting
- * @param string $value The value of the setting
- * @param string $type The type of entity (eg "user", "object" etc)
- * @param string $subtype The arbitrary subtype of the entity
- * @param int $owner_guid The GUID of the owning user
- * @param string $order_by The field to order by; by default, time_created desc
- * @param int $limit The number of entities to return; 10 by default
- * @param int $offset The indexing offset, 0 by default
- * @param boolean $count Set to true to get a count rather than the entities themselves (limits and offsets don't apply in this context). Defaults to false.
- * @param int $site_guid The site to get entities for. Leave as 0 (default) for the current site; -1 for all sites.
- * @param int|array $container_guid The container or containers to get entities from (default: all containers).
- * @return array A list of entities.
- * @todo deprecate
- */
-function get_entities_from_private_setting($name = "", $value = "", $type = "", $subtype = "", $owner_guid = 0, $order_by = "", $limit = 10, $offset = 0, $count = false, $site_guid = 0, $container_guid = null) {
- global $CONFIG;
-
- if ($subtype === false || $subtype === null || $subtype === 0) {
- return false;
+ //backwards compatibility
+ if (isset($options['view_type_toggle'])) {
+ $options['list_type_toggle'] = $options['view_type_toggle'];
}
- $name = sanitise_string($name);
- $value = sanitise_string($value);
+ $types = get_registered_entity_types();
- if ($order_by == "") {
- $order_by = "e.time_created desc";
- }
- $order_by = sanitise_string($order_by);
- $limit = (int)$limit;
- $offset = (int)$offset;
- $site_guid = (int) $site_guid;
- if ($site_guid == 0) {
- $site_guid = $CONFIG->site_guid;
- }
-
- $where = array();
-
- if (is_array($type)) {
- $tempwhere = "";
- if (sizeof($type)) {
- foreach($type as $typekey => $subtypearray) {
- foreach($subtypearray as $subtypeval) {
- $typekey = sanitise_string($typekey);
- if (!empty($subtypeval)) {
- if (!$subtypeval = (int) get_subtype_id($typekey, $subtypeval)) {
- return false;
- }
- } else {
- $subtypeval = 0;
- }
- if (!empty($tempwhere)) $tempwhere .= " or ";
- $tempwhere .= "(e.type = '{$typekey}' and e.subtype = {$subtypeval})";
+ foreach ($types as $type => $subtype_array) {
+ if (in_array($type, $options['allowed_types']) || $options['allowed_types'] === TRUE) {
+ // you must explicitly register types to show up in here and in search for objects
+ if ($type == 'object') {
+ if (is_array($subtype_array) && count($subtype_array)) {
+ $options['type_subtype_pairs'][$type] = $subtype_array;
}
- }
- }
- if (!empty($tempwhere)) {
- $where[] = "({$tempwhere})";
- }
- } else {
- $type = sanitise_string($type);
- if ($subtype AND !$subtype = get_subtype_id($type, $subtype)) {
- return false;
- }
-
- if ($type != "") {
- $where[] = "e.type='$type'";
- }
- if ($subtype!=="") {
- $where[] = "e.subtype=$subtype";
- }
- }
-
- if ($owner_guid != "") {
- if (!is_array($owner_guid)) {
- $owner_array = array($owner_guid);
- $owner_guid = (int) $owner_guid;
- // $where[] = "owner_guid = '$owner_guid'";
- } else if (sizeof($owner_guid) > 0) {
- $owner_array = array_map('sanitise_int', $owner_guid);
- // Cast every element to the owner_guid array to int
- // $owner_guid = array_map("sanitise_int", $owner_guid);
- // $owner_guid = implode(",",$owner_guid);
- // $where[] = "owner_guid in ({$owner_guid})";
- }
- if (is_null($container_guid)) {
- $container_guid = $owner_array;
- }
- }
-
- if ($site_guid > 0) {
- $where[] = "e.site_guid = {$site_guid}";
- }
-
- if (!is_null($container_guid)) {
- if (is_array($container_guid)) {
- foreach($container_guid as $key => $val) $container_guid[$key] = (int) $val;
- $where[] = "e.container_guid in (" . implode(",",$container_guid) . ")";
- } else {
- $container_guid = (int) $container_guid;
- $where[] = "e.container_guid = {$container_guid}";
- }
- }
-
- if ($name!="") {
- $where[] = "s.name = '$name'";
- }
-
- if ($value!="") {
- $where[] = "s.value='$value'";
- }
-
- if (!$count) {
- $query = "SELECT distinct e.*
- from {$CONFIG->dbprefix}entities e
- JOIN {$CONFIG->dbprefix}private_settings s ON e.guid=s.entity_guid where ";
- } else {
- $query = "SELECT count(distinct e.guid) as total
- from {$CONFIG->dbprefix}entities e JOIN {$CONFIG->dbprefix}private_settings s
- ON e.guid=s.entity_guid where ";
- }
- foreach ($where as $w) {
- $query .= " $w and ";
- }
- // Add access controls
- $query .= get_access_sql_suffix('e');
- if (!$count) {
- $query .= " order by $order_by";
- if ($limit) {
- // Add order and limit
- $query .= " limit $offset, $limit";
- }
-
- $dt = get_data($query, "entity_row_to_elggstar");
- return $dt;
- } else {
- $total = get_data_row($query);
- return $total->total;
- }
-}
-
-/**
- * Get entities based on their private data by multiple keys.
- *
- * @param string $name The name of the setting
- * @param string $value The value of the setting
- * @param string|array $type The type of entity (eg "user", "object" etc) or array(type1 => array('subtype1', ...'subtypeN'), ...)
- * @param string $subtype The arbitrary subtype of the entity
- * @param int $owner_guid The GUID of the owning user
- * @param string $order_by The field to order by; by default, time_created desc
- * @param int $limit The number of entities to return; 10 by default
- * @param int $offset The indexing offset, 0 by default
- * @param boolean $count Set to true to get a count rather than the entities themselves (limits and offsets don't apply in this context). Defaults to false.
- * @param int $site_guid The site to get entities for. Leave as 0 (default) for the current site; -1 for all sites.
- * @param int|array $container_guid The container or containers to get entities from (default: all containers).
- * @return array A list of entities.
- * @todo deprecate
- */
-function get_entities_from_private_setting_multi(array $name, $type = "", $subtype = "", $owner_guid = 0, $order_by = "", $limit = 10, $offset = 0, $count = false, $site_guid = 0, $container_guid = null) {
- global $CONFIG;
-
- if ($subtype === false || $subtype === null || $subtype === 0) {
- return false;
- }
-
- if ($order_by == "") {
- $order_by = "e.time_created desc";
- }
- $order_by = sanitise_string($order_by);
- $limit = (int)$limit;
- $offset = (int)$offset;
- $site_guid = (int) $site_guid;
- if ($site_guid == 0) {
- $site_guid = $CONFIG->site_guid;
- }
-
- $where = array();
-
- if (is_array($type)) {
- $tempwhere = "";
- if (sizeof($type)) {
- foreach($type as $typekey => $subtypearray) {
- foreach($subtypearray as $subtypeval) {
- $typekey = sanitise_string($typekey);
- if (!empty($subtypeval)) {
- if (!$subtypeval = (int) get_subtype_id($typekey, $subtypeval)) {
- return false;
- }
- } else {
- $subtypeval = 0;
- }
- if (!empty($tempwhere)) $tempwhere .= " or ";
- $tempwhere .= "(e.type = '{$typekey}' and e.subtype = {$subtypeval})";
+ } else {
+ if (is_array($subtype_array) && count($subtype_array)) {
+ $options['type_subtype_pairs'][$type] = $subtype_array;
+ } else {
+ $options['type_subtype_pairs'][$type] = ELGG_ENTITIES_ANY_VALUE;
}
}
}
- if (!empty($tempwhere)) {
- $where[] = "({$tempwhere})";
- }
-
- } else {
- $type = sanitise_string($type);
- if ($subtype AND !$subtype = get_subtype_id($type, $subtype)) {
- return false;
- }
-
- if ($type != "") {
- $where[] = "e.type='$type'";
- }
-
- if ($subtype!=="") {
- $where[] = "e.subtype=$subtype";
- }
}
- if ($owner_guid != "") {
- if (!is_array($owner_guid)) {
- $owner_array = array($owner_guid);
- $owner_guid = (int) $owner_guid;
- // $where[] = "owner_guid = '$owner_guid'";
- } else if (sizeof($owner_guid) > 0) {
- $owner_array = array_map('sanitise_int', $owner_guid);
- // Cast every element to the owner_guid array to int
- // $owner_guid = array_map("sanitise_int", $owner_guid);
- // $owner_guid = implode(",",$owner_guid);
- // $where[] = "owner_guid in ({$owner_guid})";
- }
- if (is_null($container_guid)) {
- $container_guid = $owner_array;
- }
- }
- if ($site_guid > 0) {
- $where[] = "e.site_guid = {$site_guid}";
- }
-
- if (!is_null($container_guid)) {
- if (is_array($container_guid)) {
- foreach($container_guid as $key => $val) $container_guid[$key] = (int) $val;
- $where[] = "e.container_guid in (" . implode(",",$container_guid) . ")";
- } else {
- $container_guid = (int) $container_guid;
- $where[] = "e.container_guid = {$container_guid}";
- }
- }
-
- if ($name) {
- $s_join = "";
- $i = 1;
- foreach ($name as $k => $n) {
- $k = sanitise_string($k);
- $n = sanitise_string($n);
- $s_join .= " JOIN {$CONFIG->dbprefix}private_settings s$i ON e.guid=s$i.entity_guid";
- $where[] = "s$i.name = '$k'";
- $where[] = "s$i.value = '$n'";
- $i++;
- }
- }
-
- if (!$count) {
- $query = "SELECT distinct e.* from {$CONFIG->dbprefix}entities e $s_join where ";
+ if (!empty($options['type_subtype_pairs'])) {
+ $count = elgg_get_entities(array_merge(array('count' => TRUE), $options));
+ $entities = elgg_get_entities($options);
} else {
- $query = "SELECT count(distinct e.guid) as total
- from {$CONFIG->dbprefix}entities e $s_join where ";
- }
-
- foreach ($where as $w) {
- $query .= " $w and ";
- }
-
- // Add access controls
- $query .= get_access_sql_suffix('e');
-
- if (!$count) {
- $query .= " order by $order_by";
- // Add order and limit
- if ($limit) {
- $query .= " limit $offset, $limit";
- }
-
- $dt = get_data($query, "entity_row_to_elggstar");
- return $dt;
- } else {
- $total = get_data_row($query);
- return $total->total;
- }
-}
-
-/**
- * Gets a private setting for an entity.
- *
- * Plugin authors can set private data on entities. By default
- * private data will not be searched or exported.
- *
- * @internal Private data is used to store settings for plugins
- * and user settings.
- *
- * @param int $entity_guid The entity GUID
- * @param string $name The name of the setting
- * @return mixed The setting value, or false on failure
- * @see set_private_setting()
- * @see get_all_private_settings()
- * @see remove_private_setting()
- * @see remove_all_private_settings()
- * @link http://docs.elgg.org/DataModel/Entities/PrivateSettings
- */
-function get_private_setting($entity_guid, $name) {
- global $CONFIG;
- $entity_guid = (int) $entity_guid;
- $name = sanitise_string($name);
-
- if ($setting = get_data_row("SELECT value from {$CONFIG->dbprefix}private_settings where name = '{$name}' and entity_guid = {$entity_guid}")) {
- return $setting->value;
- }
- return false;
-}
-
-/**
- * Return an array of all private settings.
- *
- * @param int $entity_guid The entity GUID
- * @return array|false
- * @see set_private_setting()
- * @see get_private_settings()
- * @see remove_private_setting()
- * @see remove_all_private_settings()
- * @link http://docs.elgg.org/DataModel/Entities/PrivateSettings
- */
-function get_all_private_settings($entity_guid) {
- global $CONFIG;
-
- $entity_guid = (int) $entity_guid;
-
- $result = get_data("SELECT * from {$CONFIG->dbprefix}private_settings where entity_guid = {$entity_guid}");
- if ($result) {
- $return = array();
- foreach ($result as $r) {
- $return[$r->name] = $r->value;
- }
-
- return $return;
- }
-
- return false;
-}
-
-/**
- * Sets a private setting for an entity.
- *
- * @param int $entity_guid The entity GUID
- * @param string $name The name of the setting
- * @param string $value The value of the setting
- * @return mixed The setting ID, or false on failure
- * @see get_private_setting()
- * @see get_all_private_settings()
- * @see remove_private_setting()
- * @see remove_all_private_settings()
- * @link http://docs.elgg.org/DataModel/Entities/PrivateSettings
- */
-function set_private_setting($entity_guid, $name, $value) {
- global $CONFIG;
-
- $entity_guid = (int) $entity_guid;
- $name = sanitise_string($name);
- $value = sanitise_string($value);
-
- $result = insert_data("INSERT into {$CONFIG->dbprefix}private_settings
- (entity_guid, name, value) VALUES
- ($entity_guid, '{$name}', '{$value}')
- ON DUPLICATE KEY UPDATE value='$value'");
- if ($result === 0) {
- return true;
- }
- return $result;
-}
-
-/**
- * Deletes a private setting for an entity.
- *
- * @param int $entity_guid The Entity GUID
- * @param string $name The name of the setting
- * @return true|false depending on success
- * @see get_private_setting()
- * @see get_all_private_settings()
- * @see set_private_setting()
- * @see remove_all_private_settings()
- * @link http://docs.elgg.org/DataModel/Entities/PrivateSettings
- */
-function remove_private_setting($entity_guid, $name) {
- global $CONFIG;
-
- $entity_guid = (int) $entity_guid;
- $name = sanitise_string($name);
-
- return delete_data("DELETE from {$CONFIG->dbprefix}private_settings
- where name = '{$name}'
- and entity_guid = {$entity_guid}");
-}
-
-/**
- * Deletes all private settings for an entity.
- *
- * @param int $entity_guid The Entity GUID
- * @return true|false depending on success
- * @see get_private_setting()
- * @see get_all_private_settings()
- * @see set_private_setting()
- * @see remove_private_settings()
- * @link http://docs.elgg.org/DataModel/Entities/PrivateSettings
- */
-function remove_all_private_settings($entity_guid) {
- global $CONFIG;
-
- $entity_guid = (int) $entity_guid;
- return delete_data("DELETE from {$CONFIG->dbprefix}private_settings
- where entity_guid = {$entity_guid}");
-}
-
-/*
- * Check the recursive delete permissions token.
- *
- * If an entity is deleted recursively, a permissions override is required to allow
- * contained or owned entities to be removed.
- *
- * @access private
- * @return bool
- * @elgg_plugin_hook_handler permissions_check all
- * @elgg_plugin_hook_handler permissions_check:metadata all
- */
-function recursive_delete_permissions_check($hook, $entity_type, $returnvalue, $params) {
- static $__RECURSIVE_DELETE_TOKEN;
-
- $entity = $params['entity'];
-
- if ((isloggedin()) && ($__RECURSIVE_DELETE_TOKEN) && (strcmp($__RECURSIVE_DELETE_TOKEN, md5(get_loggedin_userid())))) {
- return true;
+ $count = 0;
+ $entities = array();
}
- // consult next function
- return NULL;
+ $options['count'] = $count;
+ return elgg_view_entity_list($entities, $options);
}
/**
@@ -2734,16 +2457,19 @@ function recursive_delete_permissions_check($hook, $entity_type, $returnvalue, $
* @tip Use this function in actions and views to check that you are dealing
* with the correct type of entity.
*
- * @param $entity
- * @param $type
- * @param $subtype
- * @return Bool
- * @since 1.8
+ * @param mixed $entity Entity
+ * @param string $type Entity type
+ * @param string $subtype Entity subtype
+ * @param string $class Class name
+ *
+ * @return bool
+ * @since 1.8.0
*/
function elgg_instanceof($entity, $type = NULL, $subtype = NULL, $class = NULL) {
$return = ($entity instanceof ElggEntity);
if ($type) {
+ /* @var ElggEntity $entity */
$return = $return && ($entity->getType() == $type);
}
@@ -2758,30 +2484,32 @@ function elgg_instanceof($entity, $type = NULL, $subtype = NULL, $class = NULL)
return $return;
}
-
/**
* Update the last_action column in the entities table for $guid.
*
- * This determines the sort order of 1.8's default river.
- *
* @warning This is different to time_updated. Time_updated is automatically set,
* while last_action is only set when explicitly called.
*
- * @param int $guid Entity annotation|relationship action carried out on
+ * @param int $guid Entity annotation|relationship action carried out on
* @param int $posted Timestamp of last action
- **/
-function update_entity_last_action($guid, $posted = NULL){
+ *
+ * @return bool
+ * @access private
+ */
+function update_entity_last_action($guid, $posted = NULL) {
global $CONFIG;
$guid = (int)$guid;
+ $posted = (int)$posted;
if (!$posted) {
$posted = time();
}
- if ($guid){
+ if ($guid) {
//now add to the river updated table
- $query = update_data("UPDATE {$CONFIG->dbprefix}entities SET last_action = {$posted} WHERE guid = {$guid}");
- if ($query) {
+ $query = "UPDATE {$CONFIG->dbprefix}entities SET last_action = {$posted} WHERE guid = {$guid}";
+ $result = update_data($query);
+ if ($result) {
return TRUE;
} else {
return FALSE;
@@ -2794,27 +2522,38 @@ function update_entity_last_action($guid, $posted = NULL){
/**
* Garbage collect stub and fragments from any broken delete/create calls
*
- * @param unknown_type $hook
- * @param unknown_type $user
- * @param unknown_type $returnvalue
- * @param unknown_type $tag
+ * @return void
* @elgg_plugin_hook_handler gc system
+ * @access private
*/
-function entities_gc($hook, $user, $returnvalue, $tag) {
+function entities_gc() {
global $CONFIG;
- $tables = array ('sites_entity', 'objects_entity', 'groups_entity', 'users_entity');
+ $tables = array(
+ 'site' => 'sites_entity',
+ 'object' => 'objects_entity',
+ 'group' => 'groups_entity',
+ 'user' => 'users_entity'
+ );
- foreach ($tables as $table) {
- delete_data("DELETE from {$CONFIG->dbprefix}{$table}
- where guid NOT IN (SELECT guid from {$CONFIG->dbprefix}entities)");
+ foreach ($tables as $type => $table) {
+ delete_data("DELETE FROM {$CONFIG->dbprefix}{$table}
+ WHERE guid NOT IN (SELECT guid FROM {$CONFIG->dbprefix}entities)");
+ delete_data("DELETE FROM {$CONFIG->dbprefix}entities
+ WHERE type = '$type' AND guid NOT IN (SELECT guid FROM {$CONFIG->dbprefix}{$table})");
}
}
/**
* Runs unit tests for the entity objects.
*
- * @elgg_plugin_hook_handler unit_test system
+ * @param string $hook unit_test
+ * @param string $type system
+ * @param mixed $value Array of tests
+ * @param mixed $params Params
+ *
+ * @return array
+ * @access private
*/
function entities_test($hook, $type, $value, $params) {
global $CONFIG;
@@ -2825,32 +2564,27 @@ function entities_test($hook, $type, $value, $params) {
/**
* Entities init function; establishes the default entity page handler
*
+ * @return void
* @elgg_event_handler init system
+ * @access private
*/
function entities_init() {
- register_page_handler('view','entities_page_handler');
-
- register_plugin_hook('unit_test', 'system', 'entities_test');
+ elgg_register_page_handler('view', 'entities_page_handler');
- // Allow a permission override for recursive entity deletion
- // @todo Can this be done better?
- register_plugin_hook('permissions_check','all','recursive_delete_permissions_check');
- register_plugin_hook('permissions_check:metadata','all','recursive_delete_permissions_check');
+ elgg_register_plugin_hook_handler('unit_test', 'system', 'entities_test');
- register_plugin_hook('gc','system','entities_gc');
+ elgg_register_plugin_hook_handler('gc', 'system', 'entities_gc');
}
/** Register the import hook */
-register_plugin_hook("import", "all", "import_entity_plugin_hook", 0);
+elgg_register_plugin_hook_handler("import", "all", "import_entity_plugin_hook", 0);
/** Register the hook, ensuring entities are serialised first */
-register_plugin_hook("export", "all", "export_entity_plugin_hook", 0);
+elgg_register_plugin_hook_handler("export", "all", "export_entity_plugin_hook", 0);
/** Hook to get certain named bits of volatile data about an entity */
-register_plugin_hook('volatile', 'metadata', 'volatile_data_export_plugin_hook');
-
-/** Hook for rendering a default icon for entities */
-register_plugin_hook('entity:icon:url', 'all', 'default_entity_icon_hook', 1000);
+elgg_register_plugin_hook_handler('volatile', 'metadata', 'volatile_data_export_plugin_hook');
/** Register init system event **/
-register_elgg_event_handler('init', 'system', 'entities_init'); \ No newline at end of file
+elgg_register_event_handler('init', 'system', 'entities_init');
+