diff options
Diffstat (limited to 'engine/lib')
-rw-r--r-- | engine/lib/actions.php | 44 | ||||
-rw-r--r-- | engine/lib/elgglib.php | 2 | ||||
-rw-r--r-- | engine/lib/entities.php | 71 | ||||
-rw-r--r-- | engine/lib/languages.php | 3 | ||||
-rw-r--r-- | engine/lib/metadata.php | 13 | ||||
-rw-r--r-- | engine/lib/navigation.php | 12 | ||||
-rw-r--r-- | engine/lib/output.php | 18 | ||||
-rw-r--r-- | engine/lib/pagehandler.php | 12 | ||||
-rw-r--r-- | engine/lib/relationships.php | 9 | ||||
-rw-r--r-- | engine/lib/river.php | 4 | ||||
-rw-r--r-- | engine/lib/users.php | 1 | ||||
-rw-r--r-- | engine/lib/views.php | 2 |
12 files changed, 124 insertions, 67 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..3896cd58f 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) { @@ -48,14 +48,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 +77,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 +326,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 * @@ -672,8 +689,10 @@ 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. @@ -681,20 +700,33 @@ function get_entity($guid) { if (!is_numeric($guid) || $guid === 0 || $guid === '0') { return FALSE; } - - if ((!$newentity_cache) && (is_memcache_available())) { - $newentity_cache = new ElggMemcache('new_entity_cache'); + + // Check local cache first + $new_entity = retrieve_cached_entity($guid); + if ($new_entity) { + return $new_entity; } - if ($newentity_cache) { - $new_entity = $newentity_cache->load($guid); + // 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 ($shared_cache) { + $new_entity = $shared_cache->load($guid); + if ($new_entity) { + return $new_entity; + } } + $new_entity = entity_row_to_elggstar(get_entity_as_row($guid)); if ($new_entity) { - return $new_entity; + cache_entity($new_entity); } - - return entity_row_to_elggstar(get_entity_as_row($guid)); + return $new_entity; } /** @@ -936,6 +968,18 @@ function elgg_get_entities(array $options = array()) { } $dt = get_data($query, $options['callback']); + if ($dt) { + foreach ($dt as $entity) { + // If a custom callback is provided, it could return something other than ElggEntity, + // so we have to do an explicit check here. + if ($entity instanceof ElggEntity) { + cache_entity($entity); + } + } + // @todo Without this, recursive delete fails. See #4568 + reset($dt); + } + return $dt; } else { $total = get_data_row($query); @@ -1408,6 +1452,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' 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..77fa30e41 100644 --- a/engine/lib/metadata.php +++ b/engine/lib/metadata.php @@ -361,13 +361,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: 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/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 |