aboutsummaryrefslogtreecommitdiff
path: root/engine/lib
diff options
context:
space:
mode:
Diffstat (limited to 'engine/lib')
-rw-r--r--engine/lib/access.php11
-rw-r--r--engine/lib/actions.php117
-rw-r--r--engine/lib/admin.php37
-rw-r--r--engine/lib/annotations.php89
-rw-r--r--engine/lib/cache.php11
-rw-r--r--engine/lib/calendar.php2
-rw-r--r--engine/lib/configuration.php29
-rw-r--r--engine/lib/cron.php4
-rw-r--r--engine/lib/database.php95
-rw-r--r--engine/lib/deprecated-1.7.php2
-rw-r--r--engine/lib/deprecated-1.8.php66
-rw-r--r--engine/lib/elgglib.php78
-rw-r--r--engine/lib/entities.php216
-rw-r--r--engine/lib/export.php29
-rw-r--r--engine/lib/extender.php20
-rw-r--r--engine/lib/filestore.php6
-rw-r--r--engine/lib/group.php6
-rw-r--r--engine/lib/input.php15
-rw-r--r--engine/lib/languages.php48
-rw-r--r--engine/lib/location.php4
-rw-r--r--engine/lib/mb_wrapper.php2
-rw-r--r--engine/lib/memcache.php20
-rw-r--r--engine/lib/metadata.php62
-rw-r--r--engine/lib/metastrings.php37
-rw-r--r--engine/lib/navigation.php21
-rw-r--r--engine/lib/notification.php38
-rw-r--r--engine/lib/objects.php6
-rw-r--r--engine/lib/opendd.php4
-rw-r--r--engine/lib/output.php57
-rw-r--r--engine/lib/pageowner.php7
-rw-r--r--engine/lib/plugins.php90
-rw-r--r--engine/lib/relationships.php34
-rw-r--r--engine/lib/river.php23
-rw-r--r--engine/lib/sessions.php17
-rw-r--r--engine/lib/sites.php12
-rw-r--r--engine/lib/statistics.php11
-rw-r--r--engine/lib/system_log.php22
-rw-r--r--engine/lib/tags.php7
-rw-r--r--engine/lib/upgrade.php21
-rw-r--r--engine/lib/upgrades/2009102801.php5
-rw-r--r--engine/lib/upgrades/2010033101.php2
-rw-r--r--engine/lib/upgrades/2010061501.php6
-rw-r--r--engine/lib/upgrades/2010071001.php5
-rw-r--r--engine/lib/upgrades/2010071002.php5
-rw-r--r--engine/lib/upgrades/2011052801.php5
-rw-r--r--engine/lib/upgrades/2012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php2
-rw-r--r--engine/lib/upgrades/2013030600-1.8.13-update_user_location-8999eb8bf1bdd9a3.php24
-rw-r--r--engine/lib/upgrades/2013051700-1.8.15-add_missing_group_index-52a63a3a3ffaced2.php28
-rw-r--r--engine/lib/upgrades/2013052900-1.8.15-ipv6_in_syslog-f5c2cc0196e9e731.php12
-rw-r--r--engine/lib/upgrades/2013060900-1.8.15-site_secret-404fc165cf9e0ac9.php16
-rw-r--r--engine/lib/upgrades/create_upgrade.php5
-rw-r--r--engine/lib/user_settings.php7
-rw-r--r--engine/lib/users.php100
-rw-r--r--engine/lib/views.php56
-rw-r--r--engine/lib/web_services.php27
-rw-r--r--engine/lib/widgets.php3
-rw-r--r--engine/lib/xml.php2
57 files changed, 1112 insertions, 574 deletions
diff --git a/engine/lib/access.php b/engine/lib/access.php
index f7d3bf7ea..de0693ea8 100644
--- a/engine/lib/access.php
+++ b/engine/lib/access.php
@@ -1015,6 +1015,10 @@ function access_init() {
*
* Returns true to override the access system or null if no change is needed.
*
+ * @param string $hook
+ * @param string $type
+ * @param bool $value
+ * @param array $params
* @return true|null
* @access private
*/
@@ -1047,6 +1051,13 @@ function elgg_override_permissions($hook, $type, $value, $params) {
/**
* Runs unit tests for the entities object.
+ *
+ * @param string $hook
+ * @param string $type
+ * @param array $value
+ * @param array $params
+ * @return array
+ *
* @access private
*/
function access_test($hook, $type, $value, $params) {
diff --git a/engine/lib/actions.php b/engine/lib/actions.php
index 53b185dea..8047914ac 100644
--- a/engine/lib/actions.php
+++ b/engine/lib/actions.php
@@ -65,18 +65,16 @@ function action($action, $forwarder = "") {
// @todo REMOVE THESE ONCE #1509 IS IN PLACE.
// Allow users to disable plugins without a token in order to
// remove plugins that are incompatible.
- // Login and logout are for convenience.
+ // Logout for convenience.
// file/download (see #2010)
$exceptions = array(
'admin/plugins/disable',
'logout',
- 'login',
'file/download',
);
if (!in_array($action, $exceptions)) {
- // All actions require a token.
- action_gatekeeper();
+ action_gatekeeper($action);
}
$forwarder = str_replace(elgg_get_site_url(), "", $forwarder);
@@ -189,6 +187,26 @@ function elgg_unregister_action($action) {
}
/**
+ * Is the token timestamp within acceptable range?
+ *
+ * @param int $ts timestamp from the CSRF token
+ *
+ * @return bool
+ */
+function _elgg_validate_token_timestamp($ts) {
+ $action_token_timeout = elgg_get_config('action_token_timeout');
+ // default is 2 hours
+ $timeout = ($action_token_timeout !== null) ? $action_token_timeout : 2;
+
+ $hour = 60 * 60;
+ $timeout = $timeout * $hour;
+ $now = time();
+
+ // Validate time to ensure its not crazy
+ return ($timeout == 0 || ($ts > $now - $timeout) && ($ts < $now + $timeout));
+}
+
+/**
* Validate an action token.
*
* Calls to actions will automatically validate tokens. If tokens are not
@@ -206,8 +224,6 @@ function elgg_unregister_action($action) {
* @access private
*/
function validate_action_token($visibleerrors = TRUE, $token = NULL, $ts = NULL) {
- global $CONFIG;
-
if (!$token) {
$token = get_input('__elgg_token');
}
@@ -216,29 +232,18 @@ function validate_action_token($visibleerrors = TRUE, $token = NULL, $ts = NULL)
$ts = get_input('__elgg_ts');
}
- if (!isset($CONFIG->action_token_timeout)) {
- // default to 2 hours
- $timeout = 2;
- } else {
- $timeout = $CONFIG->action_token_timeout;
- }
-
$session_id = session_id();
if (($token) && ($ts) && ($session_id)) {
// generate token, check with input and forward if invalid
- $generated_token = generate_action_token($ts);
+ $required_token = generate_action_token($ts);
// Validate token
- if ($token == $generated_token) {
- $hour = 60 * 60;
- $timeout = $timeout * $hour;
- $now = time();
-
- // Validate time to ensure its not crazy
- if ($timeout == 0 || ($ts > $now - $timeout) && ($ts < $now + $timeout)) {
+ if ($token == $required_token) {
+
+ if (_elgg_validate_token_timestamp($ts)) {
// We have already got this far, so unless anything
- // else says something to the contry we assume we're ok
+ // else says something to the contrary we assume we're ok
$returnval = true;
$returnval = elgg_trigger_plugin_hook('action_gatekeeper:permissions:check', 'all', array(
@@ -252,10 +257,20 @@ function validate_action_token($visibleerrors = TRUE, $token = NULL, $ts = NULL)
register_error(elgg_echo('actiongatekeeper:pluginprevents'));
}
} else if ($visibleerrors) {
- register_error(elgg_echo('actiongatekeeper:timeerror'));
+ // this is necessary because of #5133
+ if (elgg_is_xhr()) {
+ register_error(elgg_echo('js:security:token_refresh_failed', array(elgg_get_site_url())));
+ } else {
+ register_error(elgg_echo('actiongatekeeper:timeerror'));
+ }
}
} else if ($visibleerrors) {
- register_error(elgg_echo('actiongatekeeper:tokeninvalid'));
+ // this is necessary because of #5133
+ if (elgg_is_xhr()) {
+ register_error(elgg_echo('js:security:token_refresh_failed', array(elgg_get_site_url())));
+ } else {
+ register_error(elgg_echo('actiongatekeeper:tokeninvalid'));
+ }
}
} else {
if (! empty($_SERVER['CONTENT_LENGTH']) && empty($_POST)) {
@@ -284,12 +299,33 @@ function validate_action_token($visibleerrors = TRUE, $token = NULL, $ts = NULL)
* This function verifies form input for security features (like a generated token),
* and forwards if they are invalid.
*
+ * @param string $action The action being performed
+ *
* @return mixed True if valid or redirects.
* @access private
*/
-function action_gatekeeper() {
- if (validate_action_token()) {
- return TRUE;
+function action_gatekeeper($action) {
+ if ($action === 'login') {
+ if (validate_action_token(false)) {
+ return true;
+ }
+
+ $token = get_input('__elgg_token');
+ $ts = (int)get_input('__elgg_ts');
+ if ($token && _elgg_validate_token_timestamp($ts)) {
+ // The tokens are present and the time looks valid: this is probably a mismatch due to the
+ // login form being on a different domain.
+ register_error(elgg_echo('actiongatekeeper:crosssitelogin'));
+
+
+ forward('login', 'csrf');
+ }
+
+ // let the validator send an appropriate msg
+ validate_action_token();
+
+ } elseif (validate_action_token()) {
+ return true;
}
forward(REFERER, 'csrf');
@@ -328,16 +364,19 @@ function generate_action_token($timestamp) {
}
/**
- * Initialise the site secret hash.
+ * Initialise the site secret (32 bytes: "z" to indicate format + 186-bit key in Base64 URL).
*
* Used during installation and saves as a datalist.
*
+ * Note: Old secrets were hex encoded.
+ *
* @return mixed The site secret hash or false
* @access private
* @todo Move to better file.
*/
function init_site_secret() {
- $secret = md5(rand() . microtime());
+ $secret = 'z' . ElggCrypto::getRandomString(31);
+
if (datalist_set('__site_secret__', $secret)) {
return $secret;
}
@@ -364,6 +403,26 @@ function get_site_secret() {
}
/**
+ * Get the strength of the site secret
+ *
+ * @return string "strong", "moderate", or "weak"
+ * @access private
+ */
+function _elgg_get_site_secret_strength() {
+ $secret = get_site_secret();
+ if ($secret[0] !== 'z') {
+ $rand_max = getrandmax();
+ if ($rand_max < pow(2, 16)) {
+ return 'weak';
+ }
+ if ($rand_max < pow(2, 32)) {
+ return 'moderate';
+ }
+ }
+ return 'strong';
+}
+
+/**
* Check if an action is registered and its script exists.
*
* @param string $action Action name
diff --git a/engine/lib/admin.php b/engine/lib/admin.php
index 35ab5599d..f36f29668 100644
--- a/engine/lib/admin.php
+++ b/engine/lib/admin.php
@@ -134,11 +134,11 @@ function elgg_delete_admin_notice($id) {
}
/**
- * List all admin messages.
+ * Get admin notices. An admin must be logged in since the notices are private.
*
* @param int $limit Limit
*
- * @return array List of admin notices
+ * @return array Array of admin notices
* @since 1.8.0
*/
function elgg_get_admin_notices($limit = 10) {
@@ -158,11 +158,13 @@ function elgg_get_admin_notices($limit = 10) {
* @since 1.8.0
*/
function elgg_admin_notice_exists($id) {
+ $old_ia = elgg_set_ignore_access(true);
$notice = elgg_get_entities_from_metadata(array(
'type' => 'object',
'subtype' => 'admin_notice',
'metadata_name_value_pair' => array('name' => 'admin_notice_id', 'value' => $id)
));
+ elgg_set_ignore_access($old_ia);
return ($notice) ? TRUE : FALSE;
}
@@ -234,6 +236,7 @@ function admin_init() {
elgg_register_action('admin/site/update_advanced', '', 'admin');
elgg_register_action('admin/site/flush_cache', '', 'admin');
elgg_register_action('admin/site/unlock_upgrade', '', 'admin');
+ elgg_register_action('admin/site/regenerate_secret', '', 'admin');
elgg_register_action('admin/menu/save', '', 'admin');
@@ -289,6 +292,7 @@ function admin_init() {
elgg_register_admin_menu_item('configure', 'settings', null, 100);
elgg_register_admin_menu_item('configure', 'basic', 'settings', 10);
elgg_register_admin_menu_item('configure', 'advanced', 'settings', 20);
+ elgg_register_admin_menu_item('configure', 'advanced/site_secret', 'settings', 25);
elgg_register_admin_menu_item('configure', 'menu_items', 'appearance', 30);
elgg_register_admin_menu_item('configure', 'profile_fields', 'appearance', 40);
// default widgets is added via an event handler elgg_default_widgets_init() in widgets.php
@@ -346,7 +350,7 @@ function elgg_admin_add_plugin_settings_menu() {
$active_plugins = elgg_get_plugins('active');
if (!$active_plugins) {
// nothing added because no items
- return FALSE;
+ return;
}
foreach ($active_plugins as $plugin) {
@@ -380,6 +384,7 @@ function elgg_admin_add_plugin_settings_menu() {
*/
function elgg_admin_sort_page_menu($hook, $type, $return, $params) {
$configure_items = $return['configure'];
+ /* @var ElggMenuItem[] $configure_items */
foreach ($configure_items as $menu_item) {
if ($menu_item->getName() == 'settings') {
$settings = $menu_item;
@@ -387,6 +392,7 @@ function elgg_admin_sort_page_menu($hook, $type, $return, $params) {
}
// keep the basic and advanced settings at the top
+ /* @var ElggMenuItem $settings */
$children = $settings->getChildren();
$site_settings = array_splice($children, 0, 2);
usort($children, array('ElggMenuBuilder', 'compareByText'));
@@ -466,14 +472,18 @@ function admin_page_handler($page) {
$vars = array('page' => $page);
// special page for plugin settings since we create the form for them
- if ($page[0] == 'plugin_settings' && isset($page[1]) &&
- (elgg_view_exists("settings/{$page[1]}/edit") || elgg_view_exists("plugins/{$page[1]}/settings"))) {
+ if ($page[0] == 'plugin_settings') {
+ if (isset($page[1]) && (elgg_view_exists("settings/{$page[1]}/edit") ||
+ elgg_view_exists("plugins/{$page[1]}/settings"))) {
- $view = 'admin/plugin_settings';
- $plugin = elgg_get_plugin_from_id($page[1]);
- $vars['plugin'] = $plugin;
+ $view = 'admin/plugin_settings';
+ $plugin = elgg_get_plugin_from_id($page[1]);
+ $vars['plugin'] = $plugin;
- $title = elgg_echo("admin:{$page[0]}");
+ $title = elgg_echo("admin:{$page[0]}");
+ } else {
+ forward('', '404');
+ }
} else {
$view = 'admin/' . implode('/', $page);
$title = elgg_echo("admin:{$page[0]}");
@@ -552,7 +562,7 @@ function admin_plugin_screenshot_page_handler($pages) {
* * COPYRIGHT.txt
* * LICENSE.txt
*
- * @param type $page
+ * @param array $pages
* @return bool
* @access private
*/
@@ -615,7 +625,11 @@ function admin_markdown_page_handler($pages) {
/**
* Adds default admin widgets to the admin dashboard.
*
- * @return void
+ * @param string $event
+ * @param string $type
+ * @param ElggUser $user
+ *
+ * @return null|true
* @access private
*/
function elgg_add_admin_widgets($event, $type, $user) {
@@ -637,6 +651,7 @@ function elgg_add_admin_widgets($event, $type, $user) {
$guid = elgg_create_widget($user->getGUID(), $handler, 'admin');
if ($guid) {
$widget = get_entity($guid);
+ /* @var ElggWidget $widget */
$widget->move($column, $position);
}
}
diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php
index 3b9f84703..5e9b530de 100644
--- a/engine/lib/annotations.php
+++ b/engine/lib/annotations.php
@@ -17,6 +17,7 @@
*/
function row_to_elggannotation($row) {
if (!($row instanceof stdClass)) {
+ // @todo should throw in this case?
return $row;
}
@@ -30,7 +31,7 @@ function row_to_elggannotation($row) {
*
* @param int $id The id of the annotation object being retrieved.
*
- * @return false|ElggAnnotation
+ * @return ElggAnnotation|false
*/
function elgg_get_annotation_from_id($id) {
return elgg_get_metastring_based_object_from_id($id, 'annotations');
@@ -195,10 +196,22 @@ function update_annotation($annotation_id, $name, $value, $value_type, $owner_gu
* for the proper use of the "calculation" option.
*
*
- * @return mixed
+ * @return ElggAnnotation[]|mixed
* @since 1.8.0
*/
function elgg_get_annotations(array $options = array()) {
+
+ // @todo remove support for count shortcut - see #4393
+ if (isset($options['__egefac']) && $options['__egefac']) {
+ unset($options['__egefac']);
+ } else {
+ // support shortcut of 'count' => true for 'annotation_calculation' => 'count'
+ if (isset($options['count']) && $options['count']) {
+ $options['annotation_calculation'] = 'count';
+ unset($options['count']);
+ }
+ }
+
$options['metastring_type'] = 'annotations';
return elgg_get_metastring_based_objects($options);
}
@@ -211,7 +224,7 @@ function elgg_get_annotations(array $options = array()) {
* annotation_name(s), annotation_value(s), or guid(s) must be set.
*
* @param array $options An options array. {@See elgg_get_annotations()}
- * @return mixed Null if the metadata name is invalid. Bool on success or fail.
+ * @return bool|null true on success, false on failure, null if no annotations to delete.
* @since 1.8.0
*/
function elgg_delete_annotations(array $options) {
@@ -229,16 +242,20 @@ function elgg_delete_annotations(array $options) {
* @warning Unlike elgg_get_annotations() this will not accept an empty options array!
*
* @param array $options An options array. {@See elgg_get_annotations()}
- * @return mixed
+ * @return bool|null true on success, false on failure, null if no annotations disabled.
* @since 1.8.0
*/
function elgg_disable_annotations(array $options) {
if (!elgg_is_valid_options_for_batch_operation($options, 'annotations')) {
return false;
}
+
+ // if we can see hidden (disabled) we need to use the offset
+ // otherwise we risk an infinite loop if there are more than 50
+ $inc_offset = access_get_show_hidden_status();
$options['metastring_type'] = 'annotations';
- return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', false);
+ return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', $inc_offset);
}
/**
@@ -246,8 +263,11 @@ function elgg_disable_annotations(array $options) {
*
* @warning Unlike elgg_get_annotations() this will not accept an empty options array!
*
+ * @warning In order to enable annotations, you must first use
+ * {@link access_show_hidden_entities()}.
+ *
* @param array $options An options array. {@See elgg_get_annotations()}
- * @return mixed
+ * @return bool|null true on success, false on failure, null if no metadata enabled.
* @since 1.8.0
*/
function elgg_enable_annotations(array $options) {
@@ -403,8 +423,8 @@ function elgg_list_entities_from_annotations($options = array()) {
function elgg_get_entities_from_annotation_calculation($options) {
$db_prefix = elgg_get_config('dbprefix');
$defaults = array(
- 'calculation' => 'sum',
- 'order_by' => 'annotation_calculation desc'
+ 'calculation' => 'sum',
+ 'order_by' => 'annotation_calculation desc'
);
$options = array_merge($defaults, $options);
@@ -424,6 +444,10 @@ function elgg_get_entities_from_annotation_calculation($options) {
$options['callback'] = 'entity_row_to_elggstar';
+ // see #4393
+ // @todo remove after the 'count' shortcut is removed from elgg_get_annotations()
+ $options['__egefac'] = true;
+
return elgg_get_annotations($options);
}
@@ -437,23 +461,30 @@ function elgg_get_entities_from_annotation_calculation($options) {
* @return string
*/
function elgg_list_entities_from_annotation_calculation($options) {
+ $defaults = array(
+ 'calculation' => 'sum',
+ 'order_by' => 'annotation_calculation desc'
+ );
+ $options = array_merge($defaults, $options);
+
return elgg_list_entities($options, 'elgg_get_entities_from_annotation_calculation');
}
/**
- * Handler called by trigger_plugin_hook on the "export" event.
+ * Export the annotations for the specified entity
*
* @param string $hook 'export'
- * @param string $entity_type 'all'
+ * @param string $type 'all'
* @param mixed $returnvalue Default return value
- * @param mixed $params List of params to export
+ * @param mixed $params Parameters determining what annotations to export
*
* @elgg_plugin_hook export all
*
- * @return mixed
+ * @return array
+ * @throws InvalidParameterException
* @access private
*/
-function export_annotation_plugin_hook($hook, $entity_type, $returnvalue, $params) {
+function export_annotation_plugin_hook($hook, $type, $returnvalue, $params) {
// Sanity check values
if ((!is_array($params)) && (!isset($params['guid']))) {
throw new InvalidParameterException(elgg_echo('InvalidParameterException:GUIDNotForExport'));
@@ -464,12 +495,12 @@ function export_annotation_plugin_hook($hook, $entity_type, $returnvalue, $param
}
$guid = (int)$params['guid'];
- $name = $params['name'];
+ $options = array('guid' => $guid, 'limit' => 0);
+ if (isset($params['name'])) {
+ $options['annotation_name'] = $params['name'];
+ }
- $result = elgg_get_annotations(array(
- 'guid' => $guid,
- 'limit' => 0
- ));
+ $result = elgg_get_annotations($options);
if ($result) {
foreach ($result as $r) {
@@ -514,15 +545,16 @@ function elgg_annotation_exists($entity_guid, $annotation_type, $owner_guid = NU
return FALSE;
}
- $entity_guid = (int)$entity_guid;
- $annotation_type = sanitise_string($annotation_type);
+ $entity_guid = sanitize_int($entity_guid);
+ $owner_guid = sanitize_int($owner_guid);
+ $annotation_type = sanitize_string($annotation_type);
- $sql = "select a.id" .
- " FROM {$CONFIG->dbprefix}annotations a, {$CONFIG->dbprefix}metastrings m " .
- " WHERE a.owner_guid={$owner_guid} AND a.entity_guid={$entity_guid} " .
- " AND a.name_id=m.id AND m.string='{$annotation_type}'";
+ $sql = "SELECT a.id FROM {$CONFIG->dbprefix}annotations a" .
+ " JOIN {$CONFIG->dbprefix}metastrings m ON a.name_id = m.id" .
+ " WHERE a.owner_guid = $owner_guid AND a.entity_guid = $entity_guid" .
+ " AND m.string = '$annotation_type'";
- if ($check_annotation = get_data_row($sql)) {
+ if (get_data_row($sql)) {
return TRUE;
}
@@ -541,6 +573,7 @@ function elgg_comment_url_handler(ElggAnnotation $comment) {
if ($entity) {
return $entity->getURL() . '#item-annotation-' . $comment->id;
}
+ return "";
}
/**
@@ -557,6 +590,12 @@ function elgg_register_annotation_url_handler($extender_name = "all", $function_
/**
* Register annotation unit tests
+ *
+ * @param string $hook
+ * @param string $type
+ * @param array $value
+ * @param array $params
+ * @return array
* @access private
*/
function annotations_test($hook, $type, $value, $params) {
diff --git a/engine/lib/cache.php b/engine/lib/cache.php
index be1c43e14..3116c1a9b 100644
--- a/engine/lib/cache.php
+++ b/engine/lib/cache.php
@@ -125,7 +125,7 @@ function elgg_get_filepath_cache() {
* @access private
*/
function elgg_filepath_cache_reset() {
- return elgg_reset_system_cache();
+ elgg_reset_system_cache();
}
/**
* @access private
@@ -143,13 +143,13 @@ function elgg_filepath_cache_load($type) {
* @access private
*/
function elgg_enable_filepath_cache() {
- return elgg_enable_system_cache();
+ elgg_enable_system_cache();
}
/**
* @access private
*/
function elgg_disable_filepath_cache() {
- return elgg_disable_system_cache();
+ elgg_disable_system_cache();
}
/* Simplecache */
@@ -208,6 +208,7 @@ function elgg_get_simplecache_url($type, $view) {
global $CONFIG;
$lastcache = (int)$CONFIG->lastcache;
$viewtype = elgg_get_viewtype();
+ elgg_register_simplecache_view("$type/$view");// see #5302
if (elgg_is_simplecache_enabled()) {
$url = elgg_get_site_url() . "cache/$type/$viewtype/$view.$lastcache.$type";
} else {
@@ -222,7 +223,7 @@ function elgg_get_simplecache_url($type, $view) {
/**
* Regenerates the simple cache.
*
- * @warning This does not invalidate the cache, but actively resets it.
+ * @warning This does not invalidate the cache, but actively rebuilds it.
*
* @param string $viewtype Optional viewtype to regenerate. Defaults to all valid viewtypes.
*
@@ -444,7 +445,7 @@ function _elgg_cache_init() {
if ($CONFIG->system_cache_enabled && !$CONFIG->i18n_loaded_from_cache) {
reload_all_translations();
foreach ($CONFIG->translations as $lang => $map) {
- elgg_save_system_cache("$lang.php", serialize($map));
+ elgg_save_system_cache("$lang.lang", serialize($map));
}
}
}
diff --git a/engine/lib/calendar.php b/engine/lib/calendar.php
index 9a06c5292..e6f95934c 100644
--- a/engine/lib/calendar.php
+++ b/engine/lib/calendar.php
@@ -39,6 +39,8 @@ function get_day_end($day = null, $month = null, $year = null) {
/**
* Return the notable entities for a given time period.
*
+ * @todo this function also accepts an array(type => subtypes) for 3rd arg. Should we document this?
+ *
* @param int $start_time The start time as a unix timestamp.
* @param int $end_time The end time as a unix timestamp.
* @param string $type The type of entity (eg "user", "object" etc)
diff --git a/engine/lib/configuration.php b/engine/lib/configuration.php
index b10e51130..55e5bbd36 100644
--- a/engine/lib/configuration.php
+++ b/engine/lib/configuration.php
@@ -36,6 +36,7 @@ function elgg_get_site_url($site_guid = 0) {
if (!$site instanceof ElggSite) {
return false;
}
+ /* @var ElggSite $site */
return $site->url;
}
@@ -138,7 +139,7 @@ function elgg_set_config($name, $value) {
/**
* Save a configuration setting
*
- * @param string $name Configuration name (cannot be greater than 32 characters)
+ * @param string $name Configuration name (cannot be greater than 255 characters)
* @param mixed $value Configuration value. Should be string for installation setting
* @param int $site_guid NULL for installation setting, 0 for default site
*
@@ -173,7 +174,7 @@ function elgg_save_config($name, $value, $site_guid = 0) {
/**
* Check that installation has completed and the database is populated.
*
- * @throws InstallationException
+ * @throws InstallationException|DatabaseException
* @return void
* @access private
*/
@@ -181,7 +182,7 @@ function verify_installation() {
global $CONFIG;
if (isset($CONFIG->installed)) {
- return $CONFIG->installed;
+ return;
}
try {
@@ -227,9 +228,9 @@ function datalist_get($name) {
$name = trim($name);
- // cannot store anything longer than 32 characters in db, so catch here
- if (elgg_strlen($name) > 32) {
- elgg_log("The name length for configuration variables cannot be greater than 32", "ERROR");
+ // cannot store anything longer than 255 characters in db, so catch here
+ if (elgg_strlen($name) > 255) {
+ elgg_log("The name length for configuration variables cannot be greater than 255", "ERROR");
return false;
}
@@ -286,7 +287,7 @@ function datalist_get($name) {
function datalist_set($name, $value) {
global $CONFIG, $DATALIST_CACHE;
- // cannot store anything longer than 32 characters in db, so catch before we set
+ // cannot store anything longer than 255 characters in db, so catch before we set
if (elgg_strlen($name) > 255) {
elgg_log("The name length for configuration variables cannot be greater than 255", "ERROR");
return false;
@@ -332,7 +333,7 @@ function datalist_set($name, $value) {
* This will cause the run once function to be run on all installations. To perform
* additional upgrades, create new functions for each release.
*
- * @warning The function name cannot be longer than 32 characters long due to
+ * @warning The function name cannot be longer than 255 characters long due to
* the current schema for the datalist table.
*
* @internal A datalist entry $functioname is created with the value of time().
@@ -407,7 +408,7 @@ function unset_config($name, $site_guid = 0) {
* @param string $value Its value
* @param int $site_guid Optionally, the GUID of the site (current site is assumed by default)
*
- * @return 0
+ * @return bool
* @todo The config table doens't have numeric primary keys so insert_data returns 0.
* @todo Use "INSERT ... ON DUPLICATE KEY UPDATE" instead of trying to delete then add.
* @see unset_config()
@@ -419,9 +420,9 @@ function set_config($name, $value, $site_guid = 0) {
$name = trim($name);
- // cannot store anything longer than 32 characters in db, so catch before we set
- if (elgg_strlen($name) > 32) {
- elgg_log("The name length for configuration variables cannot be greater than 32", "ERROR");
+ // cannot store anything longer than 255 characters in db, so catch before we set
+ if (elgg_strlen($name) > 255) {
+ elgg_log("The name length for configuration variables cannot be greater than 255", "ERROR");
return false;
}
@@ -485,9 +486,9 @@ function get_config($name, $site_guid = 0) {
// @todo these haven't really been implemented in Elgg 1.8. Complete in 1.9.
// show dep message
if ($new_name) {
- // $msg = "Config value $name has been renamed as $new_name";
+ // $msg = "Config value $name has been renamed as $new_name";
$name = $new_name;
- // elgg_deprecated_notice($msg, $dep_version);
+ // elgg_deprecated_notice($msg, $dep_version);
}
// decide from where to return the value
diff --git a/engine/lib/cron.php b/engine/lib/cron.php
index f7a032f4a..4f3d05b93 100644
--- a/engine/lib/cron.php
+++ b/engine/lib/cron.php
@@ -26,11 +26,10 @@ function cron_init() {
* @param array $page Pages
*
* @return bool
+ * @throws CronException
* @access private
*/
function cron_page_handler($page) {
- global $CONFIG;
-
if (!isset($page[0])) {
forward();
}
@@ -51,7 +50,6 @@ function cron_page_handler($page) {
$params['time'] = time();
// Data to return to
- $std_out = "";
$old_stdout = "";
ob_start();
diff --git a/engine/lib/database.php b/engine/lib/database.php
index 7d90b30b8..a7949788d 100644
--- a/engine/lib/database.php
+++ b/engine/lib/database.php
@@ -12,15 +12,19 @@
/**
* Query cache for all queries.
*
- * Each query and its results are stored in this array as:
+ * Each query and its results are stored in this cache as:
* <code>
- * $DB_QUERY_CACHE[$query] => array(result1, result2, ... resultN)
+ * $DB_QUERY_CACHE[query hash] => array(result1, result2, ... resultN)
* </code>
+ * @see elgg_query_runner() for details on the hash.
*
- * @global array $DB_QUERY_CACHE
+ * @warning Elgg used to set this as an empty array to turn off the cache
+ *
+ * @global ElggLRUCache|null $DB_QUERY_CACHE
+ * @access private
*/
global $DB_QUERY_CACHE;
-$DB_QUERY_CACHE = array();
+$DB_QUERY_CACHE = null;
/**
* Queries to be executed upon shutdown.
@@ -38,6 +42,7 @@ $DB_QUERY_CACHE = array();
* </code>
*
* @global array $DB_DELAYED_QUERIES
+ * @access private
*/
global $DB_DELAYED_QUERIES;
$DB_DELAYED_QUERIES = array();
@@ -48,7 +53,8 @@ $DB_DELAYED_QUERIES = array();
* Each database link created with establish_db_link($name) is stored in
* $dblink as $dblink[$name] => resource. Use get_db_link($name) to retrieve it.
*
- * @global array $dblink
+ * @global resource[] $dblink
+ * @access private
*/
global $dblink;
$dblink = array();
@@ -59,6 +65,7 @@ $dblink = array();
* Each call to the database increments this counter.
*
* @global integer $dbcalls
+ * @access private
*/
global $dbcalls;
$dbcalls = 0;
@@ -72,11 +79,12 @@ $dbcalls = 0;
* resource. eg "read", "write", or "readwrite".
*
* @return void
+ * @throws DatabaseException
* @access private
*/
function establish_db_link($dblinkname = "readwrite") {
// Get configuration, and globalise database link
- global $CONFIG, $dblink, $DB_QUERY_CACHE, $dbcalls;
+ global $CONFIG, $dblink, $DB_QUERY_CACHE;
if ($dblinkname != "readwrite" && isset($CONFIG->db[$dblinkname])) {
if (is_array($CONFIG->db[$dblinkname])) {
@@ -120,7 +128,8 @@ function establish_db_link($dblinkname = "readwrite") {
// Set up cache if global not initialized and query cache not turned off
if ((!$DB_QUERY_CACHE) && (!$db_cache_off)) {
- $DB_QUERY_CACHE = new ElggStaticVariableCache('db_query_cache');
+ // @todo if we keep this cache in 1.9, expose the size as a config parameter
+ $DB_QUERY_CACHE = new ElggLRUCache(200);
}
}
@@ -134,7 +143,7 @@ function establish_db_link($dblinkname = "readwrite") {
* @access private
*/
function setup_db_connections() {
- global $CONFIG, $dblink;
+ global $CONFIG;
if (!empty($CONFIG->db->split)) {
establish_db_link('read');
@@ -197,7 +206,7 @@ function db_delayedexecution_shutdown_hook() {
*
* @param string $dblinktype The type of link we want: "read", "write" or "readwrite".
*
- * @return object Database link
+ * @return resource Database link
* @access private
*/
function get_db_link($dblinktype) {
@@ -216,7 +225,7 @@ function get_db_link($dblinktype) {
/**
* Execute an EXPLAIN for $query.
*
- * @param str $query The query to explain
+ * @param string $query The query to explain
* @param mixed $link The database link resource to user.
*
* @return mixed An object of the query's result, or FALSE
@@ -240,14 +249,14 @@ function explain_query($query, $link) {
* {@link $dbcalls} is incremented and the query is saved into the {@link $DB_QUERY_CACHE}.
*
* @param string $query The query
- * @param link $dblink The DB link
+ * @param resource $dblink The DB link
*
- * @return The result of mysql_query()
+ * @return resource result of mysql_query()
* @throws DatabaseException
* @access private
*/
function execute_query($query, $dblink) {
- global $CONFIG, $dbcalls;
+ global $dbcalls;
if ($query == NULL) {
throw new DatabaseException(elgg_echo('DatabaseException:InvalidQuery'));
@@ -275,7 +284,7 @@ function execute_query($query, $dblink) {
* the raw result from {@link mysql_query()}.
*
* @param string $query The query to execute
- * @param resource $dblink The database link to use or the link type (read | write)
+ * @param resource|string $dblink The database link to use or the link type (read | write)
* @param string $handler A callback function to pass the results array to
*
* @return true
@@ -386,20 +395,18 @@ function get_data_row($query, $callback = "") {
* @access private
*/
function elgg_query_runner($query, $callback = null, $single = false) {
- global $CONFIG, $DB_QUERY_CACHE;
+ global $DB_QUERY_CACHE;
// Since we want to cache results of running the callback, we need to
// need to namespace the query with the callback and single result request.
- // http://trac.elgg.org/ticket/4049
+ // https://github.com/elgg/elgg/issues/4049
$hash = (string)$callback . (int)$single . $query;
// Is cached?
if ($DB_QUERY_CACHE) {
- $cached_query = $DB_QUERY_CACHE[$hash];
-
- if ($cached_query !== FALSE) {
+ if (isset($DB_QUERY_CACHE[$hash])) {
elgg_log("DB query $query results returned from cache (hash: $hash)", 'NOTICE');
- return $cached_query;
+ return $DB_QUERY_CACHE[$hash];
}
}
@@ -410,7 +417,7 @@ function elgg_query_runner($query, $callback = null, $single = false) {
// test for callback once instead of on each iteration.
// @todo check profiling to see if this needs to be broken out into
- // explicit cases instead of checking in the interation.
+ // explicit cases instead of checking in the iteration.
$is_callable = is_callable($callback);
while ($row = mysql_fetch_object($result)) {
if ($is_callable) {
@@ -451,18 +458,12 @@ function elgg_query_runner($query, $callback = null, $single = false) {
* @access private
*/
function insert_data($query) {
- global $CONFIG, $DB_QUERY_CACHE;
elgg_log("DB query $query", 'NOTICE');
$dblink = get_db_link('write');
- // Invalidate query cache
- if ($DB_QUERY_CACHE) {
- $DB_QUERY_CACHE->clear();
- }
-
- elgg_log("Query cache invalidated", 'NOTICE');
+ _elgg_invalidate_query_cache();
if (execute_query("$query", $dblink)) {
return mysql_insert_id($dblink);
@@ -472,7 +473,7 @@ function insert_data($query) {
}
/**
- * Update a row in the database.
+ * Update the database.
*
* @note Altering the DB invalidates all queries in {@link $DB_QUERY_CACHE}.
*
@@ -482,17 +483,12 @@ function insert_data($query) {
* @access private
*/
function update_data($query) {
- global $CONFIG, $DB_QUERY_CACHE;
elgg_log("DB query $query", 'NOTICE');
$dblink = get_db_link('write');
- // Invalidate query cache
- if ($DB_QUERY_CACHE) {
- $DB_QUERY_CACHE->clear();
- elgg_log("Query cache invalidated", 'NOTICE');
- }
+ _elgg_invalidate_query_cache();
if (execute_query("$query", $dblink)) {
return TRUE;
@@ -502,7 +498,7 @@ function update_data($query) {
}
/**
- * Remove a row from the database.
+ * Remove data from the database.
*
* @note Altering the DB invalidates all queries in {@link $DB_QUERY_CACHE}.
*
@@ -512,17 +508,12 @@ function update_data($query) {
* @access private
*/
function delete_data($query) {
- global $CONFIG, $DB_QUERY_CACHE;
elgg_log("DB query $query", 'NOTICE');
$dblink = get_db_link('write');
- // Invalidate query cache
- if ($DB_QUERY_CACHE) {
- $DB_QUERY_CACHE->clear();
- elgg_log("Query cache invalidated", 'NOTICE');
- }
+ _elgg_invalidate_query_cache();
if (execute_query("$query", $dblink)) {
return mysql_affected_rows($dblink);
@@ -531,6 +522,22 @@ function delete_data($query) {
return FALSE;
}
+/**
+ * Invalidate the query cache
+ *
+ * @access private
+ */
+function _elgg_invalidate_query_cache() {
+ global $DB_QUERY_CACHE;
+ if ($DB_QUERY_CACHE instanceof ElggLRUCache) {
+ $DB_QUERY_CACHE->clear();
+ elgg_log("Query cache invalidated", 'NOTICE');
+ } elseif ($DB_QUERY_CACHE) {
+ // In case someone sets the cache to an array and primes it with data
+ $DB_QUERY_CACHE = array();
+ elgg_log("Query cache invalidated", 'NOTICE');
+ }
+}
/**
* Return tables matching the database prefix {@link $CONFIG->dbprefix}% in the currently
@@ -638,7 +645,7 @@ function run_sql_script($scriptlocation) {
$statement = str_replace("prefix_", $CONFIG->dbprefix, $statement);
if (!empty($statement)) {
try {
- $result = update_data($statement);
+ update_data($statement);
} catch (DatabaseException $e) {
$errors[] = $e->getMessage();
}
@@ -661,7 +668,7 @@ function run_sql_script($scriptlocation) {
/**
* Format a query string for logging
- *
+ *
* @param string $query Query string
* @return string
* @access private
diff --git a/engine/lib/deprecated-1.7.php b/engine/lib/deprecated-1.7.php
index 519eea89d..ee95b5611 100644
--- a/engine/lib/deprecated-1.7.php
+++ b/engine/lib/deprecated-1.7.php
@@ -1137,6 +1137,7 @@ function make_register_object($register_name, $register_value, $children_array =
* @param int $guid GUID
*
* @return 1
+ * @deprecated 1.7
*/
function delete_object_entity($guid) {
system_message(elgg_echo('deprecatedfunction', array('delete_user_entity')));
@@ -1154,6 +1155,7 @@ function delete_object_entity($guid) {
* @param int $guid User GUID
*
* @return 1
+ * @deprecated 1.7
*/
function delete_user_entity($guid) {
system_message(elgg_echo('deprecatedfunction', array('delete_user_entity')));
diff --git a/engine/lib/deprecated-1.8.php b/engine/lib/deprecated-1.8.php
index 4b9d41543..91068d047 100644
--- a/engine/lib/deprecated-1.8.php
+++ b/engine/lib/deprecated-1.8.php
@@ -87,7 +87,7 @@ function list_entities_from_access_id($access_id, $entity_type = "", $entity_sub
elgg_deprecated_notice("All list_entities* functions were deprecated in 1.8. Use elgg_list_entities* instead.", 1.8);
echo elgg_list_entities_from_access_id(array('access_id' => $access_id,
- 'types' => $entity_type, 'subtypes' => $entity_subtype, 'owner_guids' => $owner_guid,
+ 'type' => $entity_type, 'subtype' => $entity_subtype, 'owner_guids' => $owner_guid,
'limit' => $limit, 'full_view' => $fullview, 'list_type_toggle' => $listtypetoggle,
'pagination' => $pagination,));
}
@@ -1314,8 +1314,8 @@ function list_entities_from_metadata($meta_name, $meta_value = "", $entity_type
$options = array(
'metadata_name' => $meta_name,
'metadata_value' => $meta_value,
- 'types' => $entity_type,
- 'subtypes' => $entity_subtype,
+ 'type' => $entity_type,
+ 'subtype' => $entity_subtype,
'limit' => $limit,
'offset' => $offset,
'count' => TRUE,
@@ -2120,8 +2120,8 @@ $fullview = true, $listtypetoggle = false, $pagination = true, $order_by = '') {
'relationship' => $relationship,
'relationship_guid' => $relationship_guid,
'inverse_relationship' => $inverse_relationship,
- 'types' => $type,
- 'subtypes' => $subtype,
+ 'type' => $type,
+ 'subtype' => $subtype,
'owner_guid' => $owner_guid,
'order_by' => $order_by,
'limit' => $limit,
@@ -2566,9 +2566,9 @@ $owner_guid = "", $owner_relationship = "") {
'relationship' => $owner_relationship,
'relationship_guid' => $owner_guid[0],
'inverse_relationship' => FALSE,
- 'types' => 'user',
- 'subtypes' => $subtype,
- 'limit' => 9999))
+ 'type' => 'user',
+ 'subtype' => $subtype,
+ 'limit' => false))
) {
$friendsarray = array();
@@ -2721,8 +2721,8 @@ function get_site_collections($site_guid, $subtype = "", $limit = 10, $offset =
'relationship' => 'member_of_site',
'relationship_guid' => $site_guid,
'inverse_relationship' => TRUE,
- 'types' => 'collection',
- 'subtypes' => $subtype,
+ 'type' => 'collection',
+ 'subtype' => $subtype,
'limit' => $limit,
'offset' => $offset
));
@@ -3414,6 +3414,7 @@ function list_annotations($entity_guid, $name = "", $limit = 25, $asc = true) {
* @param unknown_type $timeupper
* @param unknown_type $calculation
* @internal Don't use this at all.
+ * @deprecated 1.8 Use elgg_get_annotations()
*/
function elgg_deprecated_annotation_calculation($entity_guid = 0, $entity_type = "", $entity_subtype = "",
$name = "", $value = "", $value_type = "", $owner_guid = 0, $timelower = 0,
@@ -4667,6 +4668,7 @@ function display_widget(ElggObject $widget) {
*
* @param ElggEntity $entity
* @return int Number of comments
+ * @deprecated 1.8 Use ElggEntity->countComments()
*/
function elgg_count_comments($entity) {
elgg_deprecated_notice('elgg_count_comments() is deprecated by ElggEntity->countComments()', 1.8);
@@ -4772,3 +4774,47 @@ function default_page_handler($page, $handler) {
return FALSE;
}
+
+/**
+ * Invalidate this class's entry in the cache.
+ *
+ * @param int $guid The entity guid
+ *
+ * @return void
+ * @access private
+ * @deprecated 1.8
+ */
+function invalidate_cache_for_entity($guid) {
+ elgg_deprecated_notice('invalidate_cache_for_entity() is a private function and should not be used.', 1.8);
+ _elgg_invalidate_cache_for_entity($guid);
+}
+
+/**
+ * Cache an entity.
+ *
+ * Stores an entity in $ENTITY_CACHE;
+ *
+ * @param ElggEntity $entity Entity to cache
+ *
+ * @return void
+ * @access private
+ * @deprecated 1.8
+ */
+function cache_entity(ElggEntity $entity) {
+ elgg_deprecated_notice('cache_entity() is a private function and should not be used.', 1.8);
+ _elgg_cache_entity($entity);
+}
+
+/**
+ * Retrieve a entity from the cache.
+ *
+ * @param int $guid The guid
+ *
+ * @return ElggEntity|bool false if entity not cached, or not fully loaded
+ * @access private
+ * @deprecated 1.8
+ */
+function retrieve_cached_entity($guid) {
+ elgg_deprecated_notice('retrieve_cached_entity() is a private function and should not be used.', 1.8);
+ return _elgg_retrieve_cached_entity($guid);
+}
diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php
index 540605876..34111c69d 100644
--- a/engine/lib/elgglib.php
+++ b/engine/lib/elgglib.php
@@ -93,10 +93,17 @@ function elgg_register_library($name, $location) {
* @return void
* @throws InvalidParameterException
* @since 1.8.0
+ * @todo return boolean in 1.9 to indicate whether the library has been loaded
*/
function elgg_load_library($name) {
global $CONFIG;
+ static $loaded_libraries = array();
+
+ if (in_array($name, $loaded_libraries)) {
+ return;
+ }
+
if (!isset($CONFIG->libraries)) {
$CONFIG->libraries = array();
}
@@ -113,6 +120,8 @@ function elgg_load_library($name) {
);
throw new InvalidParameterException($error);
}
+
+ $loaded_libraries[] = $name;
}
/**
@@ -124,12 +133,11 @@ function elgg_load_library($name) {
* @param string $location URL to forward to browser to. Can be path relative to the network's URL.
* @param string $reason Short explanation for why we're forwarding
*
- * @return False False if headers have been sent. Terminates execution if forwarding.
+ * @return false False if headers have been sent. Terminates execution if forwarding.
+ * @throws SecurityException
*/
function forward($location = "", $reason = 'system') {
- global $CONFIG;
-
- if (!headers_sent()) {
+ if (!headers_sent($file, $line)) {
if ($location === REFERER) {
$location = $_SERVER['HTTP_REFERER'];
}
@@ -148,7 +156,7 @@ function forward($location = "", $reason = 'system') {
exit;
}
} else {
- throw new SecurityException(elgg_echo('SecurityException:ForwardFailedToRedirect'));
+ throw new SecurityException(elgg_echo('SecurityException:ForwardFailedToRedirect', array($file, $line)));
}
}
@@ -384,7 +392,7 @@ function elgg_load_external_file($type, $name) {
$item->url = '';
$item->location = '';
- $priority = $CONFIG->externals[$type]->add($item);
+ $CONFIG->externals[$type]->add($item);
$CONFIG->externals_map[$type][$name] = $item;
}
}
@@ -528,7 +536,7 @@ function sanitise_filepath($path, $append_slash = TRUE) {
* @param string $register Types of message: "error", "success" (default: success)
* @param bool $count Count the number of messages (default: false)
*
- * @return true|false|array Either the array of messages, or a response regarding
+ * @return bool|array Either the array of messages, or a response regarding
* whether the message addition was successful.
* @todo Clean up. Separate registering messages and retrieving them.
*/
@@ -562,7 +570,7 @@ function system_messages($message = null, $register = "success", $count = false)
return sizeof($_SESSION['msg'][$register]);
} else {
$count = 0;
- foreach ($_SESSION['msg'] as $register => $submessages) {
+ foreach ($_SESSION['msg'] as $submessages) {
$count += sizeof($submessages);
}
return $count;
@@ -738,7 +746,7 @@ function elgg_unregister_event_handler($event, $object_type, $callback) {
* @tip When referring to events, the preferred syntax is "event, type".
*
* @internal Only rarely should events be changed, added, or removed in core.
- * When making changes to events, be sure to first create a ticket in trac.
+ * When making changes to events, be sure to first create a ticket on Github.
*
* @internal @tip Think of $object_type as the primary namespace element, and
* $event as the secondary namespace.
@@ -839,7 +847,7 @@ function elgg_trigger_event($event, $object_type, $object = null) {
*
* @param string $hook The name of the hook
* @param string $type The type of the hook
- * @param callback $callback The name of a valid function or an array with object and method
+ * @param callable $callback The name of a valid function or an array with object and method
* @param int $priority The priority - 500 is default, lower numbers called first
*
* @return bool
@@ -885,7 +893,7 @@ function elgg_register_plugin_hook_handler($hook, $type, $callback, $priority =
*
* @param string $hook The name of the hook
* @param string $entity_type The name of the type of entity (eg "user", "object" etc)
- * @param callback $callback The PHP callback to be removed
+ * @param callable $callback The PHP callback to be removed
*
* @return void
* @since 1.8.0
@@ -1060,6 +1068,7 @@ function _elgg_php_exception_handler($exception) {
* @param array $vars An array that points to the active symbol table where error occurred
*
* @return true
+ * @throws Exception
* @access private
* @todo Replace error_log calls with elgg_log calls.
*/
@@ -1185,6 +1194,11 @@ function elgg_dump($value, $to_screen = TRUE, $level = 'NOTICE') {
$to_screen = FALSE;
}
+ // Do not want to write to JS or CSS pages
+ if (elgg_in_context('js') || elgg_in_context('css')) {
+ $to_screen = FALSE;
+ }
+
if ($to_screen == TRUE) {
echo '<pre>';
print_r($value);
@@ -1292,8 +1306,6 @@ function elgg_deprecated_notice($msg, $dep_version, $backtrace_level = 1) {
* @return string The current page URL.
*/
function current_page_url() {
- global $CONFIG;
-
$url = parse_url(elgg_get_site_url());
$page = $url['scheme'] . "://";
@@ -1338,7 +1350,7 @@ function full_url() {
"" : (":" . $_SERVER["SERVER_PORT"]);
// This is here to prevent XSS in poorly written browsers used by 80% of the population.
- // {@trac [5813]}
+ // https://github.com/Elgg/Elgg/commit/0c947e80f512cb0a482b1864fd0a6965c8a0cd4a
$quotes = array('\'', '"');
$encoded = array('%27', '%22');
@@ -1354,7 +1366,7 @@ function full_url() {
* @param array $parts Associative array of URL components like parse_url() returns
* @param bool $html_encode HTML Encode the url?
*
- * @return str Full URL
+ * @return string Full URL
* @since 1.7.0
*/
function elgg_http_build_url(array $parts, $html_encode = TRUE) {
@@ -1385,10 +1397,10 @@ function elgg_http_build_url(array $parts, $html_encode = TRUE) {
* add tokens to the action. The form view automatically handles
* tokens.
*
- * @param str $url Full action URL
- * @param bool $html_encode HTML encode the url? (default: false)
+ * @param string $url Full action URL
+ * @param bool $html_encode HTML encode the url? (default: false)
*
- * @return str URL with action tokens
+ * @return string URL with action tokens
* @since 1.7.0
* @link http://docs.elgg.org/Tutorials/Actions
*/
@@ -1440,17 +1452,17 @@ function elgg_http_remove_url_query_element($url, $element) {
}
$url_array['query'] = http_build_query($query);
- $string = elgg_http_build_url($url_array);
+ $string = elgg_http_build_url($url_array, false);
return $string;
}
/**
* Adds an element or elements to a URL's query string.
*
- * @param str $url The URL
- * @param array $elements Key/value pairs to add to the URL
+ * @param string $url The URL
+ * @param array $elements Key/value pairs to add to the URL
*
- * @return str The new URL with the query strings added
+ * @return string The new URL with the query strings added
* @since 1.7.0
*/
function elgg_http_add_url_query_elements($url, array $elements) {
@@ -1487,8 +1499,6 @@ function elgg_http_add_url_query_elements($url, array $elements) {
* @since 1.8.0
*/
function elgg_http_url_is_identical($url1, $url2, $ignore_params = array('offset', 'limit')) {
- global $CONFIG;
-
// if the server portion is missing but it starts with / then add the url in.
// @todo use elgg_normalize_url()
if (elgg_substr($url1, 0, 1) == '/') {
@@ -1627,7 +1637,7 @@ $sort_type = SORT_LOCALE_STRING) {
$sort = array();
- foreach ($array as $k => $v) {
+ foreach ($array as $v) {
if (isset($v[$element])) {
$sort[] = strtolower($v[$element]);
} else {
@@ -1646,7 +1656,7 @@ $sort_type = SORT_LOCALE_STRING) {
*
* @param string $ini_get_arg The INI setting
*
- * @return true|false Depending on whether it's on or off
+ * @return bool Depending on whether it's on or off
*/
function ini_get_bool($ini_get_arg) {
$temp = strtolower(ini_get($ini_get_arg));
@@ -1662,7 +1672,7 @@ function ini_get_bool($ini_get_arg) {
*
* @tip Use this for arithmetic when determining if a file can be uploaded.
*
- * @param str $setting The php.ini setting
+ * @param string $setting The php.ini setting
*
* @return int
* @since 1.7.0
@@ -1677,8 +1687,10 @@ function elgg_get_ini_setting_in_bytes($setting) {
switch($last) {
case 'g':
$val *= 1024;
+ // fallthrough intentional
case 'm':
$val *= 1024;
+ // fallthrough intentional
case 'k':
$val *= 1024;
}
@@ -1835,7 +1847,7 @@ function elgg_ajax_page_handler($page) {
*
* @param array $page The page array
*
- * @return void
+ * @return bool
* @elgg_pagehandler css
* @access private
*/
@@ -1899,6 +1911,7 @@ function elgg_cacheable_view_page_handler($page, $type) {
echo $return;
return true;
}
+ return false;
}
/**
@@ -2220,7 +2233,7 @@ function elgg_init() {
* @param array $params empty
*
* @elgg_plugin_hook unit_tests system
- * @return void
+ * @return array
* @access private
*/
function elgg_api_test($hook, $type, $value, $params) {
@@ -2232,7 +2245,10 @@ function elgg_api_test($hook, $type, $value, $params) {
}
/**#@+
- * Controlls access levels on ElggEntity entities, metadata, and annotations.
+ * Controls access levels on ElggEntity entities, metadata, and annotations.
+ *
+ * @warning ACCESS_DEFAULT is a place holder for the input/access view. Do not
+ * use it when saving an entity.
*
* @var int
*/
@@ -2266,7 +2282,7 @@ define('ELGG_ENTITIES_NO_VALUE', 0);
* referring page.
*
* @see forward
- * @var unknown_type
+ * @var int -1
*/
define('REFERRER', -1);
diff --git a/engine/lib/entities.php b/engine/lib/entities.php
index ce736ce05..4fcf1c657 100644
--- a/engine/lib/entities.php
+++ b/engine/lib/entities.php
@@ -17,6 +17,15 @@ global $ENTITY_CACHE;
$ENTITY_CACHE = array();
/**
+ * GUIDs of entities banned from the entity cache (during this request)
+ *
+ * @global array $ENTITY_CACHE_DISABLED_GUIDS
+ * @access private
+ */
+global $ENTITY_CACHE_DISABLED_GUIDS;
+$ENTITY_CACHE_DISABLED_GUIDS = array();
+
+/**
* Cache subtypes and related class names.
*
* @global array|null $SUBTYPE_CACHE array once populated from DB, initially null
@@ -26,14 +35,42 @@ global $SUBTYPE_CACHE;
$SUBTYPE_CACHE = null;
/**
+ * 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 null
+ * @return void
* @access private
*/
-function invalidate_cache_for_entity($guid) {
+function _elgg_invalidate_cache_for_entity($guid) {
global $ENTITY_CACHE;
$guid = (int)$guid;
@@ -50,14 +87,14 @@ function invalidate_cache_for_entity($guid) {
*
* @param ElggEntity $entity Entity to cache
*
- * @return null
- * @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(evan): Use an ElggCache object
+ * @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;
// 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.
@@ -65,8 +102,13 @@ function cache_entity(ElggEntity $entity) {
return;
}
+ $guid = $entity->getGUID();
+ if (isset($ENTITY_CACHE_DISABLED_GUIDS[$guid])) {
+ return;
+ }
+
// Don't store too many or we'll have memory problems
- // TODO(evan): Pick a less arbitrary limit
+ // @todo Pick a less arbitrary limit
if (count($ENTITY_CACHE) > 256) {
$random_guid = array_rand($ENTITY_CACHE);
@@ -79,7 +121,7 @@ function cache_entity(ElggEntity $entity) {
elgg_get_metadata_cache()->clear($random_guid);
}
- $ENTITY_CACHE[$entity->guid] = $entity;
+ $ENTITY_CACHE[$guid] = $entity;
}
/**
@@ -88,11 +130,11 @@ function cache_entity(ElggEntity $entity) {
* @param int $guid The guid
*
* @return ElggEntity|bool false if entity not cached, or not fully loaded
- * @see cache_entity()
- * @see invalidate_cache_for_entity()
+ * @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;
if (isset($ENTITY_CACHE[$guid])) {
@@ -105,31 +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
- *
- * @return mixed
- * @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
@@ -432,7 +449,7 @@ function update_subtype($type, $subtype, $class = '') {
* @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, $time_created = null) {
@@ -455,6 +472,10 @@ function update_entity($guid, $owner_guid, $access_id, $container_guid = null, $
$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 (elgg_trigger_event('update', $entity->type, $entity)) {
$ret = update_data("UPDATE {$CONFIG->dbprefix}entities
@@ -531,6 +552,7 @@ function can_write_to_container($user_guid = 0, $container_guid = 0, $type = 'al
// 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;
}
@@ -580,7 +602,6 @@ $container_guid = 0) {
$type = sanitise_string($type);
$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;
@@ -589,6 +610,10 @@ $container_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_guid = elgg_get_logged_in_user_guid();
if (!can_write_to_container($user_guid, $owner_guid, $type, $subtype)) {
@@ -736,7 +761,7 @@ function get_entity($guid) {
// @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 },
+ // 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') {
@@ -744,7 +769,7 @@ function get_entity($guid) {
}
// Check local cache first
- $new_entity = retrieve_cached_entity($guid);
+ $new_entity = _elgg_retrieve_cached_entity($guid);
if ($new_entity) {
return $new_entity;
}
@@ -766,7 +791,7 @@ function get_entity($guid) {
if ($shared_cache) {
$cached_entity = $shared_cache->load($guid);
- // @todo store ACLs in memcache http://trac.elgg.org/ticket/3018#comment:3
+ // @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;
@@ -781,7 +806,7 @@ function get_entity($guid) {
}
if ($new_entity) {
- cache_entity($new_entity);
+ _elgg_cache_entity($new_entity);
}
return $new_entity;
}
@@ -908,6 +933,8 @@ function elgg_get_entities(array $options = array()) {
'joins' => array(),
'callback' => 'entity_row_to_elggstar',
+
+ '__ElggBatch' => null,
);
$options = array_merge($defaults, $options);
@@ -1025,7 +1052,7 @@ function elgg_get_entities(array $options = array()) {
}
if ($options['callback'] === 'entity_row_to_elggstar') {
- $dt = _elgg_fetch_entities_from_sql($query);
+ $dt = _elgg_fetch_entities_from_sql($query, $options['__ElggBatch']);
} else {
$dt = get_data($query, $options['callback']);
}
@@ -1036,7 +1063,7 @@ function elgg_get_entities(array $options = 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);
+ _elgg_cache_entity($item);
// plugins usually have only settings
if (!$item instanceof ElggPlugin) {
$guids[] = $item->guid;
@@ -1060,13 +1087,14 @@ function elgg_get_entities(array $options = array()) {
/**
* Return entities from an SQL query generated by elgg_get_entities.
*
- * @param string $sql
+ * @param string $sql
+ * @param ElggBatch $batch
* @return ElggEntity[]
*
* @access private
* @throws LogicException
*/
-function _elgg_fetch_entities_from_sql($sql) {
+function _elgg_fetch_entities_from_sql($sql, ElggBatch $batch = null) {
static $plugin_subtype;
if (null === $plugin_subtype) {
$plugin_subtype = get_subtype_id('object', 'plugin');
@@ -1101,7 +1129,7 @@ function _elgg_fetch_entities_from_sql($sql) {
if (empty($row->guid) || empty($row->type)) {
throw new LogicException('Entity row missing guid or type');
}
- if ($entity = retrieve_cached_entity($row->guid)) {
+ if ($entity = _elgg_retrieve_cached_entity($row->guid)) {
$rows[$i] = $entity;
continue;
}
@@ -1119,16 +1147,17 @@ function _elgg_fetch_entities_from_sql($sql) {
// 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);
+
+ 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);
+ }
}
}
}
@@ -1142,6 +1171,11 @@ function _elgg_fetch_entities_from_sql($sql) {
} 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);
+ }
}
}
}
@@ -1217,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!", 'NOTICE');
+ // 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;
+ }
}
}
@@ -1428,8 +1473,10 @@ function elgg_list_entities(array $options = array(), $getter = 'elgg_get_entiti
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,
'list_type_toggle' => FALSE,
@@ -1459,11 +1506,13 @@ function elgg_list_entities(array $options = array(), $getter = 'elgg_get_entiti
*
* @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 $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
*
@@ -1613,7 +1662,7 @@ function disable_entity($guid, $reason = "", $recursive = true) {
$entity->disableMetadata();
$entity->disableAnnotations();
- invalidate_cache_for_entity($guid);
+ _elgg_invalidate_cache_for_entity($guid);
$res = update_data("UPDATE {$CONFIG->dbprefix}entities
SET enabled = 'no'
@@ -1629,8 +1678,8 @@ 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?
@@ -1711,7 +1760,7 @@ function delete_entity($guid, $recursive = true) {
// 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
@@ -1758,6 +1807,10 @@ function delete_entity($guid, $recursive = true) {
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->deleteMetadata();
$entity->deleteOwnedMetadata();
@@ -1765,6 +1818,9 @@ function delete_entity($guid, $recursive = true) {
$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);
@@ -2072,7 +2128,7 @@ function can_edit_entity_metadata($entity_guid, $user_guid = 0, $metadata = null
$return = null;
- if ($metadata->owner_guid == 0) {
+ if ($metadata && ($metadata->owner_guid == 0)) {
$return = true;
}
if (is_null($return)) {
@@ -2413,6 +2469,7 @@ function elgg_instanceof($entity, $type = NULL, $subtype = NULL, $class = NULL)
$return = ($entity instanceof ElggEntity);
if ($type) {
+ /* @var ElggEntity $entity */
$return = $return && ($entity->getType() == $type);
}
@@ -2472,11 +2529,18 @@ function update_entity_last_action($guid, $posted = NULL) {
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})");
}
}
diff --git a/engine/lib/export.php b/engine/lib/export.php
index ae9be95ce..ecc894e63 100644
--- a/engine/lib/export.php
+++ b/engine/lib/export.php
@@ -11,7 +11,7 @@
*
* @param mixed $object The object either an ElggEntity, ElggRelationship or ElggExtender
*
- * @return the UUID or false
+ * @return string|false the UUID or false
*/
function get_uuid_from_object($object) {
if ($object instanceof ElggEntity) {
@@ -40,8 +40,6 @@ function get_uuid_from_object($object) {
* @return string
*/
function guid_to_uuid($guid) {
- global $CONFIG;
-
return elgg_get_site_url() . "export/opendd/$guid/";
}
@@ -53,8 +51,6 @@ function guid_to_uuid($guid) {
* @return bool
*/
function is_uuid_this_domain($uuid) {
- global $CONFIG;
-
if (strpos($uuid, elgg_get_site_url()) === 0) {
return true;
}
@@ -67,7 +63,7 @@ function is_uuid_this_domain($uuid) {
*
* @param string $uuid A unique ID
*
- * @return mixed
+ * @return ElggEntity|false
*/
function get_entity_from_uuid($uuid) {
$uuid = sanitise_string($uuid);
@@ -117,18 +113,19 @@ function _process_element(ODD $odd) {
global $IMPORTED_DATA, $IMPORTED_OBJECT_COUNTER;
// See if anyone handles this element, return true if it is.
+ $to_be_serialised = null;
if ($odd) {
$handled = elgg_trigger_plugin_hook("import", "all", array("element" => $odd), $to_be_serialised);
- }
- // If not, then see if any of its sub elements are handled
- if ($handled) {
- // Increment validation counter
- $IMPORTED_OBJECT_COUNTER ++;
- // Return the constructed object
- $IMPORTED_DATA[] = $handled;
+ // If not, then see if any of its sub elements are handled
+ if ($handled) {
+ // Increment validation counter
+ $IMPORTED_OBJECT_COUNTER ++;
+ // Return the constructed object
+ $IMPORTED_DATA[] = $handled;
- return true;
+ return true;
+ }
}
return false;
@@ -167,7 +164,7 @@ function exportAsArray($guid) {
*
* @param int $guid The GUID.
*
- * @return xml
+ * @return string XML
* @see ElggEntity for an example of its usage.
* @access private
*/
@@ -184,7 +181,7 @@ function export($guid) {
* @param string $xml XML string
*
* @return bool
- * @throws Exception if there was a problem importing the data.
+ * @throws ImportException if there was a problem importing the data.
* @access private
*/
function import($xml) {
diff --git a/engine/lib/extender.php b/engine/lib/extender.php
index 538f601e1..8323bd3ce 100644
--- a/engine/lib/extender.php
+++ b/engine/lib/extender.php
@@ -86,6 +86,7 @@ function oddmetadata_to_elggextender(ElggEntity $entity, ODDMetaData $element) {
* @return null
* @elgg_plugin_hook_handler volatile metadata
* @todo investigate more.
+ * @throws ImportException
* @access private
*/
function import_extender_plugin_hook($hook, $entity_type, $returnvalue, $params) {
@@ -94,6 +95,7 @@ function import_extender_plugin_hook($hook, $entity_type, $returnvalue, $params)
$tmp = NULL;
if ($element instanceof ODDMetaData) {
+ /* @var ODDMetaData $element */
// Recall entity
$entity_uuid = $element->getAttribute('entity_uuid');
$entity = get_entity_from_uuid($entity_uuid);
@@ -124,14 +126,20 @@ function import_extender_plugin_hook($hook, $entity_type, $returnvalue, $params)
* @return bool
*/
function can_edit_extender($extender_id, $type, $user_guid = 0) {
- if (!elgg_is_logged_in()) {
- return false;
+ // @todo Since Elgg 1.0, Elgg has returned false from can_edit_extender()
+ // if no user was logged in. This breaks the access override. This is a
+ // temporary work around. This function needs to be rewritten in Elgg 1.9
+ if (!elgg_check_access_overrides($user_guid)) {
+ if (!elgg_is_logged_in()) {
+ return false;
+ }
}
$user_guid = (int)$user_guid;
- $user = get_entity($user_guid);
+ $user = get_user($user_guid);
if (!$user) {
$user = elgg_get_logged_in_user_entity();
+ $user_guid = elgg_get_logged_in_user_guid();
}
$functionname = "elgg_get_{$type}_from_id";
@@ -147,16 +155,16 @@ function can_edit_extender($extender_id, $type, $user_guid = 0) {
/* @var ElggExtender $extender */
// If the owner is the specified user, great! They can edit.
- if ($extender->getOwnerGUID() == $user->getGUID()) {
+ if ($extender->getOwnerGUID() == $user_guid) {
return true;
}
// If the user can edit the entity this is attached to, great! They can edit.
- if (can_edit_entity($extender->entity_guid, $user->getGUID())) {
+ if (can_edit_entity($extender->entity_guid, $user_guid)) {
return true;
}
- // Trigger plugin hooks
+ // Trigger plugin hook - note that $user may be null
$params = array('entity' => $extender->getEntity(), 'user' => $user);
return elgg_trigger_plugin_hook('permissions_check', $type, $params, false);
}
diff --git a/engine/lib/filestore.php b/engine/lib/filestore.php
index 93a127257..a3c7ba439 100644
--- a/engine/lib/filestore.php
+++ b/engine/lib/filestore.php
@@ -308,8 +308,6 @@ function get_image_resize_parameters($width, $height, $options) {
function file_delete($guid) {
if ($file = get_entity($guid)) {
if ($file->canEdit()) {
- $container = get_entity($file->container_guid);
-
$thumbnail = $file->thumbnail;
$smallthumb = $file->smallthumb;
$largethumb = $file->largethumb;
@@ -383,7 +381,7 @@ function file_get_general_file_type($mimetype) {
/**
* Delete a directory and all its contents
*
- * @param str $directory Directory to delete
+ * @param string $directory Directory to delete
*
* @return bool
*/
@@ -500,7 +498,7 @@ function filestore_init() {
/**
* Unit tests for files
*
- * @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/group.php b/engine/lib/group.php
index 5a38e1ea6..6ded8a825 100644
--- a/engine/lib/group.php
+++ b/engine/lib/group.php
@@ -170,7 +170,7 @@ function get_group_members($group_guid, $limit = 10, $offset = 0, $site_guid = 0
'relationship' => 'member',
'relationship_guid' => $group_guid,
'inverse_relationship' => TRUE,
- 'types' => 'user',
+ 'type' => 'user',
'limit' => $limit,
'offset' => $offset,
'count' => $count,
@@ -240,9 +240,11 @@ function leave_group($group_guid, $user_guid) {
*/
function get_users_membership($user_guid) {
$options = array(
+ 'type' => 'group',
'relationship' => 'member',
'relationship_guid' => $user_guid,
- 'inverse_relationship' => FALSE
+ 'inverse_relationship' => false,
+ 'limit' => false,
);
return elgg_get_entities_from_relationship($options);
}
diff --git a/engine/lib/input.php b/engine/lib/input.php
index 6d1646e1a..80b0b8766 100644
--- a/engine/lib/input.php
+++ b/engine/lib/input.php
@@ -60,8 +60,8 @@ function get_input($variable, $default = NULL, $filter_result = TRUE) {
*
* Note: this function does not handle nested arrays (ex: form input of param[m][n])
*
- * @param string $variable The name of the variable
- * @param string $value The value of the variable
+ * @param string $variable The name of the variable
+ * @param string|string[] $value The value of the variable
*
* @return void
*/
@@ -226,6 +226,8 @@ function elgg_clear_sticky_value($form_name, $variable) {
/**
* Page handler for autocomplete endpoint.
*
+ * @todo split this into functions/objects, this is way too big
+ *
* /livesearch?q=<query>
*
* Other options include:
@@ -233,6 +235,7 @@ function elgg_clear_sticky_value($form_name, $variable) {
* match_owner int 0/1
* limit int default is 10
*
+ * @param array $page
* @return string JSON string is returned and then exit
* @access private
*/
@@ -265,10 +268,8 @@ function input_livesearch_page_handler($page) {
}
if (get_input('match_owner', false)) {
- $owner_guid = $user->getGUID();
$owner_where = 'AND e.owner_guid = ' . $user->getGUID();
} else {
- $owner_guid = null;
$owner_where = '';
}
@@ -289,7 +290,9 @@ function input_livesearch_page_handler($page) {
if ($entities = get_data($query)) {
foreach ($entities as $entity) {
+ // @todo use elgg_get_entities (don't query in a loop!)
$entity = get_entity($entity->guid);
+ /* @var ElggUser $entity */
if (!$entity) {
continue;
}
@@ -338,7 +341,9 @@ function input_livesearch_page_handler($page) {
";
if ($entities = get_data($query)) {
foreach ($entities as $entity) {
+ // @todo use elgg_get_entities (don't query in a loop!)
$entity = get_entity($entity->guid);
+ /* @var ElggGroup $entity */
if (!$entity) {
continue;
}
@@ -385,7 +390,9 @@ function input_livesearch_page_handler($page) {
if ($entities = get_data($query)) {
foreach ($entities as $entity) {
+ // @todo use elgg_get_entities (don't query in a loop!)
$entity = get_entity($entity->guid);
+ /* @var ElggUser $entity */
if (!$entity) {
continue;
}
diff --git a/engine/lib/languages.php b/engine/lib/languages.php
index 98006f7cd..61ba91ddb 100644
--- a/engine/lib/languages.php
+++ b/engine/lib/languages.php
@@ -77,7 +77,7 @@ function elgg_echo($message_key, $args = array(), $language = "") {
* @param string $country_code Standard country code (eg 'en', 'nl', 'es')
* @param array $language_array Formatted array of strings
*
- * @return true|false Depending on success
+ * @return bool Depending on success
*/
function add_translation($country_code, $language_array) {
global $CONFIG;
@@ -104,8 +104,6 @@ function add_translation($country_code, $language_array) {
* @return string The language code for the site/user or "en" if not set
*/
function get_current_language() {
- global $CONFIG;
-
$language = get_language();
if (!$language) {
@@ -141,6 +139,9 @@ function get_language() {
return false;
}
+/**
+ * @access private
+ */
function _elgg_load_translations() {
global $CONFIG;
@@ -148,7 +149,7 @@ function _elgg_load_translations() {
$loaded = true;
$languages = array_unique(array('en', get_current_language()));
foreach ($languages as $language) {
- $data = elgg_load_system_cache("$language.php");
+ $data = elgg_load_system_cache("$language.lang");
if ($data) {
add_translation($language, unserialize($data));
} else {
@@ -177,7 +178,7 @@ function _elgg_load_translations() {
* @param bool $load_all If true all languages are loaded, if
* false only the current language + en are loaded
*
- * @return void
+ * @return bool success
*/
function register_translations($path, $load_all = false) {
global $CONFIG;
@@ -229,23 +230,37 @@ function register_translations($path, $load_all = false) {
/**
* Reload all translations from all registered paths.
*
- * This is only called by functions which need to know all possible translations, namely the
- * statistic gathering ones.
+ * This is only called by functions which need to know all possible translations.
*
* @todo Better on demand loading based on language_paths array
*
- * @return bool
+ * @return void
*/
function reload_all_translations() {
global $CONFIG;
static $LANG_RELOAD_ALL_RUN;
if ($LANG_RELOAD_ALL_RUN) {
- return null;
+ return;
}
- foreach ($CONFIG->language_paths as $path => $dummy) {
- register_translations($path, true);
+ if ($CONFIG->i18n_loaded_from_cache) {
+ $cache = elgg_get_system_cache();
+ $cache_dir = $cache->getVariable("cache_path");
+ $filenames = elgg_get_file_list($cache_dir, array(), array(), array(".lang"));
+ foreach ($filenames as $filename) {
+ if (preg_match('/([a-z]+)\.[^.]+$/', $filename, $matches)) {
+ $language = $matches[1];
+ $data = elgg_load_system_cache("$language.lang");
+ if ($data) {
+ add_translation($language, unserialize($data));
+ }
+ }
+ }
+ } else {
+ foreach ($CONFIG->language_paths as $path => $dummy) {
+ register_translations($path, true);
+ }
}
$LANG_RELOAD_ALL_RUN = true;
@@ -337,14 +352,3 @@ function get_missing_language_keys($language) {
return false;
}
-
-/**
- * Initialize the language library
- * @access private
- */
-function elgg_languages_init() {
- $lang = get_current_language();
- elgg_register_simplecache_view("js/languages/$lang");
-}
-
-elgg_register_event_handler('init', 'system', 'elgg_languages_init');
diff --git a/engine/lib/location.php b/engine/lib/location.php
index 5b889509b..1534c7d7b 100644
--- a/engine/lib/location.php
+++ b/engine/lib/location.php
@@ -101,7 +101,7 @@ function elgg_get_entities_from_location(array $options = array()) {
$long_min = $long - $long_distance;
$long_max = $long + $long_distance;
- $where = array();
+ $wheres = array();
$wheres[] = "lat_name.string='geo:lat'";
$wheres[] = "lat_value.string >= $lat_min";
$wheres[] = "lat_value.string <= $lat_max";
@@ -139,7 +139,7 @@ function elgg_get_entities_from_location(array $options = array()) {
/**
* Returns a viewable list of entities from location
*
- * @param array $options
+ * @param array $options Options array
*
* @see elgg_list_entities()
* @see elgg_get_entities_from_location()
diff --git a/engine/lib/mb_wrapper.php b/engine/lib/mb_wrapper.php
index c2f5503e0..68fa69005 100644
--- a/engine/lib/mb_wrapper.php
+++ b/engine/lib/mb_wrapper.php
@@ -11,7 +11,7 @@ if (is_callable('mb_internal_encoding')) {
* NOTE: This differs from parse_str() by returning the results
* instead of placing them in the local scope!
*
- * @param str $str The string
+ * @param string $str The string
*
* @return array
* @since 1.7.0
diff --git a/engine/lib/memcache.php b/engine/lib/memcache.php
index f79fba4a9..79b87e850 100644
--- a/engine/lib/memcache.php
+++ b/engine/lib/memcache.php
@@ -35,3 +35,23 @@ function is_memcache_available() {
return $memcache_available;
}
+
+/**
+ * Invalidate an entity in memcache
+ *
+ * @param int $entity_guid The GUID of the entity to invalidate
+ *
+ * @return void
+ * @access private
+ */
+function _elgg_invalidate_memcache_for_entity($entity_guid) {
+ static $newentity_cache;
+
+ if ((!$newentity_cache) && (is_memcache_available())) {
+ $newentity_cache = new ElggMemcache('new_entity_cache');
+ }
+
+ if ($newentity_cache) {
+ $newentity_cache->delete($entity_guid);
+ }
+} \ No newline at end of file
diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php
index f76c20f24..fdb1b85f6 100644
--- a/engine/lib/metadata.php
+++ b/engine/lib/metadata.php
@@ -191,19 +191,19 @@ function update_metadata($id, $name, $value, $value_type, $owner_guid, $access_i
}
// Add the metastring
- $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 = "UPDATE {$CONFIG->dbprefix}metadata"
- . " set name_id='$name', value_id='$value', value_type='$value_type', access_id=$access_id,"
+ . " set name_id='$name_id', value_id='$value_id', value_type='$value_type', access_id=$access_id,"
. " owner_guid=$owner_guid where id=$id";
$result = update_data($query);
@@ -277,10 +277,18 @@ $access_id = ACCESS_PRIVATE, $allow_multiple = false) {
* all metadata that match the query instead of returning
* ElggMetadata objects.
*
- * @return mixed
+ * @return ElggMetadata[]|mixed
* @since 1.8.0
*/
function elgg_get_metadata(array $options = array()) {
+
+ // @todo remove support for count shortcut - see #4393
+ // support shortcut of 'count' => true for 'metadata_calculation' => 'count'
+ if (isset($options['count']) && $options['count']) {
+ $options['metadata_calculation'] = 'count';
+ unset($options['count']);
+ }
+
$options['metastring_type'] = 'metadata';
return elgg_get_metastring_based_objects($options);
}
@@ -292,21 +300,22 @@ function elgg_get_metadata(array $options = array()) {
* This requires at least one constraint: metadata_owner_guid(s),
* metadata_name(s), metadata_value(s), or guid(s) must be set.
*
- * @warning This returns null on no ops.
- *
* @param array $options An options array. {@see elgg_get_metadata()}
- * @return mixed Null if the metadata name is invalid. Bool on success or fail.
+ * @return bool|null true on success, false on failure, null if no metadata to delete.
* @since 1.8.0
*/
function elgg_delete_metadata(array $options) {
if (!elgg_is_valid_options_for_batch_operation($options, 'metadata')) {
return false;
}
+ $options['metastring_type'] = 'metadata';
+ $result = elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback', false);
+ // This moved last in case an object's constructor sets metadata. Currently the batch
+ // delete process has to create the entity to delete its metadata. See #5214
elgg_get_metadata_cache()->invalidateByOptions('delete', $options);
- $options['metastring_type'] = 'metadata';
- return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback', false);
+ return $result;
}
/**
@@ -314,10 +323,8 @@ function elgg_delete_metadata(array $options) {
*
* @warning Unlike elgg_get_metadata() this will not accept an empty options array!
*
- * @warning This returns null on no ops.
- *
* @param array $options An options array. {@See elgg_get_metadata()}
- * @return mixed
+ * @return bool|null true on success, false on failure, null if no metadata disabled.
* @since 1.8.0
*/
function elgg_disable_metadata(array $options) {
@@ -326,9 +333,13 @@ function elgg_disable_metadata(array $options) {
}
elgg_get_metadata_cache()->invalidateByOptions('disable', $options);
+
+ // if we can see hidden (disabled) we need to use the offset
+ // otherwise we risk an infinite loop if there are more than 50
+ $inc_offset = access_get_show_hidden_status();
$options['metastring_type'] = 'metadata';
- return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', false);
+ return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', $inc_offset);
}
/**
@@ -336,10 +347,11 @@ function elgg_disable_metadata(array $options) {
*
* @warning Unlike elgg_get_metadata() this will not accept an empty options array!
*
- * @warning This returns null on no ops.
+ * @warning In order to enable metadata, you must first use
+ * {@link access_show_hidden_entities()}.
*
* @param array $options An options array. {@See elgg_get_metadata()}
- * @return mixed
+ * @return bool|null true on success, false on failure, null if no metadata enabled.
* @since 1.8.0
*/
function elgg_enable_metadata(array $options) {
@@ -394,9 +406,11 @@ function elgg_enable_metadata(array $options) {
* 'operand' => '=',
* 'case_sensitive' => TRUE
* )
- * Currently if multiple values are sent via
+ * Currently if multiple values are sent via
* an array (value => array('value1', 'value2')
* the pair's operand will be forced to "IN".
+ * If passing "IN" as the operand and a string as the value,
+ * the value must be a properly quoted and escaped string.
*
* metadata_name_value_pairs_operator => NULL|STR The operator to use for combining
* (name = value) OPERATOR (name = value); default AND
@@ -412,7 +426,7 @@ function elgg_enable_metadata(array $options) {
*
* metadata_owner_guids => NULL|ARR guids for metadata owners
*
- * @return mixed If count, int. If not count, array. false on errors.
+ * @return ElggEntity[]|mixed If count, int. If not count, array. false on errors.
* @since 1.7.0
*/
function elgg_get_entities_from_metadata(array $options = array()) {
@@ -461,7 +475,7 @@ function elgg_get_entities_from_metadata(array $options = array()) {
* @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')
+ * @return false|array False on fail, array('joins', 'wheres')
* @since 1.7.0
* @access private
*/
@@ -608,6 +622,8 @@ $owner_guids = NULL) {
// if the operand is IN don't quote it because quoting should be done already.
if (is_numeric($pair['value'])) {
$value = sanitise_string($pair['value']);
+ } else if (is_bool($pair['value'])) {
+ $value = (int) $pair['value'];
} else if (is_array($pair['value'])) {
$values_array = array();
@@ -774,10 +790,10 @@ function string_to_tag_array($string) {
$ar = explode(",", $string);
$ar = array_map('trim', $ar);
$ar = array_filter($ar, 'is_not_null');
+ $ar = array_map('strip_tags', $ar);
return $ar;
}
return false;
-
}
/**
@@ -909,8 +925,8 @@ function elgg_get_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
+ * @param array $options Options passed to elgg_(delete|disable|enable)_metadata
+ * @return void
*/
function elgg_invalidate_metadata_cache($action, array $options) {
// remove as little as possible, optimizing for common cases
diff --git a/engine/lib/metastrings.php b/engine/lib/metastrings.php
index cf6dd4d98..57d876c06 100644
--- a/engine/lib/metastrings.php
+++ b/engine/lib/metastrings.php
@@ -67,7 +67,7 @@ function get_metastring_id($string, $case_sensitive = TRUE) {
}
$row = FALSE;
- $metaStrings = get_data($query, "entity_row_to_elggstar");
+ $metaStrings = get_data($query);
if (is_array($metaStrings)) {
if (sizeof($metaStrings) > 1) {
$ids = array();
@@ -389,11 +389,6 @@ function elgg_get_metastring_based_objects($options) {
$selects = $options['selects'];
- // allow count shortcut
- if ($options['count']) {
- $options['metastring_calculation'] = 'count';
- }
-
// For performance reasons we don't want the joins required for metadata / annotations
// unless we're going through one of their callbacks.
// this means we expect the functions passing different callbacks to pass their required joins.
@@ -426,9 +421,11 @@ function elgg_get_metastring_based_objects($options) {
if ($metastring_clauses) {
$wheres = array_merge($wheres, $metastring_clauses['wheres']);
$joins = array_merge($joins, $metastring_clauses['joins']);
+ } else {
+ $wheres[] = get_access_sql_suffix('n_table');
}
- if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE) {
+ if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE && !$options['count']) {
$selects = array_unique($selects);
// evalutate selects
$select_str = '';
@@ -439,6 +436,9 @@ function elgg_get_metastring_based_objects($options) {
}
$query = "SELECT DISTINCT n_table.*{$select_str} FROM {$db_prefix}$type n_table";
+ } elseif ($options['count']) {
+ // count is over the entities
+ $query = "SELECT count(DISTINCT e.guid) as calculation FROM {$db_prefix}$type n_table";
} else {
$query = "SELECT {$options['metastring_calculation']}(v.string) as calculation FROM {$db_prefix}$type n_table";
}
@@ -467,7 +467,7 @@ function elgg_get_metastring_based_objects($options) {
$defaults['order_by']);
}
- if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE) {
+ if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE && !$options['count']) {
if (isset($options['group_by'])) {
$options['group_by'] = sanitise_string($options['group_by']);
$query .= " GROUP BY {$options['group_by']}";
@@ -515,21 +515,16 @@ function elgg_get_metastring_sql($table, $names = null, $values = null,
&& !$ids
&& (!$pairs && $pairs !== 0)) {
- return '';
+ return array();
}
$db_prefix = elgg_get_config('dbprefix');
- // join counter for incremental joins.
- $i = 1;
-
// binary forces byte-to-byte comparision of strings, making
// it case- and diacritical-mark- sensitive.
// only supported on values.
$binary = ($case_sensitive) ? ' BINARY ' : '';
- $access = get_access_sql_suffix($table);
-
$return = array (
'joins' => array (),
'wheres' => array()
@@ -594,13 +589,15 @@ function elgg_get_metastring_sql($table, $names = null, $values = null,
}
if ($names_where && $values_where) {
- $wheres[] = "($names_where AND $values_where AND $access)";
+ $wheres[] = "($names_where AND $values_where)";
} elseif ($names_where) {
- $wheres[] = "($names_where AND $access)";
+ $wheres[] = $names_where;
} elseif ($values_where) {
- $wheres[] = "($values_where AND $access)";
+ $wheres[] = $values_where;
}
+ $wheres[] = get_access_sql_suffix($table);
+
if ($where = implode(' AND ', $wheres)) {
$return['wheres'][] = "($where)";
}
@@ -663,9 +660,10 @@ function elgg_normalize_metastrings_options(array $options = array()) {
*
* @param int $id The object's ID
* @param string $enabled Value to set to: yes or no
- * @param string $type The type of table to use: metadata or anntations
+ * @param string $type The type of table to use: metadata or annotations
*
* @return bool
+ * @throws InvalidParameterException
* @since 1.8.0
* @access private
*/
@@ -740,7 +738,7 @@ function elgg_batch_metastring_based_objects(array $options, $callback, $inc_off
*
* @param int $id The metastring-based object's ID
* @param string $type The type: annotation or metadata
- * @return mixed
+ * @return ElggMetadata|ElggAnnotation
*
* @since 1.8.0
* @access private
@@ -806,6 +804,7 @@ function elgg_delete_metastring_based_object_by_id($id, $type) {
}
if ($metabyname_memcache) {
+ // @todo why name_id? is that even populated?
$metabyname_memcache->delete("{$obj->entity_guid}:{$obj->name_id}");
}
}
diff --git a/engine/lib/navigation.php b/engine/lib/navigation.php
index 86624cd7c..ab9cc05e8 100644
--- a/engine/lib/navigation.php
+++ b/engine/lib/navigation.php
@@ -126,6 +126,7 @@ function elgg_unregister_menu_item($menu_name, $item_name) {
}
foreach ($CONFIG->menus[$menu_name] as $index => $menu_object) {
+ /* @var ElggMenuItem $menu_object */
if ($menu_object->getName() == $item_name) {
unset($CONFIG->menus[$menu_name][$index]);
return true;
@@ -151,7 +152,8 @@ function elgg_is_menu_item_registered($menu_name, $item_name) {
return false;
}
- foreach ($CONFIG->menus[$menu_name] as $index => $menu_object) {
+ foreach ($CONFIG->menus[$menu_name] as $menu_object) {
+ /* @var ElggMenuItem $menu_object */
if ($menu_object->getName() == $item_name) {
return true;
}
@@ -216,7 +218,7 @@ function elgg_push_breadcrumb($title, $link = NULL) {
}
// avoid key collisions.
- $CONFIG->breadcrumbs[] = array('title' => $title, 'link' => $link);
+ $CONFIG->breadcrumbs[] = array('title' => elgg_get_excerpt($title, 100), 'link' => $link);
}
/**
@@ -311,8 +313,8 @@ function elgg_site_menu_setup($hook, $type, $return, $params) {
// check if we have anything selected
$selected = false;
- foreach ($return as $section_name => $section) {
- foreach ($section as $key => $item) {
+ foreach ($return as $section) {
+ foreach ($section as $item) {
if ($item->getSelected()) {
$selected = true;
break 2;
@@ -321,7 +323,8 @@ function elgg_site_menu_setup($hook, $type, $return, $params) {
}
if (!$selected) {
- // nothing selected, match name to context
+ // nothing selected, match name to context or match url
+ $current_url = current_page_url();
foreach ($return as $section_name => $section) {
foreach ($section as $key => $item) {
// only highlight internal links
@@ -330,6 +333,10 @@ function elgg_site_menu_setup($hook, $type, $return, $params) {
$return[$section_name][$key]->setSelected(true);
break 2;
}
+ if ($item->getHref() == $current_url) {
+ $return[$section_name][$key]->setSelected(true);
+ break 2;
+ }
}
}
}
@@ -345,6 +352,7 @@ function elgg_site_menu_setup($hook, $type, $return, $params) {
function elgg_river_menu_setup($hook, $type, $return, $params) {
if (elgg_is_logged_in()) {
$item = $params['item'];
+ /* @var ElggRiverItem $item */
$object = $item->getObjectEntity();
// comments and non-objects cannot be commented on or liked
if (!elgg_in_context('widgets') && $item->annotation_id == 0) {
@@ -388,6 +396,7 @@ function elgg_entity_menu_setup($hook, $type, $return, $params) {
}
$entity = $params['entity'];
+ /* @var ElggEntity $entity */
$handler = elgg_extract('handler', $params, false);
// access
@@ -433,6 +442,7 @@ function elgg_entity_menu_setup($hook, $type, $return, $params) {
function elgg_widget_menu_setup($hook, $type, $return, $params) {
$widget = $params['entity'];
+ /* @var ElggWidget $widget */
$show_edit = elgg_extract('show_edit', $params, true);
$collapse = array(
@@ -481,6 +491,7 @@ function elgg_widget_menu_setup($hook, $type, $return, $params) {
*/
function elgg_annotation_menu_setup($hook, $type, $return, $params) {
$annotation = $params['annotation'];
+ /* @var ElggAnnotation $annotation */
if ($annotation->name == 'generic_comment' && $annotation->canEdit()) {
$url = elgg_http_add_url_query_elements('action/comments/delete', array(
diff --git a/engine/lib/notification.php b/engine/lib/notification.php
index 9e3c075a8..be0c359d4 100644
--- a/engine/lib/notification.php
+++ b/engine/lib/notification.php
@@ -86,7 +86,7 @@ function unregister_notification_handler($method) {
* @throws NotificationException
*/
function notify_user($to, $from, $subject, $message, array $params = NULL, $methods_override = "") {
- global $NOTIFICATION_HANDLERS, $CONFIG;
+ global $NOTIFICATION_HANDLERS;
// Sanitise
if (!is_array($to)) {
@@ -110,12 +110,15 @@ function notify_user($to, $from, $subject, $message, array $params = NULL, $meth
// Are we overriding delivery?
$methods = $methods_override;
if (!$methods) {
- $tmp = (array)get_user_notification_settings($guid);
+ $tmp = get_user_notification_settings($guid);
$methods = array();
- foreach ($tmp as $k => $v) {
- // Add method if method is turned on for user!
- if ($v) {
- $methods[] = $k;
+ // $tmp may be false. don't cast
+ if (is_object($tmp)) {
+ foreach ($tmp as $k => $v) {
+ // Add method if method is turned on for user!
+ if ($v) {
+ $methods[] = $k;
+ }
}
}
}
@@ -165,7 +168,7 @@ function notify_user($to, $from, $subject, $message, array $params = NULL, $meth
*
* @param int $user_guid The user id
*
- * @return stdClass
+ * @return stdClass|false
*/
function get_user_notification_settings($user_guid = 0) {
$user_guid = (int)$user_guid;
@@ -174,7 +177,8 @@ function get_user_notification_settings($user_guid = 0) {
$user_guid = elgg_get_logged_in_user_guid();
}
- // @todo: holy crap, really?
+ // @todo: there should be a better way now that metadata is cached. E.g. just query for MD names, then
+ // query user object directly
$all_metadata = elgg_get_metadata(array(
'guid' => $user_guid,
'limit' => 0
@@ -237,6 +241,7 @@ function set_user_notification_setting($user_guid, $method, $value) {
* @param array $params Optional parameters (none taken in this instance)
*
* @return bool
+ * @throws NotificationException
* @access private
*/
function email_notify_handler(ElggEntity $from, ElggUser $to, $subject, $message,
@@ -263,7 +268,7 @@ array $params = NULL) {
$to = $to->email;
// From
- $site = get_entity($CONFIG->site_guid);
+ $site = elgg_get_site_entity();
// If there's an email address, use it - but only if its not from a user.
if (!($from instanceof ElggUser) && $from->email) {
$from = $from->email;
@@ -288,6 +293,7 @@ array $params = NULL) {
* @param array $params Optional parameters (none used in this function)
*
* @return bool
+ * @throws NotificationException
* @since 1.7.2
*/
function elgg_send_email($from, $to, $subject, $body, array $params = NULL) {
@@ -344,6 +350,8 @@ function elgg_send_email($from, $to, $subject, $body, array $params = NULL) {
// Sanitise subject by stripping line endings
$subject = preg_replace("/(\r\n|\r|\n)/", " ", $subject);
+ // this is because Elgg encodes everything and matches what is done with body
+ $subject = html_entity_decode($subject, ENT_COMPAT, 'UTF-8'); // Decode any html entities
if (is_callable('mb_encode_mimeheader')) {
$subject = mb_encode_mimeheader($subject, "UTF-8", "B");
}
@@ -422,7 +430,7 @@ function register_notification_object($entity_type, $object_subtype, $language_n
* @param int $user_guid The GUID of the user who wants to follow a user's content
* @param int $author_guid The GUID of the user whose content the user wants to follow
*
- * @return true|false Depending on success
+ * @return bool Depending on success
*/
function register_notification_interest($user_guid, $author_guid) {
return add_entity_relationship($user_guid, 'notify', $author_guid);
@@ -434,7 +442,7 @@ function register_notification_interest($user_guid, $author_guid) {
* @param int $user_guid The GUID of the user who is following a user's content
* @param int $author_guid The GUID of the user whose content the user wants to unfollow
*
- * @return true|false Depending on success
+ * @return bool Depending on success
*/
function remove_notification_interest($user_guid, $author_guid) {
return remove_entity_relationship($user_guid, 'notify', $author_guid);
@@ -450,12 +458,13 @@ function remove_notification_interest($user_guid, $author_guid) {
* @param string $object_type mixed
* @param mixed $object The object created
*
- * @return void
+ * @return bool
* @access private
*/
function object_notifications($event, $object_type, $object) {
// We only want to trigger notification events for ElggEntities
if ($object instanceof ElggEntity) {
+ /* @var ElggEntity $object */
// Get config data
global $CONFIG, $SESSION, $NOTIFICATION_HANDLERS;
@@ -492,9 +501,10 @@ function object_notifications($event, $object_type, $object) {
'relationship' => 'notify' . $method,
'relationship_guid' => $object->container_guid,
'inverse_relationship' => TRUE,
- 'types' => 'user',
- 'limit' => 99999
+ 'type' => 'user',
+ 'limit' => false
));
+ /* @var ElggUser[] $interested_users */
if ($interested_users && is_array($interested_users)) {
foreach ($interested_users as $user) {
diff --git a/engine/lib/objects.php b/engine/lib/objects.php
index e5e8f67c4..ff3cc733f 100644
--- a/engine/lib/objects.php
+++ b/engine/lib/objects.php
@@ -93,16 +93,16 @@ function get_object_sites($object_guid, $limit = 10, $offset = 0) {
return elgg_get_entities_from_relationship(array(
'relationship' => 'member_of_site',
'relationship_guid' => $object_guid,
- 'types' => 'site',
+ 'type' => 'site',
'limit' => $limit,
- 'offset' => $offset
+ 'offset' => $offset,
));
}
/**
* Runs unit tests for ElggObject
*
- * @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/opendd.php b/engine/lib/opendd.php
index f00ea6aab..7d635a295 100644
--- a/engine/lib/opendd.php
+++ b/engine/lib/opendd.php
@@ -7,6 +7,8 @@
* @version 0.4
*/
+// @codingStandardsIgnoreStart
+
/**
* Attempt to construct an ODD object out of a XmlElement or sub-elements.
*
@@ -103,3 +105,5 @@ function ODD_Import($xml) {
function ODD_Export(ODDDocument $document) {
return "$document";
}
+
+// @codingStandardsIgnoreEnd
diff --git a/engine/lib/output.php b/engine/lib/output.php
index 9295f2173..de4f911fb 100644
--- a/engine/lib/output.php
+++ b/engine/lib/output.php
@@ -12,29 +12,34 @@
*
* @param string $text The input string
*
- * @return string The output stirng with formatted links
- **/
+ * @return string The output string with formatted links
+ */
function parse_urls($text) {
+
+ // URI specification: http://www.ietf.org/rfc/rfc3986.txt
+ // This varies from the specification in the following ways:
+ // * Supports non-ascii characters
+ // * Does not allow parentheses and single quotes
+ // * Cuts off commas, exclamation points, and periods off as last character
+
// @todo this causes problems with <attr = "val">
// must be in <attr="val"> format (no space).
// By default htmlawed rewrites tags to this format.
// if PHP supported conditional negative lookbehinds we could use this:
// $r = preg_replace_callback('/(?<!=)(?<![ ])?(?<!["\'])((ht|f)tps?:\/\/[^\s\r\n\t<>"\'\!\(\),]+)/i',
- //
- // we can put , in the list of excluded char but need to keep . because of domain names.
- // it is removed in the callback.
- $r = preg_replace_callback('/(?<!=)(?<!["\'])((ht|f)tps?:\/\/[^\s\r\n\t<>"\'\!\(\),]+)/i',
+ $r = preg_replace_callback('/(?<![=\/"\'])((ht|f)tps?:\/\/[^\s\r\n\t<>"\']+)/i',
create_function(
'$matches',
'
$url = $matches[1];
- $period = \'\';
- if (substr($url, -1, 1) == \'.\') {
- $period = \'.\';
- $url = trim($url, \'.\');
+ $punc = "";
+ $last = substr($url, -1, 1);
+ if (in_array($last, array(".", "!", ",", "(", ")"))) {
+ $punc = $last;
+ $url = rtrim($url, ".!,()");
}
$urltext = str_replace("/", "/<wbr />", $url);
- return "<a href=\"$url\">$urltext</a>$period";
+ return "<a href=\"$url\" rel=\"nofollow\">$urltext</a>$punc";
'
), $text);
@@ -224,7 +229,6 @@ function elgg_normalize_url($url) {
$php_5_3_0_to_5_3_2 = version_compare(PHP_VERSION, '5.3.0', '>=') &&
version_compare(PHP_VERSION, '5.3.3', '<');
- $validated = false;
if ($php_5_2_13_and_below || $php_5_3_0_to_5_3_2) {
$tmp_address = str_replace("-", "", $url);
$validated = filter_var($tmp_address, FILTER_VALIDATE_URL);
@@ -285,11 +289,9 @@ function elgg_get_friendly_title($title) {
return $result;
}
- // handle some special cases
- $title = str_replace('&amp;', 'and', $title);
- // quotes and angle brackets stored in the database as html encoded
- $title = htmlspecialchars_decode($title);
-
+ // titles are often stored HTML encoded
+ $title = html_entity_decode($title, ENT_QUOTES, 'UTF-8');
+
$title = ElggTranslit::urlize($title);
return $title;
@@ -419,9 +421,28 @@ function _elgg_html_decode($string) {
}
/**
+ * Prepares query string for output to prevent CSRF attacks.
+ *
+ * @param string $string
+ * @return string
+ *
+ * @access private
+ */
+function _elgg_get_display_query($string) {
+ //encode <,>,&, quotes and characters above 127
+ if (function_exists('mb_convert_encoding')) {
+ $display_query = mb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8');
+ } else {
+ // if no mbstring extension, we just strip characters
+ $display_query = preg_replace("/[^\x01-\x7F]/", "", $string);
+ }
+ return htmlspecialchars($display_query, ENT_QUOTES, 'UTF-8', false);
+}
+
+/**
* Unit tests for Output
*
- * @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/pageowner.php b/engine/lib/pageowner.php
index 94765feee..bd63d08c6 100644
--- a/engine/lib/pageowner.php
+++ b/engine/lib/pageowner.php
@@ -29,7 +29,9 @@ function elgg_get_page_owner_guid($guid = 0) {
// return guid of page owner entity
$guid = elgg_trigger_plugin_hook('page_owner', 'system', NULL, 0);
- $page_owner_guid = $guid;
+ if ($guid) {
+ $page_owner_guid = $guid;
+ }
return $guid;
}
@@ -39,7 +41,7 @@ function elgg_get_page_owner_guid($guid = 0) {
*
* @note Access is disabled when getting the page owner entity.
*
- * @return ElggEntity|false The current page owner or false if none.
+ * @return ElggUser|ElggGroup|false The current page owner or false if none.
*
* @since 1.8.0
*/
@@ -113,6 +115,7 @@ function default_page_owner_handler($hook, $entity_type, $returnvalue, $params)
}
if ($user = get_user_by_username($username)) {
+ elgg_set_ignore_access($ia);
return $user->getGUID();
}
}
diff --git a/engine/lib/plugins.php b/engine/lib/plugins.php
index 94aff277e..d5d3db466 100644
--- a/engine/lib/plugins.php
+++ b/engine/lib/plugins.php
@@ -91,7 +91,9 @@ function elgg_get_plugin_ids_in_dir($dir = null) {
* @access private
*/
function elgg_generate_plugin_entities() {
+ // @todo $site unused, can remove?
$site = get_config('site');
+
$dir = elgg_get_plugins_path();
$db_prefix = elgg_get_config('dbprefix');
@@ -107,6 +109,7 @@ function elgg_generate_plugin_entities() {
$old_access = access_get_show_hidden_status();
access_show_hidden_entities(true);
$known_plugins = elgg_get_entities_from_relationship($options);
+ /* @var ElggPlugin[] $known_plugins */
if (!$known_plugins) {
$known_plugins = array();
@@ -138,7 +141,7 @@ function elgg_generate_plugin_entities() {
$index = $id_map[$plugin_id];
$plugin = $known_plugins[$index];
// was this plugin deleted and its entity disabled?
- if ($plugin->enabled != 'yes') {
+ if (!$plugin->isEnabled()) {
$plugin->enable();
$plugin->deactivate();
$plugin->setPriority('last');
@@ -192,7 +195,7 @@ function _elgg_cache_plugin_by_id(ElggPlugin $plugin) {
* Returns an ElggPlugin object with the path $path.
*
* @param string $plugin_id The id (dir name) of the plugin. NOT the guid.
- * @return mixed ElggPlugin or false.
+ * @return ElggPlugin|false
* @since 1.8.0
*/
function elgg_get_plugin_from_id($plugin_id) {
@@ -260,6 +263,8 @@ function elgg_get_max_plugin_priority() {
$data = get_data($q);
if ($data) {
$max = $data[0]->max;
+ } else {
+ $max = 1;
}
// can't have a priority of 0.
@@ -306,13 +311,11 @@ function elgg_is_active_plugin($plugin_id, $site_guid = null) {
* @access private
*/
function elgg_load_plugins() {
- global $CONFIG;
-
$plugins_path = elgg_get_plugins_path();
- $start_flags = ELGG_PLUGIN_INCLUDE_START
- | ELGG_PLUGIN_REGISTER_VIEWS
- | ELGG_PLUGIN_REGISTER_LANGUAGES
- | ELGG_PLUGIN_REGISTER_CLASSES;
+ $start_flags = ELGG_PLUGIN_INCLUDE_START |
+ ELGG_PLUGIN_REGISTER_VIEWS |
+ ELGG_PLUGIN_REGISTER_LANGUAGES |
+ ELGG_PLUGIN_REGISTER_CLASSES;
if (!$plugins_path) {
return false;
@@ -360,7 +363,7 @@ function elgg_load_plugins() {
*
* @param string $status The status of the plugins. active, inactive, or all.
* @param mixed $site_guid Optional site guid
- * @return array
+ * @return ElggPlugin[]
* @since 1.8.0
* @access private
*/
@@ -441,6 +444,7 @@ function elgg_set_plugin_priorities(array $order) {
// though we do start with 1
$order = array_values($order);
+ $missing_plugins = array();
foreach ($plugins as $plugin) {
$plugin_id = $plugin->getID();
@@ -639,19 +643,18 @@ function elgg_get_plugins_provides($type = null, $name = null) {
* @access private
*/
function elgg_check_plugins_provides($type, $name, $version = null, $comparison = 'ge') {
- if (!$provided = elgg_get_plugins_provides($type, $name)) {
+ $provided = elgg_get_plugins_provides($type, $name);
+ if (!$provided) {
return array(
'status' => false,
'version' => ''
);
}
- if ($provided) {
- if ($version) {
- $status = version_compare($provided['version'], $version, $comparison);
- } else {
- $status = true;
- }
+ if ($version) {
+ $status = version_compare($provided['version'], $version, $comparison);
+ } else {
+ $status = true;
}
return array(
@@ -861,9 +864,9 @@ function elgg_set_plugin_user_setting($name, $value, $user_guid = null, $plugin_
/**
* Unsets a user-specific plugin setting
*
- * @param str $name Name of the setting
- * @param int $user_guid Defaults to logged in user
- * @param str $plugin_id Defaults to contextual plugin name
+ * @param string $name Name of the setting
+ * @param int $user_guid Defaults to logged in user
+ * @param string $plugin_id Defaults to contextual plugin name
*
* @return bool
* @since 1.8.0
@@ -1087,7 +1090,7 @@ function plugin_run_once() {
/**
* 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
@@ -1102,6 +1105,49 @@ function plugins_test($hook, $type, $value, $params) {
}
/**
+ * Checks on deactivate plugin event if disabling it won't create unmet dependencies and blocks disable in such case.
+ *
+ * @param string $event deactivate
+ * @param string $type plugin
+ * @param array $params Parameters array containing entry with ELggPlugin instance under 'plugin_entity' key
+ * @return bool false to block plugin deactivation action
+ *
+ * @access private
+ */
+function _plugins_deactivate_dependency_check($event, $type, $params) {
+ $plugin_id = $params['plugin_entity']->getManifest()->getPluginID();
+ $plugin_name = $params['plugin_entity']->getManifest()->getName();
+
+ $active_plugins = elgg_get_plugins();
+
+ $dependents = array();
+ foreach ($active_plugins as $plugin) {
+ $manifest = $plugin->getManifest();
+ $requires = $manifest->getRequires();
+
+ foreach ($requires as $required) {
+ if ($required['type'] == 'plugin' && $required['name'] == $plugin_id) {
+ // there are active dependents
+ $dependents[$manifest->getPluginID()] = $plugin;
+ }
+ }
+ }
+
+ if ($dependents) {
+ $list = '<ul>';
+ // construct error message and prevent disabling
+ foreach ($dependents as $dependent) {
+ $list .= '<li>' . $dependent->getManifest()->getName() . '</li>';
+ }
+ $list .= '</ul>';
+
+ register_error(elgg_echo('ElggPlugin:Dependencies:ActiveDependent', array($plugin_name, $list)));
+
+ return false;
+ }
+}
+
+/**
* Initialize the plugin system
* Listens to system init and registers actions
*
@@ -1112,6 +1158,10 @@ function plugin_init() {
run_function_once("plugin_run_once");
elgg_register_plugin_hook_handler('unit_test', 'system', 'plugins_test');
+
+ // note - plugins are booted by the time this handler is registered
+ // deactivation due to error may have already occurred
+ elgg_register_event_handler('deactivate', 'plugin', '_plugins_deactivate_dependency_check');
elgg_register_action("plugins/settings/save", '', 'admin');
elgg_register_action("plugins/usersettings/save");
diff --git a/engine/lib/relationships.php b/engine/lib/relationships.php
index 01654b1ce..b0cd627fc 100644
--- a/engine/lib/relationships.php
+++ b/engine/lib/relationships.php
@@ -12,7 +12,7 @@
*
* @param stdClass $row Database row from the relationship table
*
- * @return stdClass or ElggMetadata
+ * @return ElggRelationship|stdClass
* @access private
*/
function row_to_elggrelationship($row) {
@@ -28,7 +28,7 @@ function row_to_elggrelationship($row) {
*
* @param int $id The ID of a relationship
*
- * @return mixed
+ * @return ElggRelationship|false
*/
function get_relationship($id) {
global $CONFIG;
@@ -109,7 +109,7 @@ function add_entity_relationship($guid_one, $relationship, $guid_two) {
* @param string $relationship The type of relationship
* @param int $guid_two The GUID of the entity the relationship is with
*
- * @return object|false Depending on success
+ * @return ElggRelationship|false Depending on success
*/
function check_entity_relationship($guid_one, $relationship, $guid_two) {
global $CONFIG;
@@ -123,7 +123,7 @@ function check_entity_relationship($guid_one, $relationship, $guid_two) {
AND relationship='$relationship'
AND guid_two=$guid_two limit 1";
- $row = get_data_row($query);
+ $row = row_to_elggrelationship(get_data_row($query));
if ($row) {
return $row;
}
@@ -220,7 +220,7 @@ function remove_entity_relationships($guid_one, $relationship = "", $inverse = f
* @param int $guid The GUID of the relationship owner
* @param bool $inverse_relationship Inverse relationship owners?
*
- * @return mixed
+ * @return ElggRelationship[]
*/
function get_entity_relationships($guid, $inverse_relationship = FALSE) {
global $CONFIG;
@@ -259,7 +259,7 @@ function get_entity_relationships($guid, $inverse_relationship = FALSE) {
*
* inverse_relationship => BOOL Inverse the relationship
*
- * @return mixed If count, int. If not count, array. false on errors.
+ * @return ElggEntity[]|mixed If count, int. If not count, array. false on errors.
* @since 1.7.0
*/
function elgg_get_entities_from_relationship($options) {
@@ -316,7 +316,7 @@ function elgg_get_entities_from_relationship($options) {
* Provide in table.column format.
* @param string $relationship Relationship string
* @param int $relationship_guid Entity guid to check
- * @param string $inverse_relationship Inverse relationship check?
+ * @param bool $inverse_relationship Inverse relationship check?
*
* @return mixed
* @since 1.7.0
@@ -363,7 +363,7 @@ $relationship_guid = NULL, $inverse_relationship = FALSE) {
/**
* Returns a viewable list of entities by relationship
*
- * @param array $options
+ * @param array $options Options array for retrieval of entities
*
* @see elgg_list_entities()
* @see elgg_get_entities_from_relationship()
@@ -381,7 +381,7 @@ function elgg_list_entities_from_relationship(array $options = array()) {
*
* @param array $options An options array compatible with
* elgg_get_entities_from_relationship()
- * @return mixed int If count, int. If not count, array. false on errors.
+ * @return ElggEntity[]|mixed int If count, int. If not count, array. false on errors.
* @since 1.8.0
*/
function elgg_get_entities_from_relationship_count(array $options = array()) {
@@ -398,7 +398,7 @@ function elgg_get_entities_from_relationship_count(array $options = array()) {
*
* @param array $options Options array
*
- * @return array
+ * @return string
* @since 1.8.0
*/
function elgg_list_entities_from_relationship_count($options) {
@@ -499,7 +499,7 @@ function already_attached($guid_one, $guid_two) {
* @param int $guid Entity GUID
* @param string $type The type of object to return e.g. 'file', 'friend_of' etc
*
- * @return an array of objects
+ * @return ElggEntity[]
* @access private
*/
function get_attachments($guid, $type = "") {
@@ -507,7 +507,7 @@ function get_attachments($guid, $type = "") {
'relationship' => 'attached',
'relationship_guid' => $guid,
'inverse_relationship' => false,
- 'types' => $type,
+ 'type' => $type,
'subtypes' => '',
'owner_guid' => 0,
'order_by' => 'time_created desc',
@@ -571,9 +571,8 @@ function import_relationship_plugin_hook($hook, $entity_type, $returnvalue, $par
if ($element instanceof ODDRelationship) {
$tmp = new ElggRelationship();
$tmp->import($element);
-
- return $tmp;
}
+ return $tmp;
}
/**
@@ -586,11 +585,10 @@ function import_relationship_plugin_hook($hook, $entity_type, $returnvalue, $par
*
* @elgg_event_handler export all
* @return mixed
+ * @throws InvalidParameterException
* @access private
*/
function export_relationship_plugin_hook($hook, $entity_type, $returnvalue, $params) {
- global $CONFIG;
-
// Sanity check values
if ((!is_array($params)) && (!isset($params['guid']))) {
throw new InvalidParameterException(elgg_echo('InvalidParameterException:GUIDNotForExport'));
@@ -624,9 +622,9 @@ function export_relationship_plugin_hook($hook, $entity_type, $returnvalue, $par
* @access private
*/
function relationship_notification_hook($event, $type, $object) {
-
+ /* @var ElggRelationship $object */
$user_one = get_entity($object->guid_one);
- $user_two = get_entity($object->guid_two);
+ /* @var ElggUser $user_one */
return notify_user($object->guid_two,
$object->guid_one,
diff --git a/engine/lib/river.php b/engine/lib/river.php
index 33f34360e..e92040eb7 100644
--- a/engine/lib/river.php
+++ b/engine/lib/river.php
@@ -120,7 +120,7 @@ $posted = 0, $annotation_id = 0) {
* subtypes => STR|ARR Entity subtype string(s)
* type_subtype_pairs => ARR Array of type => subtype pairs where subtype
* can be an array of subtype strings
- *
+ *
* posted_time_lower => INT The lower bound on the time posted
* posted_time_upper => INT The upper bound on the time posted
*
@@ -380,10 +380,10 @@ function _elgg_prefetch_river_entities(array $river_items) {
// prefetch objects and subjects
$guids = array();
foreach ($river_items as $item) {
- if ($item->subject_guid && !retrieve_cached_entity($item->subject_guid)) {
+ if ($item->subject_guid && !_elgg_retrieve_cached_entity($item->subject_guid)) {
$guids[$item->subject_guid] = true;
}
- if ($item->object_guid && !retrieve_cached_entity($item->object_guid)) {
+ if ($item->object_guid && !_elgg_retrieve_cached_entity($item->object_guid)) {
$guids[$item->object_guid] = true;
}
}
@@ -402,7 +402,7 @@ function _elgg_prefetch_river_entities(array $river_items) {
$guids = array();
foreach ($river_items as $item) {
$object = $item->getObjectEntity();
- if ($object->container_guid && !retrieve_cached_entity($object->container_guid)) {
+ if ($object->container_guid && !_elgg_retrieve_cached_entity($object->container_guid)) {
$guids[$object->container_guid] = true;
}
}
@@ -434,8 +434,13 @@ function elgg_list_river(array $options = array()) {
'pagination' => TRUE,
'list_class' => 'elgg-list-river elgg-river', // @todo remove elgg-river in Elgg 1.9
);
-
+
$options = array_merge($defaults, $options);
+
+ if (!$options["limit"] && !$options["offset"]) {
+ // no need for pagination if listing is unlimited
+ $options["pagination"] = false;
+ }
$options['count'] = TRUE;
$count = elgg_get_river($options);
@@ -445,6 +450,7 @@ function elgg_list_river(array $options = array()) {
$options['count'] = $count;
$options['items'] = $items;
+
return elgg_view('page/components/list', $options);
}
@@ -500,6 +506,7 @@ function elgg_get_river_type_subtype_where_sql($table, $types, $subtypes, $pairs
return '';
}
+ $wheres = array();
$types_wheres = array();
$subtypes_wheres = array();
@@ -644,7 +651,7 @@ function update_river_access_by_object($object_guid, $access_id) {
}
/**
- * Page handler for activiy
+ * Page handler for activity
*
* @param array $page
* @return bool
@@ -663,10 +670,6 @@ function elgg_river_page_handler($page) {
}
set_input('page_type', $page_type);
- // content filter code here
- $entity_type = '';
- $entity_subtype = '';
-
require_once("{$CONFIG->path}pages/river.php");
return true;
}
diff --git a/engine/lib/sessions.php b/engine/lib/sessions.php
index 72ca0a1c2..e3d5ce9cd 100644
--- a/engine/lib/sessions.php
+++ b/engine/lib/sessions.php
@@ -87,6 +87,9 @@ function elgg_is_admin_logged_in() {
*/
function elgg_is_admin_user($user_guid) {
global $CONFIG;
+
+ $user_guid = (int)$user_guid;
+
// cannot use magic metadata here because of recursion
// must support the old way of getting admin from metadata
@@ -286,8 +289,6 @@ function check_rate_limit_exceeded($user_guid) {
* @throws LoginException
*/
function login(ElggUser $user, $persistent = false) {
- global $CONFIG;
-
// User is banned, return false.
if ($user->isBanned()) {
throw new LoginException(elgg_echo('LoginException:BannedUser'));
@@ -325,6 +326,12 @@ function login(ElggUser $user, $persistent = false) {
set_last_login($_SESSION['guid']);
reset_login_failure_count($user->guid); // Reset any previous failed login attempts
+ // if memcache is enabled, invalidate the user in memcache @see https://github.com/Elgg/Elgg/issues/3143
+ if (is_memcache_available()) {
+ // this needs to happen with a shutdown function because of the timing with set_last_login()
+ register_shutdown_function("_elgg_invalidate_memcache_for_entity", $_SESSION['guid']);
+ }
+
return true;
}
@@ -334,8 +341,6 @@ function login(ElggUser $user, $persistent = false) {
* @return bool
*/
function logout() {
- global $CONFIG;
-
if (isset($_SESSION['user'])) {
if (!elgg_trigger_event('logout', 'user', $_SESSION['user'])) {
return false;
@@ -616,10 +621,8 @@ function _elgg_session_destroy($id) {
global $sess_save_path;
$sess_file = "$sess_save_path/sess_$id";
- return(@unlink($sess_file));
+ return @unlink($sess_file);
}
-
- return false;
}
/**
diff --git a/engine/lib/sites.php b/engine/lib/sites.php
index d9eb2d25e..3de0eccc2 100644
--- a/engine/lib/sites.php
+++ b/engine/lib/sites.php
@@ -26,7 +26,7 @@ function elgg_get_site_entity($site_guid = 0) {
$site = get_entity($site_guid);
}
- if($site instanceof ElggSite){
+ if ($site instanceof ElggSite) {
$result = $site;
}
@@ -118,8 +118,6 @@ function create_site_entity($guid, $name, $description, $url) {
* @return bool
*/
function add_site_user($site_guid, $user_guid) {
- global $CONFIG;
-
$site_guid = (int)$site_guid;
$user_guid = (int)$user_guid;
@@ -150,8 +148,6 @@ function remove_site_user($site_guid, $user_guid) {
* @return mixed
*/
function add_site_object($site_guid, $object_guid) {
- global $CONFIG;
-
$site_guid = (int)$site_guid;
$object_guid = (int)$object_guid;
@@ -192,8 +188,8 @@ function get_site_objects($site_guid, $subtype = "", $limit = 10, $offset = 0) {
'relationship' => 'member_of_site',
'relationship_guid' => $site_guid,
'inverse_relationship' => TRUE,
- 'types' => 'object',
- 'subtypes' => $subtype,
+ 'type' => 'object',
+ 'subtype' => $subtype,
'limit' => $limit,
'offset' => $offset
));
@@ -242,7 +238,7 @@ function get_site_domain($guid) {
/**
* Unit tests for sites
*
- * @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/statistics.php b/engine/lib/statistics.php
index 5ee640549..4cb0bb0b8 100644
--- a/engine/lib/statistics.php
+++ b/engine/lib/statistics.php
@@ -95,15 +95,20 @@ function get_number_users($show_deactivated = false) {
* @return string
*/
function get_online_users() {
- $count = find_active_users(600, 10, 0, true);
- $objects = find_active_users(600, 10);
+ $limit = max(0, (int) get_input("limit", 10));
+ $offset = max(0, (int) get_input("offset", 0));
+
+ $count = find_active_users(600, $limit, $offset, true);
+ $objects = find_active_users(600, $limit, $offset);
if ($objects) {
return elgg_view_entity_list($objects, array(
'count' => $count,
- 'limit' => 10
+ 'limit' => $limit,
+ 'offset' => $offset
));
}
+ return '';
}
/**
diff --git a/engine/lib/system_log.php b/engine/lib/system_log.php
index 53fa24557..84302632e 100644
--- a/engine/lib/system_log.php
+++ b/engine/lib/system_log.php
@@ -10,6 +10,8 @@
/**
* Retrieve the system log based on a number of parameters.
*
+ * @todo too many args, and the first arg is too confusing
+ *
* @param int|array $by_user The guid(s) of the user(s) who initiated the event.
* Use 0 for unowned entries. Anything else falsey means anyone.
* @param string $event The event you are searching on.
@@ -22,12 +24,12 @@
* @param int $timebefore Lower time limit
* @param int $timeafter Upper time limit
* @param int $object_id GUID of an object
- * @param str $ip_address The IP address.
+ * @param string $ip_address The IP address.
* @return mixed
*/
-function get_system_log($by_user = "", $event = "", $class = "", $type = "", $subtype = "",
-$limit = 10, $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $object_id = 0,
-$ip_address = false) {
+function get_system_log($by_user = "", $event = "", $class = "", $type = "", $subtype = "", $limit = 10,
+ $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $object_id = 0,
+ $ip_address = "") {
global $CONFIG;
@@ -166,6 +168,7 @@ function system_log($object, $event) {
if ($object instanceof Loggable) {
+ /* @var ElggEntity|ElggExtender $object */
if (datalist_get('version') < 2012012000) {
// this is a site that doesn't have the ip_address column yet
return;
@@ -184,7 +187,16 @@ function system_log($object, $event) {
$object_subtype = $object->getSubtype();
$event = sanitise_string($event);
$time = time();
- $ip_address = sanitise_string($_SERVER['REMOTE_ADDR']);
+
+ if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+ $ip_address = array_pop(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));
+ } elseif (!empty($_SERVER['HTTP_X_REAL_IP'])) {
+ $ip_address = array_pop(explode(',', $_SERVER['HTTP_X_REAL_IP']));
+ } else {
+ $ip_address = $_SERVER['REMOTE_ADDR'];
+ }
+ $ip_address = sanitise_string($ip_address);
+
$performed_by = elgg_get_logged_in_user_guid();
if (isset($object->access_id)) {
diff --git a/engine/lib/tags.php b/engine/lib/tags.php
index a0887d0f3..586a9b9e4 100644
--- a/engine/lib/tags.php
+++ b/engine/lib/tags.php
@@ -48,7 +48,7 @@ function calculate_tag_size($min, $max, $number_of_tags, $buckets = 6) {
* @param array $tags The array of tags.
* @param int $buckets The number of buckets
*
- * @return An associated array of tags with a weighting, this can then be mapped to a display class.
+ * @return array An associated array of tags with a weighting, this can then be mapped to a display class.
* @access private
*/
function generate_tag_cloud(array $tags, $buckets = 6) {
@@ -114,8 +114,8 @@ function generate_tag_cloud(array $tags, $buckets = 6) {
*
* joins => array() Additional joins
*
- * @return false/array - if no tags or error, false
- * otherwise, array of objects with ->tag and ->total values
+ * @return object[]|false If no tags or error, false
+ * otherwise, array of objects with ->tag and ->total values
* @since 1.7.1
*/
function elgg_get_tags(array $options = array()) {
@@ -172,6 +172,7 @@ function elgg_get_tags(array $options = array()) {
// catch for tags that were spaces
$wheres[] = "msv.string != ''";
+ $sanitised_tags = array();
foreach ($options['tag_names'] as $tag) {
$sanitised_tags[] = '"' . sanitise_string($tag) . '"';
}
diff --git a/engine/lib/upgrade.php b/engine/lib/upgrade.php
index f4f4b16f5..158ec9ec1 100644
--- a/engine/lib/upgrade.php
+++ b/engine/lib/upgrade.php
@@ -17,8 +17,9 @@
* @access private
*/
function upgrade_code($version, $quiet = FALSE) {
+ // do not remove - upgrade scripts depend on this
global $CONFIG;
-
+
$version = (int) $version;
$upgrade_path = elgg_get_config('path') . 'engine/lib/upgrades/';
$processed_upgrades = elgg_get_processed_upgrades();
@@ -244,7 +245,7 @@ function version_upgrade() {
// No version number? Oh snap...this is an upgrade from a clean installation < 1.7.
// Run all upgrades without error reporting and hope for the best.
- // See http://trac.elgg.org/elgg/ticket/1432 for more.
+ // See https://github.com/elgg/elgg/issues/1432 for more.
$quiet = !$dbversion;
// Note: Database upgrades are deprecated as of 1.8. Use code upgrades. See #1433
@@ -291,7 +292,6 @@ function elgg_upgrade_bootstrap_17_to_18() {
'2011010101.php',
);
- $upgrades_17 = array();
$upgrade_files = elgg_get_upgrade_files();
$processed_upgrades = array();
@@ -354,15 +354,12 @@ function _elgg_upgrade_unlock() {
* @access private
*/
function _elgg_upgrade_is_locked() {
- global $CONFIG, $DB_QUERY_CACHE;
-
+ global $CONFIG;
+
$is_locked = count(get_data("show tables like '{$CONFIG->dbprefix}upgrade_lock'"));
-
- // Invalidate query cache
- if ($DB_QUERY_CACHE) {
- $DB_QUERY_CACHE->clear();
- elgg_log("Query cache invalidated", 'NOTICE');
- }
-
+
+ // @todo why?
+ _elgg_invalidate_query_cache();
+
return $is_locked;
}
diff --git a/engine/lib/upgrades/2009102801.php b/engine/lib/upgrades/2009102801.php
index cab9a6835..3ad113fb2 100644
--- a/engine/lib/upgrades/2009102801.php
+++ b/engine/lib/upgrades/2009102801.php
@@ -203,14 +203,15 @@ function user_file_matrix($guid) {
return "$time_created/$user->guid/";
}
-global $DB_QUERY_CACHE, $DB_PROFILE, $ENTITY_CACHE;
+global $ENTITY_CACHE, $CONFIG;
/**
* Upgrade file locations
*/
$users = mysql_query("SELECT guid, username
FROM {$CONFIG->dbprefix}users_entity WHERE username != ''");
while ($user = mysql_fetch_object($users)) {
- $DB_QUERY_CACHE = $DB_PROFILE = $ENTITY_CACHE = array();
+ $ENTITY_CACHE = array();
+ _elgg_invalidate_query_cache();
$to = $CONFIG->dataroot . user_file_matrix($user->guid);
foreach (array('1_0', '1_1', '1_6') as $version) {
diff --git a/engine/lib/upgrades/2010033101.php b/engine/lib/upgrades/2010033101.php
index 0bffee001..4779295fd 100644
--- a/engine/lib/upgrades/2010033101.php
+++ b/engine/lib/upgrades/2010033101.php
@@ -1,7 +1,7 @@
<?php
/**
- * Conditional upgrade for UTF8 as described in http://trac.elgg.org/ticket/1928
+ * Conditional upgrade for UTF8 as described in https://github.com/elgg/elgg/issues/1928
*/
// get_version() returns the code version.
diff --git a/engine/lib/upgrades/2010061501.php b/engine/lib/upgrades/2010061501.php
index 9ff7d3102..744c28fd5 100644
--- a/engine/lib/upgrades/2010061501.php
+++ b/engine/lib/upgrades/2010061501.php
@@ -45,7 +45,7 @@ if ($dbversion < 2009100701) {
}
}
- global $DB_QUERY_CACHE, $DB_PROFILE, $ENTITY_CACHE;
+ global $ENTITY_CACHE;
/**
Upgrade file locations
@@ -60,7 +60,9 @@ if ($dbversion < 2009100701) {
$users = mysql_query("SELECT guid, username FROM {$CONFIG->dbprefix}users_entity
WHERE username != ''", $link);
while ($user = mysql_fetch_object($users)) {
- $DB_QUERY_CACHE = $DB_PROFILE = $ENTITY_CACHE = array();
+ $ENTITY_CACHE = array();
+ _elgg_invalidate_query_cache();
+
$to = $CONFIG->dataroot . user_file_matrix($user->guid);
foreach (array('1_0', '1_1', '1_6') as $version) {
diff --git a/engine/lib/upgrades/2010071001.php b/engine/lib/upgrades/2010071001.php
index 1b5d379d8..5594493a8 100644
--- a/engine/lib/upgrades/2010071001.php
+++ b/engine/lib/upgrades/2010071001.php
@@ -30,11 +30,12 @@ function user_file_matrix_2010071001($guid) {
$sizes = array('large', 'medium', 'small', 'tiny', 'master', 'topbar');
-global $DB_QUERY_CACHE, $DB_PROFILE, $ENTITY_CACHE, $CONFIG;
+global $ENTITY_CACHE, $CONFIG;
$users = mysql_query("SELECT guid, username FROM {$CONFIG->dbprefix}users_entity
WHERE username != ''");
while ($user = mysql_fetch_object($users)) {
- $DB_QUERY_CACHE = $DB_PROFILE = $ENTITY_CACHE = array();
+ $ENTITY_CACHE = array();
+ _elgg_invalidate_query_cache();
$user_directory = user_file_matrix_2010071001($user->guid);
if (!$user_directory) {
diff --git a/engine/lib/upgrades/2010071002.php b/engine/lib/upgrades/2010071002.php
index 30bd6538c..52aa15ef5 100644
--- a/engine/lib/upgrades/2010071002.php
+++ b/engine/lib/upgrades/2010071002.php
@@ -4,12 +4,13 @@
*/
// loop through all users checking collections and notifications
-global $DB_QUERY_CACHE, $DB_PROFILE, $ENTITY_CACHE, $CONFIG;
+global $ENTITY_CACHE, $CONFIG;
global $NOTIFICATION_HANDLERS;
$users = mysql_query("SELECT guid, username FROM {$CONFIG->dbprefix}users_entity
WHERE username != ''");
while ($user = mysql_fetch_object($users)) {
- $DB_QUERY_CACHE = $DB_PROFILE = $ENTITY_CACHE = array();
+ $ENTITY_CACHE = array();
+ _elgg_invalidate_query_cache();
$user = get_entity($user->guid);
foreach ($NOTIFICATION_HANDLERS as $method => $foo) {
diff --git a/engine/lib/upgrades/2011052801.php b/engine/lib/upgrades/2011052801.php
index 8084bc06c..b5a8e1018 100644
--- a/engine/lib/upgrades/2011052801.php
+++ b/engine/lib/upgrades/2011052801.php
@@ -2,7 +2,7 @@
/**
* Make sure all users have the relationship member_of_site
*/
-global $DB_QUERY_CACHE, $DB_PROFILE, $ENTITY_CACHE, $CONFIG;
+global $ENTITY_CACHE;
$db_prefix = get_config('dbprefix');
$limit = 100;
@@ -17,7 +17,8 @@ $q = "SELECT e.* FROM {$db_prefix}entities e
$users = get_data($q);
while ($users) {
- $DB_QUERY_CACHE = $DB_PROFILE = $ENTITY_CACHE = array();
+ $ENTITY_CACHE = array();
+ _elgg_invalidate_query_cache();
// do manually to not trigger any events because these aren't new users.
foreach ($users as $user) {
diff --git a/engine/lib/upgrades/2012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php b/engine/lib/upgrades/2012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php
index 07732f261..780038c32 100644
--- a/engine/lib/upgrades/2012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php
+++ b/engine/lib/upgrades/2012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php
@@ -3,7 +3,7 @@
* Elgg 1.8.3 upgrade 2012041801
* multiple_user_tokens
*
- * Fixes http://trac.elgg.org/ticket/4291
+ * Fixes https://github.com/elgg/elgg/issues/4291
* Removes the unique index on users_apisessions for user_guid and site_guid
*/
diff --git a/engine/lib/upgrades/2013030600-1.8.13-update_user_location-8999eb8bf1bdd9a3.php b/engine/lib/upgrades/2013030600-1.8.13-update_user_location-8999eb8bf1bdd9a3.php
new file mode 100644
index 000000000..8eccf05e2
--- /dev/null
+++ b/engine/lib/upgrades/2013030600-1.8.13-update_user_location-8999eb8bf1bdd9a3.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * Elgg 1.8.14 upgrade 2013030600
+ * update_user_location
+ *
+ * Before Elgg 1.8, a location like "London, England" would be stored as an array.
+ * This script turns that back into a string.
+ */
+
+$ia = elgg_set_ignore_access(true);
+$options = array(
+ 'type' => 'user',
+ 'limit' => 0,
+);
+$batch = new ElggBatch('elgg_get_entities', $options);
+
+foreach ($batch as $entity) {
+ _elgg_invalidate_query_cache();
+
+ if (is_array($entity->location)) {
+ $entity->location = implode(', ', $entity->location);
+ }
+}
+elgg_set_ignore_access($ia);
diff --git a/engine/lib/upgrades/2013051700-1.8.15-add_missing_group_index-52a63a3a3ffaced2.php b/engine/lib/upgrades/2013051700-1.8.15-add_missing_group_index-52a63a3a3ffaced2.php
new file mode 100644
index 000000000..ee99bdbc8
--- /dev/null
+++ b/engine/lib/upgrades/2013051700-1.8.15-add_missing_group_index-52a63a3a3ffaced2.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Elgg 1.8.15 upgrade 2013051700
+ * add_missing_group_index
+ *
+ * Some Elgg sites are missing the groups_entity full text index on name and
+ * description. This checks if it exists and adds it if it does not.
+ */
+
+$db_prefix = elgg_get_config('dbprefix');
+
+$full_text_index_exists = false;
+$results = get_data("SHOW INDEX FROM {$db_prefix}groups_entity");
+if ($results) {
+ foreach ($results as $result) {
+ if ($result->Index_type === 'FULLTEXT') {
+ $full_text_index_exists = true;
+ }
+ }
+}
+
+if ($full_text_index_exists == false) {
+ $query = "ALTER TABLE {$db_prefix}groups_entity
+ ADD FULLTEXT name_2 (name, description)";
+ if (!update_data($query)) {
+ elgg_log("Failed to add full text index to groups_entity table", 'ERROR');
+ }
+}
diff --git a/engine/lib/upgrades/2013052900-1.8.15-ipv6_in_syslog-f5c2cc0196e9e731.php b/engine/lib/upgrades/2013052900-1.8.15-ipv6_in_syslog-f5c2cc0196e9e731.php
new file mode 100644
index 000000000..d333a6cd2
--- /dev/null
+++ b/engine/lib/upgrades/2013052900-1.8.15-ipv6_in_syslog-f5c2cc0196e9e731.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Elgg 1.8.15 upgrade 2013052900
+ * ipv6_in_syslog
+ *
+ * Upgrade the ip column in system_log to be able to store ipv6 addresses
+ */
+
+$db_prefix = elgg_get_config('dbprefix');
+$q = "ALTER TABLE {$db_prefix}system_log MODIFY COLUMN ip_address varchar(46) NOT NULL";
+
+update_data($q); \ No newline at end of file
diff --git a/engine/lib/upgrades/2013060900-1.8.15-site_secret-404fc165cf9e0ac9.php b/engine/lib/upgrades/2013060900-1.8.15-site_secret-404fc165cf9e0ac9.php
new file mode 100644
index 000000000..538d74dd6
--- /dev/null
+++ b/engine/lib/upgrades/2013060900-1.8.15-site_secret-404fc165cf9e0ac9.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Elgg 1.8.15 upgrade 2013060900
+ * site_secret
+ *
+ * Description
+ */
+
+$strength = _elgg_get_site_secret_strength();
+
+if ($strength !== 'strong') {
+ // a new key is needed immediately
+ register_translations(elgg_get_root_path() . 'languages/');
+
+ elgg_add_admin_notice('weak_site_key', elgg_echo("upgrade:site_secret_warning:$strength"));
+}
diff --git a/engine/lib/upgrades/create_upgrade.php b/engine/lib/upgrades/create_upgrade.php
index 3652e18a2..b34f31b7e 100644
--- a/engine/lib/upgrades/create_upgrade.php
+++ b/engine/lib/upgrades/create_upgrade.php
@@ -93,7 +93,7 @@ if (!$h) {
die("Could not open file $upgrade_file");
}
-if (!fputs($h, $upgrade_code)) {
+if (!fwrite($h, $upgrade_code)) {
die("Could not write to $upgrade_file");
} else {
elgg_set_version_dot_php_version($upgrade_version);
@@ -128,8 +128,9 @@ function elgg_set_version_dot_php_version($version) {
rewind($h);
- fputs($h, $out);
+ fwrite($h, $out);
fclose($h);
+ return true;
}
/**
diff --git a/engine/lib/user_settings.php b/engine/lib/user_settings.php
index e4069fb53..0e36dc46d 100644
--- a/engine/lib/user_settings.php
+++ b/engine/lib/user_settings.php
@@ -265,9 +265,9 @@ function elgg_set_user_default_access() {
* @access private
*/
function usersettings_pagesetup() {
- if (elgg_get_context() == "settings") {
- $user = elgg_get_page_owner_entity();
+ $user = elgg_get_page_owner_entity();
+ if ($user && elgg_get_context() == "settings") {
$params = array(
'name' => '1_account',
'text' => elgg_echo('usersettings:user:opt:linktext'),
@@ -308,7 +308,7 @@ function usersettings_page_handler($page) {
$user = get_user_by_username($page[1]);
elgg_set_page_owner_guid($user->guid);
} else {
- $user = elgg_get_logged_in_user_guid();
+ $user = elgg_get_logged_in_user_entity();
elgg_set_page_owner_guid($user->guid);
}
@@ -332,6 +332,7 @@ function usersettings_page_handler($page) {
require $path;
return true;
}
+ return false;
}
/**
diff --git a/engine/lib/users.php b/engine/lib/users.php
index 95ef9d176..a8fb9121c 100644
--- a/engine/lib/users.php
+++ b/engine/lib/users.php
@@ -237,7 +237,7 @@ function make_user_admin($user_guid) {
}
$r = update_data("UPDATE {$CONFIG->dbprefix}users_entity set admin='yes' where guid=$user_guid");
- invalidate_cache_for_entity($user_guid);
+ _elgg_invalidate_cache_for_entity($user_guid);
return $r;
}
@@ -273,7 +273,7 @@ function remove_user_admin($user_guid) {
}
$r = update_data("UPDATE {$CONFIG->dbprefix}users_entity set admin='no' where guid=$user_guid");
- invalidate_cache_for_entity($user_guid);
+ _elgg_invalidate_cache_for_entity($user_guid);
return $r;
}
@@ -290,7 +290,7 @@ function remove_user_admin($user_guid) {
* @param int $limit Number of results to return
* @param int $offset Any indexing offset
*
- * @return false|array On success, an array of ElggSites
+ * @return ElggSite[]|false On success, an array of ElggSites
*/
function get_user_sites($user_guid, $limit = 10, $offset = 0) {
$user_guid = (int)$user_guid;
@@ -302,7 +302,7 @@ function get_user_sites($user_guid, $limit = 10, $offset = 0) {
'relationship' => 'member_of_site',
'relationship_guid' => $user_guid,
'inverse_relationship' => FALSE,
- 'types' => 'site',
+ 'type' => 'site',
'limit' => $limit,
'offset' => $offset,
));
@@ -343,8 +343,6 @@ function user_add_friend($user_guid, $friend_guid) {
* @return bool Depending on success
*/
function user_remove_friend($user_guid, $friend_guid) {
- global $CONFIG;
-
$user_guid = (int) $user_guid;
$friend_guid = (int) $friend_guid;
@@ -379,7 +377,7 @@ function user_is_friend($user_guid, $friend_guid) {
* @param int $limit Number of results to return (default 10)
* @param int $offset Indexing offset, if any
*
- * @return false|array Either an array of ElggUsers or false, depending on success
+ * @return ElggUser[]|false Either an array of ElggUsers or false, depending on success
*/
function get_user_friends($user_guid, $subtype = ELGG_ENTITIES_ANY_VALUE, $limit = 10,
$offset = 0) {
@@ -387,8 +385,8 @@ $offset = 0) {
return elgg_get_entities_from_relationship(array(
'relationship' => 'friend',
'relationship_guid' => $user_guid,
- 'types' => 'user',
- 'subtypes' => $subtype,
+ 'type' => 'user',
+ 'subtype' => $subtype,
'limit' => $limit,
'offset' => $offset
));
@@ -402,7 +400,7 @@ $offset = 0) {
* @param int $limit Number of results to return (default 10)
* @param int $offset Indexing offset, if any
*
- * @return false|array Either an array of ElggUsers or false, depending on success
+ * @return ElggUser[]|false Either an array of ElggUsers or false, depending on success
*/
function get_user_friends_of($user_guid, $subtype = ELGG_ENTITIES_ANY_VALUE, $limit = 10,
$offset = 0) {
@@ -411,8 +409,8 @@ $offset = 0) {
'relationship' => 'friend',
'relationship_guid' => $user_guid,
'inverse_relationship' => TRUE,
- 'types' => 'user',
- 'subtypes' => $subtype,
+ 'type' => 'user',
+ 'subtype' => $subtype,
'limit' => $limit,
'offset' => $offset
));
@@ -428,7 +426,7 @@ $offset = 0) {
* @param int $timelower The earliest time the entity can have been created. Default: all
* @param int $timeupper The latest time the entity can have been created. Default: all
*
- * @return false|array An array of ElggObjects or false, depending on success
+ * @return ElggObject[]|false An array of ElggObjects or false, depending on success
*/
function get_user_friends_objects($user_guid, $subtype = ELGG_ENTITIES_ANY_VALUE, $limit = 10,
$offset = 0, $timelower = 0, $timeupper = 0) {
@@ -555,13 +553,18 @@ function get_user($guid) {
function get_user_by_username($username) {
global $CONFIG, $USERNAME_TO_GUID_MAP_CACHE;
+ // Fixes #6052. Username is frequently sniffed from the path info, which,
+ // unlike $_GET, is not URL decoded. If the username was not URL encoded,
+ // this is harmless.
+ $username = rawurldecode($username);
+
$username = sanitise_string($username);
$access = get_access_sql_suffix('e');
// Caching
if ((isset($USERNAME_TO_GUID_MAP_CACHE[$username]))
- && (retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]))) {
- return retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]);
+ && (_elgg_retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]))) {
+ return _elgg_retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]);
}
$query = "SELECT e.* from {$CONFIG->dbprefix}users_entity u
@@ -594,9 +597,9 @@ function get_user_by_code($code) {
// Caching
if ((isset($CODE_TO_GUID_MAP_CACHE[$code]))
- && (retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]))) {
+ && (_elgg_retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]))) {
- return retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]);
+ return _elgg_retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]);
}
$query = "SELECT e.* from {$CONFIG->dbprefix}users_entity u
@@ -675,25 +678,22 @@ function find_active_users($seconds = 600, $limit = 10, $offset = 0, $count = fa
* @return bool
*/
function send_new_password_request($user_guid) {
- global $CONFIG;
-
$user_guid = (int)$user_guid;
$user = get_entity($user_guid);
- if ($user) {
+ if ($user instanceof ElggUser) {
// generate code
$code = generate_random_cleartext_password();
$user->setPrivateSetting('passwd_conf_code', $code);
-
// generate link
- $link = $CONFIG->site->url . "resetpassword?u=$user_guid&c=$code";
+ $link = elgg_get_site_url() . "resetpassword?u=$user_guid&c=$code";
// generate email
$email = elgg_echo('email:resetreq:body', array($user->name, $_SERVER['REMOTE_ADDR'], $link));
- return notify_user($user->guid, $CONFIG->site->guid,
- elgg_echo('email:resetreq:subject'), $email, NULL, 'email');
+ return notify_user($user->guid, elgg_get_site_entity()->guid,
+ elgg_echo('email:resetreq:subject'), $email, array(), 'email');
}
return false;
@@ -710,19 +710,18 @@ function send_new_password_request($user_guid) {
* @return bool
*/
function force_user_password_reset($user_guid, $password) {
- global $CONFIG;
-
$user = get_entity($user_guid);
+ if ($user instanceof ElggUser) {
+ $ia = elgg_set_ignore_access();
- if ($user) {
- $salt = generate_random_cleartext_password(); // Reset the salt
- $user->salt = $salt;
+ $user->salt = generate_random_cleartext_password();
+ $hash = generate_user_password($user, $password);
+ $user->password = $hash;
+ $result = (bool)$user->save();
- $hash = generate_user_password($user, $password);
+ elgg_set_ignore_access($ia);
- $query = "UPDATE {$CONFIG->dbprefix}users_entity
- set password='$hash', salt='$salt' where guid=$user_guid";
- return update_data($query);
+ return $result;
}
return false;
@@ -742,7 +741,7 @@ function execute_new_password_request($user_guid, $conf_code) {
$user_guid = (int)$user_guid;
$user = get_entity($user_guid);
- if ($user) {
+ if ($user instanceof ElggUser) {
$saved_code = $user->getPrivateSetting('passwd_conf_code');
if ($saved_code && $saved_code == $conf_code) {
@@ -756,7 +755,7 @@ function execute_new_password_request($user_guid, $conf_code) {
$email = elgg_echo('email:resetpassword:body', array($user->name, $password));
return notify_user($user->guid, $CONFIG->site->guid,
- elgg_echo('email:resetpassword:subject'), $email, NULL, 'email');
+ elgg_echo('email:resetpassword:subject'), $email, array(), 'email');
}
}
}
@@ -841,7 +840,7 @@ function validate_username($username) {
for ($n = 0; $n < strlen($blacklist2); $n++) {
if (strpos($username, $blacklist2[$n]) !== false) {
$msg = elgg_echo('registration:invalidchars', array($blacklist2[$n], $blacklist2));
- $msg = htmlentities($msg, ENT_COMPAT, 'UTF-8');
+ $msg = htmlspecialchars($msg, ENT_QUOTES, 'UTF-8');
throw new RegistrationException($msg);
}
}
@@ -908,13 +907,11 @@ function validate_email_address($address) {
* @param string $invitecode An invite code from a friend
*
* @return int|false The new user's GUID; false on failure
+ * @throws RegistrationException
*/
function register_user($username, $password, $name, $email,
$allow_multiple_emails = false, $friend_guid = 0, $invitecode = '') {
- // Load the configuration
- global $CONFIG;
-
// no need to trim password.
$username = trim($username);
$name = trim(strip_tags($name));
@@ -1031,7 +1028,7 @@ function elgg_get_user_validation_status($user_guid) {
'metadata_name' => 'validated'
));
if ($md == false) {
- return;
+ return null;
}
if ($md[0]->value) {
@@ -1067,10 +1064,10 @@ function collections_submenu_items() {
* @return bool
* @access private
*/
-function friends_page_handler($page_elements, $handler) {
+function friends_page_handler($segments, $handler) {
elgg_set_context('friends');
- if (isset($page_elements[0]) && $user = get_user_by_username($page_elements[0])) {
+ if (isset($segments[0]) && $user = get_user_by_username($segments[0])) {
elgg_set_page_owner_guid($user->getGUID());
}
if (elgg_get_logged_in_user_guid() == elgg_get_page_owner_guid()) {
@@ -1099,6 +1096,7 @@ function friends_page_handler($page_elements, $handler) {
* @access private
*/
function collections_page_handler($page_elements) {
+ gatekeeper();
elgg_set_context('friends');
$base = elgg_get_config('path');
if (isset($page_elements[0])) {
@@ -1197,13 +1195,11 @@ function set_last_login($user_guid) {
* @param string $object_type user
* @param ElggUser $object User object
*
- * @return bool
+ * @return void
* @access private
*/
function user_create_hook_add_site_relationship($event, $object_type, $object) {
- global $CONFIG;
-
- add_entity_relationship($object->getGUID(), 'member_of_site', $CONFIG->site->getGUID());
+ add_entity_relationship($object->getGUID(), 'member_of_site', elgg_get_site_entity()->guid);
}
/**
@@ -1233,6 +1229,7 @@ function user_avatar_hook($hook, $entity_type, $returnvalue, $params) {
*/
function elgg_user_hover_menu($hook, $type, $return, $params) {
$user = $params['entity'];
+ /* @var ElggUser $user */
if (elgg_is_logged_in()) {
if (elgg_get_logged_in_user_guid() != $user->guid) {
@@ -1309,7 +1306,12 @@ function elgg_user_hover_menu($hook, $type, $return, $params) {
/**
* Setup the menu shown with an entity
*
+ * @param string $hook
+ * @param string $type
+ * @param array $return
+ * @param array $params
* @return array
+ *
* @access private
*/
function elgg_users_setup_entity_menu($hook, $type, $return, $params) {
@@ -1321,6 +1323,7 @@ function elgg_users_setup_entity_menu($hook, $type, $return, $params) {
if (!elgg_instanceof($entity, 'user')) {
return $return;
}
+ /* @var ElggUser $entity */
if ($entity->isBanned()) {
$banned = elgg_echo('banned');
@@ -1334,9 +1337,10 @@ function elgg_users_setup_entity_menu($hook, $type, $return, $params) {
} else {
$return = array();
if (isset($entity->location)) {
+ $location = htmlspecialchars($entity->location, ENT_QUOTES, 'UTF-8', false);
$options = array(
'name' => 'location',
- 'text' => "<span>$entity->location</span>",
+ 'text' => "<span>$location</span>",
'href' => false,
'priority' => 150,
);
@@ -1587,7 +1591,7 @@ function users_init() {
/**
* Runs unit tests for ElggObject
*
- * @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/views.php b/engine/lib/views.php
index 01291b889..1142461fe 100644
--- a/engine/lib/views.php
+++ b/engine/lib/views.php
@@ -218,7 +218,7 @@ function elgg_register_ajax_view($view) {
/**
* Unregister a view for ajax calls
- *
+ *
* @param string $view The view name
* @return void
* @since 1.8.3
@@ -369,7 +369,7 @@ function elgg_view_exists($view, $viewtype = '', $recurse = true) {
* view, $view_name plugin hook.
*
* @warning Any variables in $_SESSION will override passed vars
- * upon name collision. See {@trac #2124}.
+ * upon name collision. See https://github.com/Elgg/Elgg/issues/2124
*
* @param string $view The name and location of the view to use
* @param array $vars Variables to pass to the view.
@@ -795,7 +795,7 @@ function elgg_view_menu($menu_name, array $vars = array()) {
* - bool 'full_view' Whether to show a full or condensed view.
*
* @tip This function can automatically appends annotations to entities if in full
- * view and a handler is registered for the entity:annotate. See {@trac 964} and
+ * view and a handler is registered for the entity:annotate. See https://github.com/Elgg/Elgg/issues/964 and
* {@link elgg_view_entity_annotations()}.
*
* @param ElggEntity $entity The entity to display
@@ -992,6 +992,11 @@ function elgg_view_annotation(ElggAnnotation $annotation, array $vars = array(),
function elgg_view_entity_list($entities, $vars = array(), $offset = 0, $limit = 10, $full_view = true,
$list_type_toggle = true, $pagination = true) {
+ if (!$vars["limit"] && !$vars["offset"]) {
+ // no need for pagination if listing is unlimited
+ $vars["pagination"] = false;
+ }
+
if (!is_int($offset)) {
$offset = (int)get_input('offset', 0);
}
@@ -1064,8 +1069,13 @@ function elgg_view_annotation_list($annotations, array $vars = array()) {
'full_view' => true,
'offset_key' => 'annoff',
);
-
+
$vars = array_merge($defaults, $vars);
+
+ if (!$vars["limit"] && !$vars["offset"]) {
+ // no need for pagination if listing is unlimited
+ $vars["pagination"] = false;
+ }
return elgg_view('page/components/list', $vars);
}
@@ -1107,7 +1117,7 @@ function elgg_view_entity_annotations(ElggEntity $entity, $full_view = true) {
* This is a shortcut for {@elgg_view page/elements/title}.
*
* @param string $title The page title
- * @param array $vars View variables (was submenu be displayed? (deprecated))
+ * @param array $vars View variables (was submenu be displayed? (deprecated))
*
* @return string The HTML (etc)
*/
@@ -1179,7 +1189,7 @@ function elgg_view_comments($entity, $add_comment = true, array $vars = array())
*
* @param string $image The icon and other information
* @param string $body Description content
- * @param array $vars Additional parameters for the view
+ * @param array $vars Additional parameters for the view
*
* @return string
* @since 1.8.0
@@ -1236,15 +1246,17 @@ function elgg_view_river_item($item, array $vars = array()) {
// subject is disabled or subject/object deleted
return '';
}
+
+ // @todo this needs to be cleaned up
// Don't hide objects in closed groups that a user can see.
- // see http://trac.elgg.org/ticket/4789
-// else {
-// // hide based on object's container
-// $visibility = ElggGroupItemVisibility::factory($object->container_guid);
-// if ($visibility->shouldHideItems) {
-// return '';
-// }
-// }
+ // see https://github.com/elgg/elgg/issues/4789
+ // else {
+ // // hide based on object's container
+ // $visibility = ElggGroupItemVisibility::factory($object->container_guid);
+ // if ($visibility->shouldHideItems) {
+ // return '';
+ // }
+ // }
$vars['item'] = $item;
@@ -1308,7 +1320,7 @@ function elgg_view_form($action, $form_vars = array(), $body_vars = array()) {
/**
* View an item in a list
*
- * @param object $item ElggEntity or ElggAnnotation
+ * @param ElggEntity|ElggAnnotation $item
* @param array $vars Additional parameters for the rendering
*
* @return string
@@ -1332,12 +1344,12 @@ function elgg_view_list_item($item, array $vars = array()) {
/**
* View one of the elgg sprite icons
- *
+ *
* Shorthand for <span class="elgg-icon elgg-icon-$name"></span>
- *
+ *
* @param string $name The specific icon to display
* @param string $class Additional class: float, float-alt, or custom class
- *
+ *
* @return string The html for displaying an icon
*/
function elgg_view_icon($name, $class = '') {
@@ -1451,17 +1463,13 @@ function elgg_get_views($dir, $base) {
*/
function elgg_view_tree($view_root, $viewtype = "") {
global $CONFIG;
- static $treecache;
+ static $treecache = array();
// Get viewtype
if (!$viewtype) {
$viewtype = elgg_get_viewtype();
}
- // Has the treecache been initialised?
- if (!isset($treecache)) {
- $treecache = array();
- }
// A little light internal caching
if (!empty($treecache[$view_root])) {
return $treecache[$view_root];
@@ -1640,7 +1648,7 @@ function elgg_views_boot() {
}
// set default icon sizes - can be overridden in settings.php or with plugin
- if (!$CONFIG->icon_sizes) {
+ if (!isset($CONFIG->icon_sizes)) {
$icon_sizes = array(
'topbar' => array('w' => 16, 'h' => 16, 'square' => TRUE, 'upscale' => TRUE),
'tiny' => array('w' => 25, 'h' => 25, 'square' => TRUE, 'upscale' => TRUE),
diff --git a/engine/lib/web_services.php b/engine/lib/web_services.php
index c8e4a13cc..51cad6f39 100644
--- a/engine/lib/web_services.php
+++ b/engine/lib/web_services.php
@@ -178,7 +178,7 @@ function authenticate_method($method) {
// check if user authentication is required
if ($API_METHODS[$method]["require_user_auth"] == true) {
if ($user_auth_result == false) {
- throw new APIException($user_pam->getFailureMessage());
+ throw new APIException($user_pam->getFailureMessage(), ErrorResult::$RESULT_FAIL_AUTHTOKEN);
}
}
@@ -1166,6 +1166,17 @@ function list_all_apis() {
* @access private
*/
function auth_gettoken($username, $password) {
+ // check if username is an email address
+ if (is_email_address($username)) {
+ $users = get_user_by_email($username);
+
+ // check if we have a unique user
+ if (is_array($users) && (count($users) == 1)) {
+ $username = $users[0]->username;
+ }
+ }
+
+ // validate username and password
if (true === elgg_authenticate($username, $password)) {
$token = create_user_token($username);
if ($token) {
@@ -1195,7 +1206,7 @@ $ERRORS = array();
*
* @return void
* @access private
- *
+ *
* @throws Exception
*/
function _php_api_error_handler($errno, $errmsg, $filename, $linenum, $vars) {
@@ -1267,14 +1278,14 @@ function service_handler($handler, $request) {
$request = explode('/', $request);
// after the handler, the first identifier is response format
- // ex) http://example.org/services/api/rest/xml/?method=test
- $reponse_format = array_shift($request);
+ // ex) http://example.org/services/api/rest/json/?method=test
+ $response_format = array_shift($request);
// Which view - xml, json, ...
- if ($reponse_format) {
- elgg_set_viewtype($reponse_format);
+ if ($response_format && elgg_is_valid_view_type($response_format)) {
+ elgg_set_viewtype($response_format);
} else {
- // default to xml
- elgg_set_viewtype("xml");
+ // default to json
+ elgg_set_viewtype("json");
}
if (!isset($CONFIG->servicehandler) || empty($handler)) {
diff --git a/engine/lib/widgets.php b/engine/lib/widgets.php
index d73dd6330..699462a1b 100644
--- a/engine/lib/widgets.php
+++ b/engine/lib/widgets.php
@@ -336,7 +336,7 @@ function elgg_default_widgets_init() {
*
* @param string $event The event
* @param string $type The type of object
- * @param object $entity The entity being created
+ * @param ElggEntity $entity The entity being created
* @return void
* @access private
*/
@@ -372,6 +372,7 @@ function elgg_create_default_widgets($event, $type, $entity) {
);
$widgets = elgg_get_entities_from_private_settings($options);
+ /* @var ElggWidget[] $widgets */
foreach ($widgets as $widget) {
// change the container and owner
diff --git a/engine/lib/xml.php b/engine/lib/xml.php
index ff82d7e8a..497459d83 100644
--- a/engine/lib/xml.php
+++ b/engine/lib/xml.php
@@ -104,7 +104,7 @@ function serialise_array_to_xml(array $data, $n = 0) {
*
* @param string $xml The XML
*
- * @return object
+ * @return ElggXMLElement
*/
function xml_to_object($xml) {
return new ElggXMLElement($xml);