aboutsummaryrefslogtreecommitdiff
path: root/engine/lib
diff options
context:
space:
mode:
Diffstat (limited to 'engine/lib')
-rw-r--r--engine/lib/actions.php44
-rw-r--r--engine/lib/elgglib.php2
-rw-r--r--engine/lib/entities.php120
-rw-r--r--engine/lib/languages.php3
-rw-r--r--engine/lib/metadata.php135
-rw-r--r--engine/lib/navigation.php12
-rw-r--r--engine/lib/output.php18
-rw-r--r--engine/lib/pagehandler.php12
-rw-r--r--engine/lib/relationships.php9
-rw-r--r--engine/lib/river.php4
-rw-r--r--engine/lib/sites.php12
-rw-r--r--engine/lib/upgrades/2010121602.php2
-rw-r--r--engine/lib/users.php1
-rw-r--r--engine/lib/views.php2
14 files changed, 256 insertions, 120 deletions
diff --git a/engine/lib/actions.php b/engine/lib/actions.php
index 3a7c02488..53b185dea 100644
--- a/engine/lib/actions.php
+++ b/engine/lib/actions.php
@@ -82,44 +82,28 @@ function action($action, $forwarder = "") {
$forwarder = str_replace(elgg_get_site_url(), "", $forwarder);
$forwarder = str_replace("http://", "", $forwarder);
$forwarder = str_replace("@", "", $forwarder);
-
if (substr($forwarder, 0, 1) == "/") {
$forwarder = substr($forwarder, 1);
}
- if (isset($CONFIG->actions[$action])) {
- if (elgg_is_admin_logged_in() || ($CONFIG->actions[$action]['access'] !== 'admin')) {
- if (elgg_is_logged_in() || ($CONFIG->actions[$action]['access'] === 'public')) {
-
- // Trigger action event
- // @todo This is only called before the primary action is called.
- $event_result = true;
- $event_result = elgg_trigger_plugin_hook('action', $action, null, $event_result);
-
- // Include action
- // Event_result being false doesn't produce an error
- // since i assume this will be handled in the hook itself.
- // @todo make this better!
- if ($event_result) {
- if (!include($CONFIG->actions[$action]['file'])) {
- register_error(elgg_echo('actionnotfound', array($action)));
- }
- }
- } else {
- register_error(elgg_echo('actionloggedout'));
+ if (!isset($CONFIG->actions[$action])) {
+ register_error(elgg_echo('actionundefined', array($action)));
+ } elseif (!elgg_is_admin_logged_in() && ($CONFIG->actions[$action]['access'] === 'admin')) {
+ register_error(elgg_echo('actionunauthorized'));
+ } elseif (!elgg_is_logged_in() && ($CONFIG->actions[$action]['access'] !== 'public')) {
+ register_error(elgg_echo('actionloggedout'));
+ } else {
+ // Returning falsy doesn't produce an error
+ // We assume this will be handled in the hook itself.
+ if (elgg_trigger_plugin_hook('action', $action, null, true)) {
+ if (!include($CONFIG->actions[$action]['file'])) {
+ register_error(elgg_echo('actionnotfound', array($action)));
}
- } else {
- register_error(elgg_echo('actionunauthorized'));
}
- } else {
- register_error(elgg_echo('actionundefined', array($action)));
}
- if (!empty($forwarder)) {
- forward($forwarder);
- } else {
- forward(REFERER);
- }
+ $forwarder = empty($forwarder) ? REFERER : $forwarder;
+ forward($forwarder);
}
/**
diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php
index 3026a78e3..554b0561f 100644
--- a/engine/lib/elgglib.php
+++ b/engine/lib/elgglib.php
@@ -1575,7 +1575,7 @@ function elgg_http_url_is_identical($url1, $url2, $ignore_params = array('offset
* @param bool $strict Return array key if it's set, even if empty. If false,
* return $default if the array key is unset or empty.
*
- * @return void
+ * @return mixed
* @since 1.8.0
*/
function elgg_extract($key, array $array, $default = null, $strict = true) {
diff --git a/engine/lib/entities.php b/engine/lib/entities.php
index abfe07276..a50567d9f 100644
--- a/engine/lib/entities.php
+++ b/engine/lib/entities.php
@@ -30,7 +30,7 @@ $SUBTYPE_CACHE = NULL;
*
* @param int $guid The entity guid
*
- * @return void
+ * @return null
* @access private
*/
function invalidate_cache_for_entity($guid) {
@@ -39,6 +39,8 @@ function invalidate_cache_for_entity($guid) {
$guid = (int)$guid;
unset($ENTITY_CACHE[$guid]);
+
+ elgg_get_metadata_cache()->clear($guid);
}
/**
@@ -48,14 +50,27 @@ function invalidate_cache_for_entity($guid) {
*
* @param ElggEntity $entity Entity to cache
*
- * @return void
+ * @return null
* @see retrieve_cached_entity()
* @see invalidate_cache_for_entity()
* @access private
+ * TODO(evan): Use an ElggCache object
*/
function cache_entity(ElggEntity $entity) {
global $ENTITY_CACHE;
+ // Don't cache entities while access control is off, otherwise they could be
+ // exposed to users who shouldn't see them when control is re-enabled.
+ if (elgg_get_ignore_access()) {
+ return;
+ }
+
+ // Don't store too many or we'll have memory problems
+ // TODO(evan): Pick a less arbitrary limit
+ if (count($ENTITY_CACHE) > 256) {
+ unset($ENTITY_CACHE[array_rand($ENTITY_CACHE)]);
+ }
+
$ENTITY_CACHE[$entity->guid] = $entity;
}
@@ -64,7 +79,7 @@ function cache_entity(ElggEntity $entity) {
*
* @param int $guid The guid
*
- * @return void
+ * @return ElggEntity|bool false if entity not cached, or not fully loaded
* @see cache_entity()
* @see invalidate_cache_for_entity()
* @access private
@@ -313,6 +328,10 @@ function add_subtype($type, $subtype, $class = "") {
/**
* Removes a registered ElggEntity type, subtype, and classname.
*
+ * @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
*
@@ -589,12 +608,14 @@ function get_entity_as_row($guid) {
*
* @param stdClass $row The row of the entry in the entities table.
*
- * @return object|false
+ * @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)) {
@@ -672,29 +693,53 @@ function entity_row_to_elggstar($row) {
* @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;
+ return false;
+ }
+
+ // Check local cache first
+ $new_entity = retrieve_cached_entity($guid);
+ if ($new_entity) {
+ return $new_entity;
}
- if ((!$newentity_cache) && (is_memcache_available())) {
- $newentity_cache = new ElggMemcache('new_entity_cache');
+ // 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) {
- $new_entity = $newentity_cache->load($guid);
+ // until ACLs in memcache, DB query is required to determine access
+ $entity_row = get_entity_as_row($guid);
+ if (!$entity_row) {
+ return false;
}
- if ($new_entity) {
- return $new_entity;
+ if ($shared_cache) {
+ $cached_entity = $shared_cache->load($guid);
+ // @todo store ACLs in memcache http://trac.elgg.org/ticket/3018#comment:3
+ if ($cached_entity) {
+ // @todo use ACL and cached entity access_id to determine if user can see it
+ return $cached_entity;
+ }
}
- return entity_row_to_elggstar(get_entity_as_row($guid));
+ $new_entity = entity_row_to_elggstar($entity_row);
+ if ($new_entity) {
+ cache_entity($new_entity);
+ }
+ return $new_entity;
}
/**
@@ -936,6 +981,26 @@ function elgg_get_entities(array $options = array()) {
}
$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) {
+ 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);
+
+ if ($guids) {
+ elgg_get_metadata_cache()->populateFromEntities($guids);
+ }
+ }
return $dt;
} else {
$total = get_data_row($query);
@@ -1109,7 +1174,7 @@ function elgg_get_entity_type_subtype_where_sql($table, $types, $subtypes, $pair
* best to provide in table.column format.
* @param NULL|array $guids Array of GUIDs.
*
- * @return false|str
+ * @return false|string
* @since 1.8.0
* @access private
*/
@@ -1158,7 +1223,7 @@ function elgg_get_guid_based_where_sql($column, $guids) {
* @param NULL|int $time_updated_upper Time updated upper limit
* @param NULL|int $time_updated_lower Time updated lower limit
*
- * @return FALSE|str FALSE on fail, string on success.
+ * @return FALSE|string FALSE on fail, string on success.
* @since 1.7.0
* @access private
*/
@@ -1260,7 +1325,7 @@ function elgg_list_entities(array $options = array(), $getter = 'elgg_get_entiti
* @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 Order_by SQL order by clause
+ * @param string $order_by Order_by SQL order by clause
*
* @return array|false Either an array months as YYYYMM, or false on failure
*/
@@ -1408,6 +1473,7 @@ function disable_entity($guid, $reason = "", $recursive = true) {
$entity->disableMetadata();
$entity->disableAnnotations();
+ invalidate_cache_for_entity($guid);
$res = update_data("UPDATE {$CONFIG->dbprefix}entities
SET enabled = 'no'
@@ -1604,7 +1670,7 @@ function delete_entity($guid, $recursive = true) {
* @param string $returnvalue Return value from previous hook
* @param array $params The parameters, passed 'guid' and 'varname'
*
- * @return void
+ * @return ElggMetadata|null
* @elgg_plugin_hook_handler volatile metadata
* @todo investigate more.
* @access private
@@ -1649,6 +1715,8 @@ function volatile_data_export_plugin_hook($hook, $entity_type, $returnvalue, $pa
* @elgg_event_handler export all
* @return mixed
* @access private
+ *
+ * @throws InvalidParameterException|InvalidClassException
*/
function export_entity_plugin_hook($hook, $entity_type, $returnvalue, $params) {
// Sanity check values
@@ -1691,6 +1759,8 @@ function export_entity_plugin_hook($hook, $entity_type, $returnvalue, $params) {
* @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');
@@ -1762,6 +1832,8 @@ function oddentity_to_elggentity(ODDEntity $element) {
* @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'];
@@ -1808,8 +1880,6 @@ function import_entity_plugin_hook($hook, $entity_type, $returnvalue, $params) {
* @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) {
@@ -1933,7 +2003,7 @@ function get_entity_url($entity_guid) {
* @param string $entity_subtype The entity subtype
* @param string $function_name The function to register
*
- * @return true|false Depending on success
+ * @return bool Depending on success
* @see get_entity_url()
* @see ElggEntity::getURL()
* @since 1.8.0
@@ -1969,7 +2039,7 @@ function elgg_register_entity_url_handler($entity_type, $entity_subtype, $functi
* @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
+ * @return bool Depending on success
* @see get_registered_entity_types()
* @link http://docs.elgg.org/Search
* @link http://docs.elgg.org/Tutorials/Search
@@ -2006,7 +2076,7 @@ function elgg_register_entity_type($type, $subtype = null) {
* @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
+ * @return bool Depending on success
* @see elgg_register_entity_type()
*/
function unregister_entity_type($type, $subtype) {
@@ -2073,7 +2143,7 @@ function get_registered_entity_types($type = null) {
* @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 = null) {
global $CONFIG;
@@ -2273,7 +2343,7 @@ function entities_gc() {
/**
* Runs unit tests for the entity objects.
*
- * @param sting $hook unit_test
+ * @param string $hook unit_test
* @param string $type system
* @param mixed $value Array of tests
* @param mixed $params Params
diff --git a/engine/lib/languages.php b/engine/lib/languages.php
index 15c48f902..98006f7cd 100644
--- a/engine/lib/languages.php
+++ b/engine/lib/languages.php
@@ -50,8 +50,11 @@ function elgg_echo($message_key, $args = array(), $language = "") {
$string = $CONFIG->translations[$language][$message_key];
} else if (isset($CONFIG->translations["en"][$message_key])) {
$string = $CONFIG->translations["en"][$message_key];
+ $lang = $CONFIG->translations["en"][$language];
+ elgg_log(sprintf('Missing %s translation for "%s" language key', $lang, $message_key), 'NOTICE');
} else {
$string = $message_key;
+ elgg_log(sprintf('Missing English translation for "%s" language key', $message_key), 'NOTICE');
}
// only pass through if we have arguments to allow backward compatibility
diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php
index 0ff3a43dc..f76c20f24 100644
--- a/engine/lib/metadata.php
+++ b/engine/lib/metadata.php
@@ -12,7 +12,7 @@
*
* @param stdClass $row An object from the database
*
- * @return stdClass or ElggMetadata
+ * @return stdClass|ElggMetadata
* @access private
*/
function row_to_elggmetadata($row) {
@@ -30,7 +30,7 @@ function row_to_elggmetadata($row) {
*
* @param int $id The id of the metadata object being retrieved.
*
- * @return false|ElggMetadata
+ * @return ElggMetadata|false FALSE if not found
*/
function elgg_get_metadata_from_id($id) {
return elgg_get_metastring_based_object_from_id($id, 'metadata');
@@ -64,7 +64,7 @@ function elgg_delete_metadata_by_id($id) {
* @param int $access_id Default is ACCESS_PRIVATE
* @param bool $allow_multiple Allow multiple values for one key. Default is FALSE
*
- * @return int/bool id of metadata or FALSE if failure
+ * @return int|false id of metadata or FALSE if failure
*/
function create_metadata($entity_guid, $name, $value, $value_type = '', $owner_guid = 0,
$access_id = ACCESS_PRIVATE, $allow_multiple = false) {
@@ -90,8 +90,6 @@ function create_metadata($entity_guid, $name, $value, $value_type = '', $owner_g
$access_id = (int)$access_id;
- $id = false;
-
$query = "SELECT * from {$CONFIG->dbprefix}metadata"
. " WHERE entity_guid = $entity_guid and name_id=" . add_metastring($name) . " limit 1";
@@ -106,34 +104,33 @@ function create_metadata($entity_guid, $name, $value, $value_type = '', $owner_g
} else {
// Support boolean types
if (is_bool($value)) {
- if ($value) {
- $value = 1;
- } else {
- $value = 0;
- }
+ $value = (int) $value;
}
// Add the metastrings
- $value = add_metastring($value);
- if (!$value) {
+ $value_id = add_metastring($value);
+ if (!$value_id) {
return false;
}
- $name = add_metastring($name);
- if (!$name) {
+ $name_id = add_metastring($name);
+ if (!$name_id) {
return false;
}
// If ok then add it
$query = "INSERT into {$CONFIG->dbprefix}metadata"
. " (entity_guid, name_id, value_id, value_type, owner_guid, time_created, access_id)"
- . " VALUES ($entity_guid, '$name','$value','$value_type', $owner_guid, $time, $access_id)";
+ . " VALUES ($entity_guid, '$name_id','$value_id','$value_type', $owner_guid, $time, $access_id)";
$id = insert_data($query);
if ($id !== false) {
$obj = elgg_get_metadata_from_id($id);
if (elgg_trigger_event('create', 'metadata', $obj)) {
+
+ elgg_get_metadata_cache()->save($entity_guid, $name, $value, $allow_multiple);
+
return $id;
} else {
elgg_delete_metadata_by_id($id);
@@ -175,6 +172,7 @@ function update_metadata($id, $name, $value, $value_type, $owner_guid, $access_i
}
if ($metabyname_memcache) {
+ // @todo fix memcache (name_id is not a property of ElggMetadata)
$metabyname_memcache->delete("{$md->entity_guid}:{$md->name_id}");
}
@@ -187,15 +185,9 @@ function update_metadata($id, $name, $value, $value_type, $owner_guid, $access_i
$access_id = (int)$access_id;
- $access = get_access_sql_suffix();
-
// Support boolean types (as integers)
if (is_bool($value)) {
- if ($value) {
- $value = 1;
- } else {
- $value = 0;
- }
+ $value = (int) $value;
}
// Add the metastring
@@ -216,6 +208,9 @@ function update_metadata($id, $name, $value, $value_type, $owner_guid, $access_i
$result = update_data($query);
if ($result !== false) {
+
+ elgg_get_metadata_cache()->save($md->entity_guid, $name, $value);
+
// @todo this event tells you the metadata has been updated, but does not
// let you do anything about it. What is needed is a plugin hook before
// the update that passes old and new values.
@@ -234,7 +229,7 @@ function update_metadata($id, $name, $value, $value_type, $owner_guid, $access_i
* associative arrays and there is no guarantee on the ordering in the array.
*
* @param int $entity_guid The entity to attach the metadata to
- * @param string $name_and_values Associative array - a value can be a string, number, bool
+ * @param array $name_and_values Associative array - a value can be a string, number, bool
* @param string $value_type 'text', 'integer', or '' for automatic detection
* @param int $owner_guid GUID of entity that owns the metadata
* @param int $access_id Default is ACCESS_PRIVATE
@@ -308,6 +303,8 @@ function elgg_delete_metadata(array $options) {
return false;
}
+ elgg_get_metadata_cache()->invalidateByOptions('delete', $options);
+
$options['metastring_type'] = 'metadata';
return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback', false);
}
@@ -328,6 +325,8 @@ function elgg_disable_metadata(array $options) {
return false;
}
+ elgg_get_metadata_cache()->invalidateByOptions('disable', $options);
+
$options['metastring_type'] = 'metadata';
return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', false);
}
@@ -348,6 +347,8 @@ function elgg_enable_metadata(array $options) {
return false;
}
+ elgg_get_metadata_cache()->invalidateByOptions('enable', $options);
+
$options['metastring_type'] = 'metadata';
return elgg_batch_metastring_based_objects($options, 'elgg_batch_enable_callback');
}
@@ -361,13 +362,24 @@ function elgg_enable_metadata(array $options) {
* options available to elgg_get_entities(). Supports
* the singular option shortcut.
*
- * NB: Using metadata_names and metadata_values results in a
+ * @note Using metadata_names and metadata_values results in a
* "names IN (...) AND values IN (...)" clause. This is subtly
* differently than default multiple metadata_name_value_pairs, which use
* "(name = value) AND (name = value)" clauses.
*
* When in doubt, use name_value_pairs.
*
+ * To ask for entities that do not have a metadata value, use a custom
+ * where clause like this:
+ *
+ * $options['wheres'][] = "NOT EXISTS (
+ * SELECT 1 FROM {$dbprefix}metadata md
+ * WHERE md.entity_guid = e.guid
+ * AND md.name_id = $name_metastring_id
+ * AND md.value_id = $value_metastring_id)";
+ *
+ * Note the metadata name and value has been denormalized in the above example.
+ *
* @see elgg_get_entities
*
* @param array $options Array in format:
@@ -438,16 +450,16 @@ function elgg_get_entities_from_metadata(array $options = array()) {
* This function is reused for annotations because the tables are
* exactly the same.
*
- * @param string $e_table Entities table name
- * @param string $n_table Normalized metastrings table name (Where entities,
+ * @param string $e_table Entities table name
+ * @param string $n_table Normalized metastrings table name (Where entities,
* values, and names are joined. annotations / metadata)
- * @param arr|null $names Array of names
- * @param arr|null $values Array of values
- * @param arr|null $pairs Array of names / values / operands
- * @param and|or $pair_operator Operator to use to join the where clauses for pairs
- * @param bool $case_sensitive Case sensitive metadata names?
- * @param arr|null $order_by_metadata Array of names / direction
- * @param arr|null $owner_guids Array of owner GUIDs
+ * @param array|null $names Array of names
+ * @param array|null $values Array of values
+ * @param array|null $pairs Array of names / values / operands
+ * @param string $pair_operator ("AND" or "OR") Operator to use to join the where clauses for pairs
+ * @param bool $case_sensitive Case sensitive metadata names?
+ * @param array|null $order_by_metadata Array of names / direction
+ * @param array|null $owner_guids Array of owner GUIDs
*
* @return FALSE|array False on fail, array('joins', 'wheres')
* @since 1.7.0
@@ -721,6 +733,8 @@ function elgg_list_entities_from_metadata($options) {
*
* @return array
* @access private
+ *
+ * @throws InvalidParameterException
*/
function export_metadata_plugin_hook($hook, $entity_type, $returnvalue, $params) {
// Sanity check values
@@ -732,15 +746,13 @@ function export_metadata_plugin_hook($hook, $entity_type, $returnvalue, $params)
throw new InvalidParameterException(elgg_echo('InvalidParameterException:NonArrayReturnValue'));
}
- $guid = (int)$params['guid'];
- $name = $params['name'];
-
$result = elgg_get_metadata(array(
- 'guid' => $guid,
- 'limit' => 0
+ 'guid' => (int)$params['guid'],
+ 'limit' => 0,
));
if ($result) {
+ /* @var ElggMetadata[] $result */
foreach ($result as $r) {
$returnvalue[] = $r->export();
}
@@ -878,6 +890,50 @@ function elgg_register_metadata_url_handler($extender_name, $function) {
return elgg_register_extender_url_handler('metadata', $extender_name, $function);
}
+/**
+ * Get the global metadata cache instance
+ *
+ * @return ElggVolatileMetadataCache
+ *
+ * @access private
+ */
+function elgg_get_metadata_cache() {
+ global $CONFIG;
+ if (empty($CONFIG->local_metadata_cache)) {
+ $CONFIG->local_metadata_cache = new ElggVolatileMetadataCache();
+ }
+ return $CONFIG->local_metadata_cache;
+}
+
+/**
+ * Invalidate the metadata cache based on options passed to various *_metadata functions
+ *
+ * @param string $action Action performed on metadata. "delete", "disable", or "enable"
+ *
+ * @param array $options Options passed to elgg_(delete|disable|enable)_metadata
+ */
+function elgg_invalidate_metadata_cache($action, array $options) {
+ // remove as little as possible, optimizing for common cases
+ $cache = elgg_get_metadata_cache();
+ if (empty($options['guid'])) {
+ // safest to clear everything unless we want to make this even more complex :(
+ $cache->flush();
+ } else {
+ if (empty($options['metadata_name'])) {
+ // safest to clear the whole entity
+ $cache->clear($options['guid']);
+ } else {
+ switch ($action) {
+ case 'delete':
+ $cache->markEmpty($options['guid'], $options['metadata_name']);
+ break;
+ default:
+ $cache->markUnknown($options['guid'], $options['metadata_name']);
+ }
+ }
+ }
+}
+
/** Register the hook */
elgg_register_plugin_hook_handler("export", "all", "export_metadata_plugin_hook", 2);
@@ -901,5 +957,6 @@ elgg_register_plugin_hook_handler('unit_test', 'system', 'metadata_test');
function metadata_test($hook, $type, $value, $params) {
global $CONFIG;
$value[] = $CONFIG->path . 'engine/tests/api/metadata.php';
+ $value[] = $CONFIG->path . 'engine/tests/api/metadata_cache.php';
return $value;
-} \ No newline at end of file
+}
diff --git a/engine/lib/navigation.php b/engine/lib/navigation.php
index 4ff009bfb..8c3952594 100644
--- a/engine/lib/navigation.php
+++ b/engine/lib/navigation.php
@@ -335,6 +335,18 @@ function elgg_river_menu_setup($hook, $type, $return, $params) {
$return[] = ElggMenuItem::factory($options);
}
}
+
+ if (elgg_is_admin_logged_in()) {
+ $options = array(
+ 'name' => 'delete',
+ 'href' => elgg_add_action_tokens_to_url("action/river/delete?id=$item->id"),
+ 'text' => elgg_view_icon('delete'),
+ 'title' => elgg_echo('delete'),
+ 'confirm' => elgg_echo('deleteconfirm'),
+ 'priority' => 200,
+ );
+ $return[] = ElggMenuItem::factory($options);
+ }
}
return $return;
diff --git a/engine/lib/output.php b/engine/lib/output.php
index b1245a924..7bfc4be6e 100644
--- a/engine/lib/output.php
+++ b/engine/lib/output.php
@@ -310,19 +310,11 @@ function elgg_get_friendly_title($title) {
return $result;
}
- // @todo not using this because of locale concerns
- //$title = iconv('UTF-8', 'ASCII//TRANSLIT', $title);
-
- // @todo this uses a utf8 character class. can use if
- // we want to support utf8 in the url.
- //$title = preg_replace('/[^\p{L}\- ]/u', '', $title);
-
- // use A-Za-z0-9_ instead of \w because \w is locale sensitive
- $title = preg_replace("/[^A-Za-z0-9_\- ]/", "", $title);
- $title = str_replace(" ", "-", $title);
- $title = str_replace("--", "-", $title);
- $title = trim($title);
- $title = elgg_strtolower($title);
+ // handle some special cases
+ $title = str_replace('&', 'and', $title);
+
+ $title = ElggTranslit::urlize($title);
+
return $title;
}
diff --git a/engine/lib/pagehandler.php b/engine/lib/pagehandler.php
index 46c7d059e..ba7518a77 100644
--- a/engine/lib/pagehandler.php
+++ b/engine/lib/pagehandler.php
@@ -31,18 +31,18 @@ function page_handler($handler, $page) {
}
// return false to stop processing the request (because you handled it)
- // return a new $params array if you want to route the request differently
- $params = array(
+ // return a new $request array if you want to route the request differently
+ $request = array(
'handler' => $handler,
'segments' => $page,
);
- $params = elgg_trigger_plugin_hook('route', $handler, NULL, $params);
- if ($params === false) {
+ $request = elgg_trigger_plugin_hook('route', $handler, null, $request);
+ if ($request === false) {
return true;
}
- $handler = $params['handler'];
- $page = $params['segments'];
+ $handler = $request['handler'];
+ $page = $request['segments'];
$result = false;
if (isset($CONFIG->pagehandler) && !empty($handler) && isset($CONFIG->pagehandler[$handler])) {
diff --git a/engine/lib/relationships.php b/engine/lib/relationships.php
index f50c4a485..09d541e22 100644
--- a/engine/lib/relationships.php
+++ b/engine/lib/relationships.php
@@ -239,6 +239,15 @@ function get_entity_relationships($guid, $inverse_relationship = FALSE) {
* Also accepts all options available to elgg_get_entities() and
* elgg_get_entities_from_metadata().
*
+ * To ask for entities that do not have a particulat relationship to an entity,
+ * use a custom where clause like the following:
+ *
+ * $options['wheres'][] = "NOT EXISTS (
+ * SELECT 1 FROM {$db_prefix}entity_relationships
+ * WHERE guid_one = e.guid
+ * AND relationship = '$relationship'
+ * )";
+ *
* @see elgg_get_entities
* @see elgg_get_entities_from_metadata
*
diff --git a/engine/lib/river.php b/engine/lib/river.php
index 711832f70..b717a7756 100644
--- a/engine/lib/river.php
+++ b/engine/lib/river.php
@@ -643,9 +643,11 @@ function elgg_river_init() {
elgg_register_page_handler('activity', 'elgg_river_page_handler');
$item = new ElggMenuItem('activity', elgg_echo('activity'), 'activity');
elgg_register_menu_item('site', $item);
-
+
elgg_register_widget_type('river_widget', elgg_echo('river:widget:title'), elgg_echo('river:widget:description'));
+ elgg_register_action('river/delete', '', 'admin');
+
elgg_register_plugin_hook_handler('unit_test', 'system', 'elgg_river_test');
}
diff --git a/engine/lib/sites.php b/engine/lib/sites.php
index 850092cad..8b772668d 100644
--- a/engine/lib/sites.php
+++ b/engine/lib/sites.php
@@ -18,11 +18,19 @@
function elgg_get_site_entity($site_guid = 0) {
global $CONFIG;
+ $result = false;
+
if ($site_guid == 0) {
- return $CONFIG->site;
+ $site = $CONFIG->site;
+ } else {
+ $site = get_entity($site_guid);
+ }
+
+ if($site instanceof ElggSite){
+ $result = $site;
}
- return get_entity($site_guid);
+ return $result;
}
/**
diff --git a/engine/lib/upgrades/2010121602.php b/engine/lib/upgrades/2010121602.php
index 2d55c8214..5b0996b5e 100644
--- a/engine/lib/upgrades/2010121602.php
+++ b/engine/lib/upgrades/2010121602.php
@@ -4,7 +4,7 @@
*/
$query = "UPDATE {$CONFIG->dbprefix}river
- SET view='river/annotation/generic_comment/create', action_type='create'
+ SET view='river/annotation/generic_comment/create'
WHERE view='annotation/annotate' AND action_type='comment'";
update_data($query);
diff --git a/engine/lib/users.php b/engine/lib/users.php
index 241b524f9..527eff3cd 100644
--- a/engine/lib/users.php
+++ b/engine/lib/users.php
@@ -136,7 +136,6 @@ function ban_user($user_guid, $reason = "") {
global $CONFIG;
$user_guid = (int)$user_guid;
- $reason = sanitise_string($reason);
$user = get_entity($user_guid);
diff --git a/engine/lib/views.php b/engine/lib/views.php
index 25acbf2b2..b00334062 100644
--- a/engine/lib/views.php
+++ b/engine/lib/views.php
@@ -303,7 +303,7 @@ function elgg_set_view_location($view, $location, $viewtype = '') {
/**
* Returns whether the specified view exists
*
- * @note If $recurse is strue, also checks if a view exists only as an extension.
+ * @note If $recurse is true, also checks if a view exists only as an extension.
*
* @param string $view The view name
* @param string $viewtype If set, forces the viewtype