aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--CHANGES.txt23
-rw-r--r--actions/avatar/remove.php52
-rw-r--r--actions/login.php5
-rw-r--r--actions/profile/edit.php5
-rw-r--r--engine/classes/ElggAttributeLoader.php30
-rw-r--r--engine/classes/ElggBatch.php63
-rw-r--r--engine/classes/ElggEntity.php12
-rw-r--r--engine/classes/ElggFile.php9
-rw-r--r--engine/classes/ElggGroup.php7
-rw-r--r--engine/classes/ElggObject.php8
-rw-r--r--engine/classes/ElggPlugin.php9
-rw-r--r--engine/classes/ElggPluginPackage.php1
-rw-r--r--engine/classes/ElggUser.php9
-rw-r--r--engine/handlers/cache_handler.php8
-rw-r--r--engine/lib/annotations.php10
-rw-r--r--engine/lib/elgglib.php3
-rw-r--r--engine/lib/entities.php94
-rw-r--r--engine/lib/group.php1
-rw-r--r--engine/lib/metadata.php14
-rw-r--r--engine/lib/metastrings.php7
-rw-r--r--engine/lib/navigation.php9
-rw-r--r--engine/lib/output.php8
-rw-r--r--engine/lib/sessions.php3
-rw-r--r--engine/lib/statistics.php10
-rw-r--r--engine/lib/views.php2
-rw-r--r--engine/tests/api/entity_getter_functions.php2
-rw-r--r--engine/tests/api/helpers.php101
-rw-r--r--engine/tests/api/metadata_cache.php7
-rw-r--r--engine/tests/objects/users.php3
-rw-r--r--engine/tests/regression/trac_bugs.php36
-rw-r--r--install/cli/sample_installer.php40
-rw-r--r--js/lib/elgglib.js4
-rw-r--r--js/lib/session.js32
-rw-r--r--js/lib/ui.userpicker.js4
-rw-r--r--js/tests/ElggLibTest.js10
-rw-r--r--js/tests/README5
-rw-r--r--languages/en.php2
-rw-r--r--mod/blog/actions/blog/save.php11
-rw-r--r--mod/blog/start.php13
-rw-r--r--mod/blog/views/default/blog/sidebar/archives.php2
-rw-r--r--mod/bookmarks/pages/bookmarks/all.php3
-rw-r--r--mod/bookmarks/pages/bookmarks/friends.php2
-rw-r--r--mod/bookmarks/pages/bookmarks/owner.php3
-rw-r--r--mod/embed/start.php6
-rw-r--r--mod/file/pages/file/friends.php2
-rw-r--r--mod/file/pages/file/owner.php3
-rw-r--r--mod/file/pages/file/world.php3
-rw-r--r--mod/groups/lib/discussion.php5
-rw-r--r--mod/groups/lib/groups.php7
-rw-r--r--mod/groups/start.php4
-rw-r--r--mod/groups/views/default/object/groupforumtopic.php5
-rw-r--r--mod/messageboard/pages/messageboard/owner.php1
-rw-r--r--mod/pages/pages/pages/friends.php2
-rw-r--r--mod/pages/pages/pages/owner.php2
-rw-r--r--mod/search/search_hooks.php28
-rw-r--r--mod/search/views/default/search/comments/entity.php11
-rw-r--r--mod/search/views/rss/search/comments/entity.php11
-rw-r--r--mod/thewire/pages/thewire/everyone.php2
-rw-r--r--mod/thewire/pages/thewire/friends.php2
-rw-r--r--mod/thewire/pages/thewire/owner.php4
-rw-r--r--pages/account/forgotten_password.php11
-rw-r--r--pages/account/login.php14
-rw-r--r--pages/account/register.php11
-rw-r--r--pages/account/reset_password.php11
-rw-r--r--pages/avatar/edit.php5
-rw-r--r--pages/river.php1
-rw-r--r--version.php2
-rw-r--r--views/default/forms/plugins/settings/save.php6
-rw-r--r--views/default/forms/profile/edit.php13
-rw-r--r--views/default/input/userpicker.php8
-rw-r--r--views/default/js/walled_garden.php28
-rw-r--r--views/default/object/default.php1
-rw-r--r--views/default/object/elements/full.php4
-rw-r--r--views/default/object/elements/summary.php2
-rw-r--r--views/default/page/walled_garden.php15
-rw-r--r--views/default/river/elements/summary.php3
77 files changed, 701 insertions, 217 deletions
diff --git a/.gitignore b/.gitignore
index c0bba2c6c..a1c78c400 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,7 +38,7 @@
!/mod/uservalidationbyemail/
!/mod/zaudio/
-# ignore IDE/hidden/OS cache files
+# ignore IDE/hidden/testing/OS cache files
.*
*~
/nbproject
@@ -49,6 +49,7 @@ Session.vim
tmtags
Thumbs.db
Desktop.ini
+/JsTestDriver-*.jar
# don't ignore travis config
!/.travis.yml
diff --git a/CHANGES.txt b/CHANGES.txt
index 9b79735b3..187dc7e25 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,26 @@
+Version 1.8.16
+(June 25, 2013 from https://github.com/Elgg/Elgg/tree/1.8)
+ Contributing Developers:
+ * Brett Profitt
+ * Cash Costello
+ * Jeff Tilson
+ * Jerome Bakker
+ * Paweł Sroka
+ * Steve Clay
+
+ Security Fixes:
+ * Fixed avatar removal bug (thanks to Jerome Bakker for the first report of this)
+
+ Bugfixes:
+ * Fixed infinite loop when deleting/disabling an entity with > 50 annotations
+ * Fixed deleting log tables in log rotate plugin
+ * Added full text index for groups if missing
+ * Added workaround for IE8 and jumping user avatar
+ * Fixed pagination for members pages
+ * Fixed several internal cache issues
+ * Plus many more bug fixes
+
+
Version 1.8.15
(April 23, 2013 from https://github.com/Elgg/Elgg/tree/1.8)
Contributing Developers:
diff --git a/actions/avatar/remove.php b/actions/avatar/remove.php
index cd38e456a..9cb40a760 100644
--- a/actions/avatar/remove.php
+++ b/actions/avatar/remove.php
@@ -3,32 +3,34 @@
* Avatar remove action
*/
-$guid = get_input('guid');
-$user = get_entity($guid);
-if ($user) {
- // Delete all icons from diskspace
- $icon_sizes = elgg_get_config('icon_sizes');
- foreach ($icon_sizes as $name => $size_info) {
- $file = new ElggFile();
- $file->owner_guid = $guid;
- $file->setFilename("profile/{$guid}{$name}.jpg");
- $filepath = $file->getFilenameOnFilestore();
- if (!$file->delete()) {
- elgg_log("Avatar file remove failed. Remove $filepath manually, please.", 'WARNING');
- }
- }
-
- // Remove crop coords
- unset($user->x1);
- unset($user->x2);
- unset($user->y1);
- unset($user->y2);
-
- // Remove icon
- unset($user->icontime);
- system_message(elgg_echo('avatar:remove:success'));
-} else {
+$user_guid = get_input('guid');
+$user = get_user($user_guid);
+
+if (!$user || !$user->canEdit()) {
register_error(elgg_echo('avatar:remove:fail'));
+ forward(REFERER);
}
+// Delete all icons from diskspace
+$icon_sizes = elgg_get_config('icon_sizes');
+foreach ($icon_sizes as $name => $size_info) {
+ $file = new ElggFile();
+ $file->owner_guid = $user_guid;
+ $file->setFilename("profile/{$user_guid}{$name}.jpg");
+ $filepath = $file->getFilenameOnFilestore();
+ if (!$file->delete()) {
+ elgg_log("Avatar file remove failed. Remove $filepath manually, please.", 'WARNING');
+ }
+}
+
+// Remove crop coords
+unset($user->x1);
+unset($user->x2);
+unset($user->y1);
+unset($user->y2);
+
+// Remove icon
+unset($user->icontime);
+
+system_message(elgg_echo('avatar:remove:success'));
forward(REFERER);
diff --git a/actions/login.php b/actions/login.php
index 1e5e92ede..bd7f91299 100644
--- a/actions/login.php
+++ b/actions/login.php
@@ -9,7 +9,6 @@
// set forward url
if (!empty($_SESSION['last_forward_from'])) {
$forward_url = $_SESSION['last_forward_from'];
- unset($_SESSION['last_forward_from']);
} elseif (get_input('returntoreferer')) {
$forward_url = REFERER;
} else {
@@ -62,5 +61,9 @@ if ($user->language) {
$message = elgg_echo('loginok');
}
+if (isset($_SESSION['last_forward_from'])) {
+ unset($_SESSION['last_forward_from']);
+}
+
system_message($message);
forward($forward_url);
diff --git a/actions/profile/edit.php b/actions/profile/edit.php
index b817463ac..e1f066e82 100644
--- a/actions/profile/edit.php
+++ b/actions/profile/edit.php
@@ -4,6 +4,8 @@
*
*/
+elgg_make_sticky_form('profile:edit');
+
$guid = get_input('guid');
$owner = get_entity($guid);
@@ -80,7 +82,7 @@ if (sizeof($input) > 0) {
);
elgg_delete_metadata($options);
- if(!is_null($value) && ($value !== '')){
+ if (!is_null($value) && ($value !== '')) {
// only create metadata for non empty values (0 is allowed) to prevent metadata records with empty string values #4858
if (isset($accesslevel[$shortname])) {
@@ -107,6 +109,7 @@ if (sizeof($input) > 0) {
// Notify of profile update
elgg_trigger_event('profileupdate', $owner->type, $owner);
+ elgg_clear_sticky_form('profile:edit');
system_message(elgg_echo("profile:saved"));
}
diff --git a/engine/classes/ElggAttributeLoader.php b/engine/classes/ElggAttributeLoader.php
index b91e4b88a..0b770da75 100644
--- a/engine/classes/ElggAttributeLoader.php
+++ b/engine/classes/ElggAttributeLoader.php
@@ -24,7 +24,7 @@ class ElggAttributeLoader {
'time_created',
'time_updated',
'last_action',
- 'enabled'
+ 'enabled',
);
/**
@@ -200,6 +200,8 @@ class ElggAttributeLoader {
// saved, these are stored w/ type "site", but with no sites_entity row. These
// are probably only created in the unit tests.
// @todo Don't save vanilla ElggEntities with type "site"
+
+ $row = $this->filterAddedColumns($row);
$row['guid'] = (int) $row['guid'];
return $row;
}
@@ -209,6 +211,8 @@ class ElggAttributeLoader {
}
}
+ $row = $this->filterAddedColumns($row);
+
// Note: If there are still missing attributes, we're running on a 1.7 or earlier schema. We let
// this pass so the upgrades can run.
@@ -217,4 +221,28 @@ class ElggAttributeLoader {
return $row;
}
+
+ /**
+ * Filter out keys returned by the query which should not appear in the entity's attributes
+ *
+ * @param array $row All columns from the query
+ * @return array Columns acceptable for the entity's attributes
+ */
+ protected function filterAddedColumns($row) {
+ // make an array with keys as acceptable attribute names
+ $acceptable_attrs = self::$primary_attr_names;
+ array_splice($acceptable_attrs, count($acceptable_attrs), 0, $this->secondary_attr_names);
+ $acceptable_attrs = array_combine($acceptable_attrs, $acceptable_attrs);
+
+ // @todo remove these when #4584 is in place
+ $acceptable_attrs['tables_split'] = true;
+ $acceptable_attrs['tables_loaded'] = true;
+
+ foreach ($row as $key => $val) {
+ if (!isset($acceptable_attrs[$key])) {
+ unset($row[$key]);
+ }
+ }
+ return $row;
+ }
}
diff --git a/engine/classes/ElggBatch.php b/engine/classes/ElggBatch.php
index eb93b0f5d..d810ea066 100644
--- a/engine/classes/ElggBatch.php
+++ b/engine/classes/ElggBatch.php
@@ -150,6 +150,20 @@ class ElggBatch
private $incrementOffset = true;
/**
+ * Entities that could not be instantiated during a fetch
+ *
+ * @var stdClass[]
+ */
+ private $incompleteEntities = array();
+
+ /**
+ * Total number of incomplete entities fetched
+ *
+ * @var int
+ */
+ private $totalIncompletes = 0;
+
+ /**
* Batches operations on any elgg_get_*() or compatible function that supports
* an options array.
*
@@ -222,6 +236,17 @@ class ElggBatch
}
/**
+ * Tell the process that an entity was incomplete during a fetch
+ *
+ * @param stdClass $row
+ *
+ * @access private
+ */
+ public function reportIncompleteEntity(stdClass $row) {
+ $this->incompleteEntities[] = $row;
+ }
+
+ /**
* Fetches the next chunk of results
*
* @return bool
@@ -260,27 +285,47 @@ class ElggBatch
if ($this->incrementOffset) {
$offset = $this->offset + $this->retrievedResults;
} else {
- $offset = $this->offset;
+ $offset = $this->offset + $this->totalIncompletes;
}
$current_options = array(
'limit' => $limit,
- 'offset' => $offset
+ 'offset' => $offset,
+ '__ElggBatch' => $this,
);
$options = array_merge($this->options, $current_options);
- $getter = $this->getter;
- if (is_string($getter)) {
- $this->results = $getter($options);
- } else {
- $this->results = call_user_func_array($getter, array($options));
+ $this->incompleteEntities = array();
+ $this->results = call_user_func_array($this->getter, array($options));
+
+ $num_results = count($this->results);
+ $num_incomplete = count($this->incompleteEntities);
+
+ $this->totalIncompletes += $num_incomplete;
+
+ if ($this->incompleteEntities) {
+ // pad the front of the results with nulls representing the incompletes
+ array_splice($this->results, 0, 0, array_pad(array(), $num_incomplete, null));
+ // ...and skip past them
+ reset($this->results);
+ for ($i = 0; $i < $num_incomplete; $i++) {
+ next($this->results);
+ }
}
if ($this->results) {
$this->chunkIndex++;
- $this->resultIndex = 0;
- $this->retrievedResults += count($this->results);
+
+ // let the system know we've jumped past the nulls
+ $this->resultIndex = $num_incomplete;
+
+ $this->retrievedResults += ($num_results + $num_incomplete);
+ if ($num_results == 0) {
+ // This fetch was *all* incompletes! We need to fetch until we can either
+ // offer at least one row to iterate over, or give up.
+ return $this->getNextResultsChunk();
+ }
return true;
} else {
return false;
diff --git a/engine/classes/ElggEntity.php b/engine/classes/ElggEntity.php
index 8b3ceb551..dd1c7c114 100644
--- a/engine/classes/ElggEntity.php
+++ b/engine/classes/ElggEntity.php
@@ -1270,15 +1270,23 @@ abstract class ElggEntity extends ElggData implements
public function save() {
$guid = $this->getGUID();
if ($guid > 0) {
- _elgg_cache_entity($this);
- return update_entity(
+ // See #5600. This ensures the lower level can_edit_entity() check will use a
+ // fresh entity from the DB so it sees the persisted owner_guid
+ _elgg_disable_caching_for_entity($guid);
+
+ $ret = update_entity(
$guid,
$this->get('owner_guid'),
$this->get('access_id'),
$this->get('container_guid'),
$this->get('time_created')
);
+
+ _elgg_enable_caching_for_entity($guid);
+ _elgg_cache_entity($this);
+
+ return $ret;
} else {
// Create a new entity (nb: using attribute array directly
// 'cos set function does something special!)
diff --git a/engine/classes/ElggFile.php b/engine/classes/ElggFile.php
index 3e9c24c17..23080834b 100644
--- a/engine/classes/ElggFile.php
+++ b/engine/classes/ElggFile.php
@@ -275,9 +275,14 @@ class ElggFile extends ElggObject {
*/
public function delete() {
$fs = $this->getFilestore();
- if ($fs->delete($this)) {
- return parent::delete();
+
+ $result = $fs->delete($this);
+
+ if ($this->getGUID() && $result) {
+ $result = parent::delete();
}
+
+ return $result;
}
/**
diff --git a/engine/classes/ElggGroup.php b/engine/classes/ElggGroup.php
index 61f9163d5..7e69b7a84 100644
--- a/engine/classes/ElggGroup.php
+++ b/engine/classes/ElggGroup.php
@@ -352,7 +352,12 @@ class ElggGroup extends ElggEntity
}
// Now save specific stuff
- return create_group_entity($this->get('guid'), $this->get('name'), $this->get('description'));
+
+ _elgg_disable_caching_for_entity($this->guid);
+ $ret = create_group_entity($this->get('guid'), $this->get('name'), $this->get('description'));
+ _elgg_enable_caching_for_entity($this->guid);
+
+ return $ret;
}
// EXPORTABLE INTERFACE ////////////////////////////////////////////////////////////
diff --git a/engine/classes/ElggObject.php b/engine/classes/ElggObject.php
index d54752dca..aeaa3ba5c 100644
--- a/engine/classes/ElggObject.php
+++ b/engine/classes/ElggObject.php
@@ -126,8 +126,12 @@ class ElggObject extends ElggEntity {
}
// Save ElggObject-specific attributes
- return create_object_entity($this->get('guid'), $this->get('title'),
- $this->get('description'));
+
+ _elgg_disable_caching_for_entity($this->guid);
+ $ret = create_object_entity($this->get('guid'), $this->get('title'), $this->get('description'));
+ _elgg_enable_caching_for_entity($this->guid);
+
+ return $ret;
}
/**
diff --git a/engine/classes/ElggPlugin.php b/engine/classes/ElggPlugin.php
index c1c46f272..7bf6eb1df 100644
--- a/engine/classes/ElggPlugin.php
+++ b/engine/classes/ElggPlugin.php
@@ -350,11 +350,14 @@ class ElggPlugin extends ElggObject {
*/
public function unsetAllSettings() {
$db_prefix = get_config('dbprefix');
- $ps_prefix = elgg_namespace_plugin_private_setting('setting', '');
+
+ $us_prefix = elgg_namespace_plugin_private_setting('user_setting', '', $this->getID());
+ $is_prefix = elgg_namespace_plugin_private_setting('internal', '', $this->getID());
$q = "DELETE FROM {$db_prefix}private_settings
WHERE entity_guid = $this->guid
- AND name NOT LIKE '$ps_prefix%'";
+ AND name NOT LIKE '$us_prefix%'
+ AND name NOT LIKE '$is_prefix%'";
return delete_data($q);
}
@@ -546,7 +549,7 @@ class ElggPlugin extends ElggObject {
* Returns if the plugin is complete, meaning has all required files
* and Elgg can read them and they make sense.
*
- * @todo bad name? This could be confused with isValid() from ElggPackage.
+ * @todo bad name? This could be confused with isValid() from ElggPluginPackage.
*
* @return bool
*/
diff --git a/engine/classes/ElggPluginPackage.php b/engine/classes/ElggPluginPackage.php
index 209242288..37eb4bf4d 100644
--- a/engine/classes/ElggPluginPackage.php
+++ b/engine/classes/ElggPluginPackage.php
@@ -294,6 +294,7 @@ class ElggPluginPackage {
return true;
}
+ $this->errorMsg = elgg_echo('unknown_error');
return false;
}
diff --git a/engine/classes/ElggUser.php b/engine/classes/ElggUser.php
index 6d9f10b57..6163f9b62 100644
--- a/engine/classes/ElggUser.php
+++ b/engine/classes/ElggUser.php
@@ -40,6 +40,9 @@ class ElggUser extends ElggEntity
$this->attributes['code'] = NULL;
$this->attributes['banned'] = "no";
$this->attributes['admin'] = 'no';
+ $this->attributes['prev_last_action'] = NULL;
+ $this->attributes['last_login'] = NULL;
+ $this->attributes['prev_last_login'] = NULL;
$this->attributes['tables_split'] = 2;
}
@@ -129,9 +132,13 @@ class ElggUser extends ElggEntity
}
// Now save specific stuff
- return create_user_entity($this->get('guid'), $this->get('name'), $this->get('username'),
+ _elgg_disable_caching_for_entity($this->guid);
+ $ret = create_user_entity($this->get('guid'), $this->get('name'), $this->get('username'),
$this->get('password'), $this->get('salt'), $this->get('email'), $this->get('language'),
$this->get('code'));
+ _elgg_enable_caching_for_entity($this->guid);
+
+ return $ret;
}
/**
diff --git a/engine/handlers/cache_handler.php b/engine/handlers/cache_handler.php
index 9848d3531..36fc665bb 100644
--- a/engine/handlers/cache_handler.php
+++ b/engine/handlers/cache_handler.php
@@ -88,20 +88,18 @@ header("ETag: \"$etag\"");
$filename = $dataroot . 'views_simplecache/' . md5($viewtype . $view);
if (file_exists($filename)) {
- $contents = file_get_contents($filename);
+ readfile($filename);
} else {
// someone trying to access a non-cached file or a race condition with cache flushing
mysql_close($mysql_dblink);
require_once(dirname(dirname(__FILE__)) . "/start.php");
global $CONFIG;
- if (!isset($CONFIG->views->simplecache[$view])) {
+ if (!in_array($view, $CONFIG->views->simplecache)) {
header("HTTP/1.1 404 Not Found");
exit;
}
elgg_set_viewtype($viewtype);
- $contents = elgg_view($view);
+ echo elgg_view($view);
}
-
-echo $contents;
diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php
index 81755f169..124e67e0f 100644
--- a/engine/lib/annotations.php
+++ b/engine/lib/annotations.php
@@ -419,8 +419,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);
@@ -457,6 +457,12 @@ 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');
}
diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php
index fb652a141..b5ef7e572 100644
--- a/engine/lib/elgglib.php
+++ b/engine/lib/elgglib.php
@@ -2247,6 +2247,9 @@ function elgg_api_test($hook, $type, $value, $params) {
/**#@+
* 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
*/
define('ACCESS_DEFAULT', -1);
diff --git a/engine/lib/entities.php b/engine/lib/entities.php
index 15ab1170e..997db79d2 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,6 +35,34 @@ 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
@@ -57,7 +94,7 @@ function _elgg_invalidate_cache_for_entity($guid) {
* @todo Use an ElggCache object
*/
function _elgg_cache_entity(ElggEntity $entity) {
- global $ENTITY_CACHE;
+ 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,6 +102,11 @@ function _elgg_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 Pick a less arbitrary limit
if (count($ENTITY_CACHE) > 256) {
@@ -79,7 +121,7 @@ function _elgg_cache_entity(ElggEntity $entity) {
elgg_get_metadata_cache()->clear($random_guid);
}
- $ENTITY_CACHE[$entity->guid] = $entity;
+ $ENTITY_CACHE[$guid] = $entity;
}
/**
@@ -407,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) {
@@ -430,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
@@ -556,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;
@@ -565,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)) {
@@ -712,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') {
@@ -884,6 +933,8 @@ function elgg_get_entities(array $options = array()) {
'joins' => array(),
'callback' => 'entity_row_to_elggstar',
+
+ '__ElggBatch' => null,
);
$options = array_merge($defaults, $options);
@@ -1001,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,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');
@@ -1119,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);
+ }
}
}
}
@@ -1416,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,
@@ -2069,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)) {
@@ -2470,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/group.php b/engine/lib/group.php
index 359bc59c2..6ded8a825 100644
--- a/engine/lib/group.php
+++ b/engine/lib/group.php
@@ -240,6 +240,7 @@ 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,
diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php
index 43f7d5d6e..d2f8d4cd4 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);
@@ -402,9 +402,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
diff --git a/engine/lib/metastrings.php b/engine/lib/metastrings.php
index 39a81c6d0..57d876c06 100644
--- a/engine/lib/metastrings.php
+++ b/engine/lib/metastrings.php
@@ -425,7 +425,7 @@ function elgg_get_metastring_based_objects($options) {
$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 = '';
@@ -436,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";
}
@@ -464,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']}";
diff --git a/engine/lib/navigation.php b/engine/lib/navigation.php
index 118a7214c..ab9cc05e8 100644
--- a/engine/lib/navigation.php
+++ b/engine/lib/navigation.php
@@ -218,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);
}
/**
@@ -323,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
@@ -332,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;
+ }
}
}
}
diff --git a/engine/lib/output.php b/engine/lib/output.php
index 5adc01053..6172a5c8d 100644
--- a/engine/lib/output.php
+++ b/engine/lib/output.php
@@ -27,16 +27,16 @@ function parse_urls($text) {
// 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',
- $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];
- $punc = \'\';
+ $punc = "";
$last = substr($url, -1, 1);
- if (in_array($last, array(".", "!", ","))) {
+ if (in_array($last, array(".", "!", ",", "(", ")"))) {
$punc = $last;
- $url = rtrim($url, ".!,");
+ $url = rtrim($url, ".!,()");
}
$urltext = str_replace("/", "/<wbr />", $url);
return "<a href=\"$url\" rel=\"nofollow\">$urltext</a>$punc";
diff --git a/engine/lib/sessions.php b/engine/lib/sessions.php
index a34c2045b..fb28e1e9a 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
diff --git a/engine/lib/statistics.php b/engine/lib/statistics.php
index 0c9a3c945..4cb0bb0b8 100644
--- a/engine/lib/statistics.php
+++ b/engine/lib/statistics.php
@@ -95,13 +95,17 @@ 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/views.php b/engine/lib/views.php
index c4b349fc6..65ba20204 100644
--- a/engine/lib/views.php
+++ b/engine/lib/views.php
@@ -1638,7 +1638,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/tests/api/entity_getter_functions.php b/engine/tests/api/entity_getter_functions.php
index 7bf8ef04a..0492b1fb0 100644
--- a/engine/tests/api/entity_getter_functions.php
+++ b/engine/tests/api/entity_getter_functions.php
@@ -2755,7 +2755,7 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest {
'calculation' => 'count',
'count' => true,
);
- $count = (int)elgg_get_entities_from_annotation_calculation($options);
+ $count = elgg_get_entities_from_annotation_calculation($options);
$this->assertEqual(1, $count);
}
diff --git a/engine/tests/api/helpers.php b/engine/tests/api/helpers.php
index 62e4471e0..10216140f 100644
--- a/engine/tests/api/helpers.php
+++ b/engine/tests/api/helpers.php
@@ -578,6 +578,107 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest {
$this->assertEqual(11, $j);
}
+ public function testElggBatchReadHandlesBrokenEntities() {
+ $num_test_entities = 8;
+ $guids = array();
+ for ($i = $num_test_entities; $i > 0; $i--) {
+ $entity = new ElggObject();
+ $entity->type = 'object';
+ $entity->subtype = 'test_5357_subtype';
+ $entity->access_id = ACCESS_PUBLIC;
+ $entity->save();
+ $guids[] = $entity->guid;
+ _elgg_invalidate_cache_for_entity($entity->guid);
+ }
+
+ // break entities such that the first fetch has one incomplete
+ // and the second and third fetches have only incompletes!
+ $db_prefix = elgg_get_config('dbprefix');
+ delete_data("
+ DELETE FROM {$db_prefix}objects_entity
+ WHERE guid IN ({$guids[1]}, {$guids[2]}, {$guids[3]}, {$guids[4]}, {$guids[5]})
+ ");
+
+ $options = array(
+ 'type' => 'object',
+ 'subtype' => 'test_5357_subtype',
+ 'order_by' => 'e.guid',
+ );
+
+ $entities_visited = array();
+ $batch = new ElggBatch('elgg_get_entities', $options, null, 2);
+ /* @var ElggEntity[] $batch */
+ foreach ($batch as $entity) {
+ $entities_visited[] = $entity->guid;
+ }
+
+ // The broken entities should not have been visited
+ $this->assertEqual($entities_visited, array($guids[0], $guids[6], $guids[7]));
+
+ // cleanup (including leftovers from previous tests)
+ $entity_rows = elgg_get_entities(array_merge($options, array(
+ 'callback' => '',
+ 'limit' => false,
+ )));
+ $guids = array();
+ foreach ($entity_rows as $row) {
+ $guids[] = $row->guid;
+ }
+ delete_data("DELETE FROM {$db_prefix}entities WHERE guid IN (" . implode(',', $guids) . ")");
+ delete_data("DELETE FROM {$db_prefix}objects_entity WHERE guid IN (" . implode(',', $guids) . ")");
+ }
+
+ public function testElggBatchDeleteHandlesBrokenEntities() {
+ $num_test_entities = 8;
+ $guids = array();
+ for ($i = $num_test_entities; $i > 0; $i--) {
+ $entity = new ElggObject();
+ $entity->type = 'object';
+ $entity->subtype = 'test_5357_subtype';
+ $entity->access_id = ACCESS_PUBLIC;
+ $entity->save();
+ $guids[] = $entity->guid;
+ _elgg_invalidate_cache_for_entity($entity->guid);
+ }
+
+ // break entities such that the first fetch has one incomplete
+ // and the second and third fetches have only incompletes!
+ $db_prefix = elgg_get_config('dbprefix');
+ delete_data("
+ DELETE FROM {$db_prefix}objects_entity
+ WHERE guid IN ({$guids[1]}, {$guids[2]}, {$guids[3]}, {$guids[4]}, {$guids[5]})
+ ");
+
+ $options = array(
+ 'type' => 'object',
+ 'subtype' => 'test_5357_subtype',
+ 'order_by' => 'e.guid',
+ );
+
+ $entities_visited = array();
+ $batch = new ElggBatch('elgg_get_entities', $options, null, 2, false);
+ /* @var ElggEntity[] $batch */
+ foreach ($batch as $entity) {
+ $entities_visited[] = $entity->guid;
+ $entity->delete();
+ }
+
+ // The broken entities should not have been visited
+ $this->assertEqual($entities_visited, array($guids[0], $guids[6], $guids[7]));
+
+ // cleanup (including leftovers from previous tests)
+ $entity_rows = elgg_get_entities(array_merge($options, array(
+ 'callback' => '',
+ 'limit' => false,
+ )));
+ $guids = array();
+ foreach ($entity_rows as $row) {
+ $guids[] = $row->guid;
+ }
+ delete_data("DELETE FROM {$db_prefix}entities WHERE guid IN (" . implode(',', $guids) . ")");
+ delete_data("DELETE FROM {$db_prefix}objects_entity WHERE guid IN (" . implode(',', $guids) . ")");
+ }
+
static function elgg_batch_callback_test($options, $reset = false) {
static $count = 1;
diff --git a/engine/tests/api/metadata_cache.php b/engine/tests/api/metadata_cache.php
index 846116a7b..7fb328169 100644
--- a/engine/tests/api/metadata_cache.php
+++ b/engine/tests/api/metadata_cache.php
@@ -166,4 +166,11 @@ class ElggCoreMetadataCacheTest extends ElggCoreUnitTest {
$actual = $this->cache->filterMetadataHeavyEntities($guids, 6000);
$this->assertIdentical($actual, $expected);
}
+
+ public function testCreateMetadataInvalidates() {
+ $this->obj1->foo = 1;
+ create_metadata($this->guid1, 'foo', 2, '', elgg_get_logged_in_user_guid(), ACCESS_FRIENDS);
+
+ $this->assertEqual($this->obj1->foo, 2);
+ }
}
diff --git a/engine/tests/objects/users.php b/engine/tests/objects/users.php
index a3573acb6..dc9129326 100644
--- a/engine/tests/objects/users.php
+++ b/engine/tests/objects/users.php
@@ -65,6 +65,9 @@ class ElggCoreUserTest extends ElggCoreUnitTest {
$attributes['code'] = NULL;
$attributes['banned'] = 'no';
$attributes['admin'] = 'no';
+ $attributes['prev_last_action'] = NULL;
+ $attributes['last_login'] = NULL;
+ $attributes['prev_last_login'] = NULL;
ksort($attributes);
$entity_attributes = $this->user->expose_attributes();
diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php
index 051aa8d1b..f173b5b9f 100644
--- a/engine/tests/regression/trac_bugs.php
+++ b/engine/tests/regression/trac_bugs.php
@@ -291,9 +291,45 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest {
'unquoted already anchor <a href=http://www.yahoo.com>yahoo</a>' =>
'unquoted already anchor <a href=http://www.yahoo.com>yahoo</a>',
+
+ 'parens in uri http://thedailywtf.com/Articles/A-(Long-Overdue)-BuildMaster-Introduction.aspx' =>
+ 'parens in uri <a href="http://thedailywtf.com/Articles/A-(Long-Overdue)-BuildMaster-Introduction.aspx" rel="nofollow">http:/<wbr />/<wbr />thedailywtf.com/<wbr />Articles/<wbr />A-(Long-Overdue)-BuildMaster-Introduction.aspx</a>'
);
foreach ($cases as $input => $output) {
$this->assertEqual($output, parse_urls($input));
}
}
+
+ /**
+ * Ensure additional select columns do not end up in entity attributes.
+ *
+ * https://github.com/Elgg/Elgg/issues/5538
+ */
+ public function test_extra_columns_dont_appear_in_attributes() {
+ global $ENTITY_CACHE;
+
+ // may not have groups in DB - let's create one
+ $group = new ElggGroup();
+ $group->name = 'test_group';
+ $group->access_id = ACCESS_PUBLIC;
+ $this->assertTrue($group->save() !== false);
+
+ // entity cache interferes with our test
+ $ENTITY_CACHE = array();
+
+ foreach (array('site', 'user', 'group', 'object') as $type) {
+ $entities = elgg_get_entities(array(
+ 'type' => $type,
+ 'selects' => array('1 as _nonexistent_test_column'),
+ 'limit' => 1,
+ ));
+ if (!$this->assertTrue($entities, "Query for '$type' did not return an entity.")) {
+ continue;
+ }
+ $entity = $entities[0];
+ $this->assertNull($entity->_nonexistent_test_column, "Additional select columns are leaking to attributes for '$type'");
+ }
+
+ $group->delete();
+ }
}
diff --git a/install/cli/sample_installer.php b/install/cli/sample_installer.php
index 0bae0cd23..a51f9aae4 100644
--- a/install/cli/sample_installer.php
+++ b/install/cli/sample_installer.php
@@ -1,28 +1,12 @@
<?php
+
/**
* Sample cli installer script
*/
+// change to true to run this script. Change back to false when done.
$enabled = false;
-// Do not edit below this line. //////////////////////////////
-
-
-if (!$enabled) {
- echo "To enable this script, change \$enabled to true.\n";
- echo "You *must* disable this script after a successful installation.\n";
- exit;
-}
-
-if (PHP_SAPI !== 'cli') {
- echo "You must use the command line to run this script.";
- exit;
-}
-
-require_once(dirname(dirname(__FILE__)) . "/ElggInstaller.php");
-
-$installer = new ElggInstaller();
-
// none of the following may be empty
$params = array(
// database parameters
@@ -43,11 +27,29 @@ $params = array(
'password' => '',
);
+
+// Do not edit below this line. //////////////////////////////
+
+
+if (!$enabled) {
+ echo "To enable this script, change \$enabled to true.\n";
+ echo "You *must* disable this script after a successful installation.\n";
+ exit;
+}
+
+if (PHP_SAPI !== 'cli') {
+ echo "You must use the command line to run this script.";
+ exit;
+}
+
+require_once(dirname(dirname(__FILE__)) . "/ElggInstaller.php");
+
+$installer = new ElggInstaller();
+
// install and create the .htaccess file
$installer->batchInstall($params, TRUE);
// at this point installation has completed (otherwise an exception halted execution).
-
// try to rewrite the script to disable it.
if (is_writable(__FILE__)) {
$code = file_get_contents(__FILE__);
diff --git a/js/lib/elgglib.js b/js/lib/elgglib.js
index af2c94000..a8e187f1d 100644
--- a/js/lib/elgglib.js
+++ b/js/lib/elgglib.js
@@ -474,8 +474,8 @@ elgg.parse_str = function(string) {
re = /([^&=]+)=?([^&]*)/g;
while (result = re.exec(string)) {
- key = decodeURIComponent(result[1])
- value = decodeURIComponent(result[2])
+ key = decodeURIComponent(result[1].replace(/\+/g, ' '));
+ value = decodeURIComponent(result[2].replace(/\+/g, ' '));
params[key] = value;
}
diff --git a/js/lib/session.js b/js/lib/session.js
index fa3d60aa9..a8d52733c 100644
--- a/js/lib/session.js
+++ b/js/lib/session.js
@@ -14,9 +14,9 @@ elgg.provide('elgg.session');
* {string} options[domain]
* {boolean} options[secure]
*
- * @return {string} The value of the cookie, if only name is specified
+ * @return {string|undefined} The value of the cookie, if only name is specified. Undefined if no value set
*/
-elgg.session.cookie = function (name, value, options) {
+elgg.session.cookie = function(name, value, options) {
var cookies = [], cookie = [], i = 0, date, valid = true;
//elgg.session.cookie()
@@ -47,21 +47,19 @@ elgg.session.cookie = function (name, value, options) {
}
cookies.push(name + '=' + value);
-
- if (elgg.isNumber(options.expires)) {
- if (elgg.isNumber(options.expires)) {
- date = new Date();
- date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
- } else if (options.expires.toUTCString) {
- date = options.expires;
- } else {
- valid = false;
- }
-
- if (valid) {
- cookies.push('expires=' + date.toUTCString());
- }
- }
+
+ if (options.expires) {
+ if (elgg.isNumber(options.expires)) {
+ date = new Date();
+ date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
+ } else if (options.expires.toUTCString) {
+ date = options.expires;
+ }
+
+ if (date) {
+ cookies.push('expires=' + date.toUTCString());
+ }
+ }
// CAUTION: Needed to parenthesize options.path and options.domain
// in the following expressions, otherwise they evaluate to undefined
diff --git a/js/lib/ui.userpicker.js b/js/lib/ui.userpicker.js
index 7298da114..669b84cdb 100644
--- a/js/lib/ui.userpicker.js
+++ b/js/lib/ui.userpicker.js
@@ -107,11 +107,11 @@ elgg.userpicker.viewUser = function(info) {
* @return Object
*/
elgg.userpicker.getSearchParams = function(obj) {
- if (obj.element.siblings('[name=match_on]').attr('checked')) {
+ if (obj.element.parent('.elgg-user-picker').find('input[name=match_on]').attr('checked')) {
return {'match_on[]': 'friends', 'term' : obj.term};
} else {
return {'match_on[]': 'users', 'term' : obj.term};
}
};
-elgg.register_hook_handler('init', 'system', elgg.userpicker.init); \ No newline at end of file
+elgg.register_hook_handler('init', 'system', elgg.userpicker.init);
diff --git a/js/tests/ElggLibTest.js b/js/tests/ElggLibTest.js
index 31b561923..bd39e7fb3 100644
--- a/js/tests/ElggLibTest.js
+++ b/js/tests/ElggLibTest.js
@@ -128,3 +128,13 @@ ElggLibTest.prototype.testParseUrl = function() {
});
};
+ElggLibTest.prototype.testParseStr = function() {
+
+ [
+ ["A+%2B+B=A+%2B+B", {"A + B": "A + B"}]
+
+ ].forEach(function(args) {
+ assertEquals(args[1], elgg.parse_str(args[0]));
+ });
+};
+
diff --git a/js/tests/README b/js/tests/README
index 4f86b27c6..f43c0c89d 100644
--- a/js/tests/README
+++ b/js/tests/README
@@ -12,9 +12,10 @@ based debuggers. Visit its wiki at the Google Code site for more information.
Sample Usage
============
1. Put jar file in the base directory of Elgg
- 2. Run the server: java -jar JsTestDriver-1.3.3d.jar --port 4224
+ 2. Run the server: java -jar JsTestDriver-1.3.5.jar --port 4224
3. Point a web browser at http://localhost:4224
- 4. Run the tests: java -jar JsTestDriver-1.3.3d.jar --config js/tests/jsTestDriver.conf --basePath . --tests all
+ 4. Click "Capture this browser"
+ 5. Run the tests: java -jar JsTestDriver-1.3.5.jar --config js/tests/jsTestDriver.conf --basePath . --tests all
Configuration Hints
diff --git a/languages/en.php b/languages/en.php
index be86e12e6..1721865f7 100644
--- a/languages/en.php
+++ b/languages/en.php
@@ -359,6 +359,7 @@ $english = array(
'friendspicker:chararray' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'avatar' => 'Avatar',
+ 'avatar:noaccess' => "You're not allowed to edit this user's avatar",
'avatar:create' => 'Create your avatar',
'avatar:edit' => 'Edit avatar',
'avatar:preview' => 'Preview',
@@ -902,6 +903,7 @@ $english = array(
'total' => 'Total',
'learnmore' => "Click here to learn more.",
+ 'unknown_error' => 'Unknown error',
'content' => "content",
'content:latest' => 'Latest activity',
diff --git a/mod/blog/actions/blog/save.php b/mod/blog/actions/blog/save.php
index 9256610cc..82a9e6c51 100644
--- a/mod/blog/actions/blog/save.php
+++ b/mod/blog/actions/blog/save.php
@@ -79,11 +79,7 @@ foreach ($values as $name => $default) {
switch ($name) {
case 'tags':
- if ($value) {
- $values[$name] = string_to_tag_array($value);
- } else {
- unset ($values[$name]);
- }
+ $values[$name] = string_to_tag_array($value);
break;
case 'excerpt':
@@ -125,10 +121,7 @@ if ($values['status'] == 'draft') {
// assign values to the entity, stopping on error.
if (!$error) {
foreach ($values as $name => $value) {
- if (FALSE === ($blog->$name = $value)) {
- $error = elgg_echo('blog:error:cannot_save' . "$name=$value");
- break;
- }
+ $blog->$name = $value;
}
}
diff --git a/mod/blog/start.php b/mod/blog/start.php
index 25cd81935..91525acee 100644
--- a/mod/blog/start.php
+++ b/mod/blog/start.php
@@ -113,14 +113,23 @@ function blog_page_handler($page) {
switch ($page_type) {
case 'owner':
$user = get_user_by_username($page[1]);
+ if (!$user) {
+ forward('', '404');
+ }
$params = blog_get_page_content_list($user->guid);
break;
case 'friends':
$user = get_user_by_username($page[1]);
+ if (!$user) {
+ forward('', '404');
+ }
$params = blog_get_page_content_friends($user->guid);
break;
case 'archive':
$user = get_user_by_username($page[1]);
+ if (!$user) {
+ forward('', '404');
+ }
$params = blog_get_page_content_archive($user->guid, $page[2], $page[3]);
break;
case 'view':
@@ -139,6 +148,10 @@ function blog_page_handler($page) {
$params = blog_get_page_content_edit($page_type, $page[1], $page[2]);
break;
case 'group':
+ $group = get_entity($page[1]);
+ if (!elgg_instanceof($group, 'group')) {
+ forward('', '404');
+ }
if ($page[2] == 'all') {
$params = blog_get_page_content_list($page[1]);
} else {
diff --git a/mod/blog/views/default/blog/sidebar/archives.php b/mod/blog/views/default/blog/sidebar/archives.php
index 3d8f28ca4..5098e6e3e 100644
--- a/mod/blog/views/default/blog/sidebar/archives.php
+++ b/mod/blog/views/default/blog/sidebar/archives.php
@@ -14,7 +14,7 @@ if (elgg_instanceof($page_owner, 'user')) {
// This is a limitation of the URL schema.
if ($page_owner && $vars['page'] != 'friends') {
- $dates = get_entity_dates('object', 'blog', $page_owner->getGUID());
+ $dates = array_reverse(get_entity_dates('object', 'blog', $page_owner->getGUID()));
if ($dates) {
$title = elgg_echo('blog:archives');
diff --git a/mod/bookmarks/pages/bookmarks/all.php b/mod/bookmarks/pages/bookmarks/all.php
index bdb8fc793..5c6011ad9 100644
--- a/mod/bookmarks/pages/bookmarks/all.php
+++ b/mod/bookmarks/pages/bookmarks/all.php
@@ -13,9 +13,8 @@ elgg_register_title_button();
$content = elgg_list_entities(array(
'type' => 'object',
'subtype' => 'bookmarks',
- 'limit' => 10,
'full_view' => false,
- 'view_toggle_type' => false
+ 'view_toggle_type' => false,
));
if (!$content) {
diff --git a/mod/bookmarks/pages/bookmarks/friends.php b/mod/bookmarks/pages/bookmarks/friends.php
index 15b1da098..173996346 100644
--- a/mod/bookmarks/pages/bookmarks/friends.php
+++ b/mod/bookmarks/pages/bookmarks/friends.php
@@ -7,7 +7,7 @@
$page_owner = elgg_get_page_owner_entity();
if (!$page_owner) {
- forward('bookmarks/all');
+ forward('', '404');
}
elgg_push_breadcrumb($page_owner->name, "bookmarks/owner/$page_owner->username");
diff --git a/mod/bookmarks/pages/bookmarks/owner.php b/mod/bookmarks/pages/bookmarks/owner.php
index a024ff352..b7b907916 100644
--- a/mod/bookmarks/pages/bookmarks/owner.php
+++ b/mod/bookmarks/pages/bookmarks/owner.php
@@ -7,7 +7,7 @@
$page_owner = elgg_get_page_owner_entity();
if (!$page_owner) {
- forward('bookmarks/all');
+ forward('', '404');
}
elgg_push_breadcrumb($page_owner->name);
@@ -18,7 +18,6 @@ $content .= elgg_list_entities(array(
'type' => 'object',
'subtype' => 'bookmarks',
'container_guid' => $page_owner->guid,
- 'limit' => 10,
'full_view' => false,
'view_toggle_type' => false
));
diff --git a/mod/embed/start.php b/mod/embed/start.php
index e14e0efd4..1da35aa46 100644
--- a/mod/embed/start.php
+++ b/mod/embed/start.php
@@ -14,8 +14,10 @@ elgg_register_event_handler('init', 'system', 'embed_init');
function embed_init() {
elgg_extend_view('css/elgg', 'embed/css');
elgg_extend_view('css/admin', 'embed/css');
-
- elgg_register_plugin_hook_handler('register', 'menu:longtext', 'embed_longtext_menu');
+
+ if (elgg_is_logged_in()) {
+ elgg_register_plugin_hook_handler('register', 'menu:longtext', 'embed_longtext_menu');
+ }
elgg_register_plugin_hook_handler('register', 'menu:embed', 'embed_select_tab', 1000);
// Page handler for the modal media embed
diff --git a/mod/file/pages/file/friends.php b/mod/file/pages/file/friends.php
index f504bdc1f..d55c1e62b 100644
--- a/mod/file/pages/file/friends.php
+++ b/mod/file/pages/file/friends.php
@@ -7,7 +7,7 @@
$owner = elgg_get_page_owner_entity();
if (!$owner) {
- forward('file/all');
+ forward('', '404');
}
elgg_push_breadcrumb(elgg_echo('file'), "file/all");
diff --git a/mod/file/pages/file/owner.php b/mod/file/pages/file/owner.php
index d7f057f2a..99cf62714 100644
--- a/mod/file/pages/file/owner.php
+++ b/mod/file/pages/file/owner.php
@@ -10,7 +10,7 @@ group_gatekeeper();
$owner = elgg_get_page_owner_entity();
if (!$owner) {
- forward('file/all');
+ forward('', '404');
}
elgg_push_breadcrumb(elgg_echo('file'), "file/all");
@@ -39,7 +39,6 @@ $content = elgg_list_entities(array(
'type' => 'object',
'subtype' => 'file',
'container_guid' => $owner->guid,
- 'limit' => 10,
'full_view' => FALSE,
));
if (!$content) {
diff --git a/mod/file/pages/file/world.php b/mod/file/pages/file/world.php
index 8e6c87f26..96c8de785 100644
--- a/mod/file/pages/file/world.php
+++ b/mod/file/pages/file/world.php
@@ -9,14 +9,11 @@ elgg_push_breadcrumb(elgg_echo('file'));
elgg_register_title_button();
-$limit = get_input("limit", 10);
-
$title = elgg_echo('file:all');
$content = elgg_list_entities(array(
'type' => 'object',
'subtype' => 'file',
- 'limit' => $limit,
'full_view' => FALSE
));
if (!$content) {
diff --git a/mod/groups/lib/discussion.php b/mod/groups/lib/discussion.php
index ab2fe4849..874e21b2d 100644
--- a/mod/groups/lib/discussion.php
+++ b/mod/groups/lib/discussion.php
@@ -39,9 +39,8 @@ function discussion_handle_list_page($guid) {
elgg_set_page_owner_guid($guid);
$group = get_entity($guid);
- if (!$group) {
- register_error(elgg_echo('group:notfound'));
- forward();
+ if (!elgg_instanceof($group, 'group')) {
+ forward('', '404');
}
elgg_push_breadcrumb($group->name);
diff --git a/mod/groups/lib/groups.php b/mod/groups/lib/groups.php
index 0557d41eb..77d7c09cc 100644
--- a/mod/groups/lib/groups.php
+++ b/mod/groups/lib/groups.php
@@ -255,8 +255,8 @@ function groups_handle_profile_page($guid) {
elgg_push_context('group_profile');
$group = get_entity($guid);
- if (!$group) {
- forward('groups/all');
+ if (!elgg_instanceof($group, 'group')) {
+ forward('', '404');
}
elgg_push_breadcrumb($group->name);
@@ -366,12 +366,15 @@ function groups_handle_members_page($guid) {
elgg_push_breadcrumb($group->name, $group->getURL());
elgg_push_breadcrumb(elgg_echo('groups:members'));
+ $db_prefix = elgg_get_config('dbprefix');
$content = elgg_list_entities_from_relationship(array(
'relationship' => 'member',
'relationship_guid' => $group->guid,
'inverse_relationship' => true,
'type' => 'user',
'limit' => 20,
+ 'joins' => array("JOIN {$db_prefix}users_entity u ON e.guid=u.guid"),
+ 'order_by' => 'u.name ASC',
));
$params = array(
diff --git a/mod/groups/start.php b/mod/groups/start.php
index 46ab0e636..6002a535c 100644
--- a/mod/groups/start.php
+++ b/mod/groups/start.php
@@ -142,6 +142,10 @@ function groups_setup_sidebar_menus() {
$page_owner = elgg_get_page_owner_entity();
if (elgg_in_context('group_profile')) {
+ if (!elgg_instanceof($page_owner, 'group')) {
+ forward('', '404');
+ }
+
if (elgg_is_logged_in() && $page_owner->canEdit() && !$page_owner->isPublicMembership()) {
$url = elgg_get_site_url() . "groups/requests/{$page_owner->getGUID()}";
diff --git a/mod/groups/views/default/object/groupforumtopic.php b/mod/groups/views/default/object/groupforumtopic.php
index 34e0ee3cc..e6988d16e 100644
--- a/mod/groups/views/default/object/groupforumtopic.php
+++ b/mod/groups/views/default/object/groupforumtopic.php
@@ -73,7 +73,10 @@ if ($full) {
$info = elgg_view_image_block($poster_icon, $list_body);
- $body = elgg_view('output/longtext', array('value' => $topic->description));
+ $body = elgg_view('output/longtext', array(
+ 'value' => $topic->description,
+ 'class' => 'clearfix',
+ ));
echo <<<HTML
$info
diff --git a/mod/messageboard/pages/messageboard/owner.php b/mod/messageboard/pages/messageboard/owner.php
index 2c854d4f3..b3e9f45b0 100644
--- a/mod/messageboard/pages/messageboard/owner.php
+++ b/mod/messageboard/pages/messageboard/owner.php
@@ -16,7 +16,6 @@ elgg_push_breadcrumb($page_owner->name, $page_owner->getURL());
$options = array(
'annotations_name' => 'messageboard',
'guid' => $page_owner_guid,
- 'limit' => 10,
'reverse_order_by' => true,
);
diff --git a/mod/pages/pages/pages/friends.php b/mod/pages/pages/pages/friends.php
index 87ac631c2..cecc4053b 100644
--- a/mod/pages/pages/pages/friends.php
+++ b/mod/pages/pages/pages/friends.php
@@ -7,7 +7,7 @@
$owner = elgg_get_page_owner_entity();
if (!$owner) {
- forward('pages/all');
+ forward('', '404');
}
elgg_push_breadcrumb($owner->name, "pages/owner/$owner->username");
diff --git a/mod/pages/pages/pages/owner.php b/mod/pages/pages/pages/owner.php
index 48199368c..7de74a3b4 100644
--- a/mod/pages/pages/pages/owner.php
+++ b/mod/pages/pages/pages/owner.php
@@ -7,7 +7,7 @@
$owner = elgg_get_page_owner_entity();
if (!$owner) {
- forward('pages/all');
+ forward('', '404');
}
// access check for closed groups
diff --git a/mod/search/search_hooks.php b/mod/search/search_hooks.php
index c92003c7e..923cf0aa8 100644
--- a/mod/search/search_hooks.php
+++ b/mod/search/search_hooks.php
@@ -405,14 +405,19 @@ function search_comments_hook($hook, $type, $value, $params) {
// don't continue if nothing there...
if (!$count) {
- return array ('entities' => array(), 'count' => 0);
+ return array('entities' => array(), 'count' => 0);
}
-
- $order_by = search_get_order_by_sql('e', null, $params['sort'], $params['order']);
+
+ // no full text index on metastrings table
+ if ($params['sort'] == 'relevance') {
+ $params['sort'] = 'created';
+ }
+
+ $order_by = search_get_order_by_sql('a', null, $params['sort'], $params['order']);
if ($order_by) {
$order_by = "ORDER BY $order_by";
}
-
+
$q = "SELECT DISTINCT a.*, msv.string as comment FROM {$db_prefix}annotations a
JOIN {$db_prefix}metastrings msn ON a.name_id = msn.id
JOIN {$db_prefix}metastrings msv ON a.value_id = msv.id
@@ -450,10 +455,17 @@ function search_comments_hook($hook, $type, $value, $params) {
}
$comment_str = search_get_highlighted_relevant_substrings($comment->comment, $query);
- $entity->setVolatileData('search_match_annotation_id', $comment->id);
- $entity->setVolatileData('search_matched_comment', $comment_str);
- $entity->setVolatileData('search_matched_comment_owner_guid', $comment->owner_guid);
- $entity->setVolatileData('search_matched_comment_time_created', $comment->time_created);
+ $comments_data = $entity->getVolatileData('search_comments_data');
+ if (!$comments_data) {
+ $comments_data = array();
+ }
+ $comments_data[] = array(
+ 'annotation_id' => $comment->id,
+ 'text' => $comment_str,
+ 'owner_guid' => $comment->owner_guid,
+ 'time_created' => $comment->time_created,
+ );
+ $entity->setVolatileData('search_comments_data', $comments_data);
$entities[] = $entity;
}
diff --git a/mod/search/views/default/search/comments/entity.php b/mod/search/views/default/search/comments/entity.php
index 005bb270c..77e950843 100644
--- a/mod/search/views/default/search/comments/entity.php
+++ b/mod/search/views/default/search/comments/entity.php
@@ -6,8 +6,11 @@
*/
$entity = $vars['entity'];
+$comments_data = $entity->getVolatileData('search_comments_data');
+$comment_data = array_shift($comments_data);
+$entity->setVolatileData('search_comments_data', $comments_data);
-$owner = get_entity($entity->getVolatileData('search_matched_comment_owner_guid'));
+$owner = get_entity($comment_data['owner_guid']);
if ($owner instanceof ElggUser) {
$icon = elgg_view_entity_icon($owner, 'tiny');
@@ -38,12 +41,12 @@ if ($entity->getVolatileData('search_unavailable_entity')) {
$title = elgg_echo('search:comment_on', array($title));
// @todo this should use something like $comment->getURL()
- $url = $entity->getURL() . '#comment_' . $entity->getVolatileData('search_match_annotation_id');
+ $url = $entity->getURL() . '#comment_' . $comment_data['annotation_id'];
$title = "<a href=\"$url\">$title</a>";
}
-$description = $entity->getVolatileData('search_matched_comment');
-$tc = $entity->getVolatileData('search_matched_comment_time_created');;
+$description = $comment_data['text'];
+$tc = $comment_data['time_created'];
$time = elgg_view_friendly_time($tc);
$body = "<p class=\"mbn\">$title</p>$description";
diff --git a/mod/search/views/rss/search/comments/entity.php b/mod/search/views/rss/search/comments/entity.php
index 869779f35..e47afec4a 100644
--- a/mod/search/views/rss/search/comments/entity.php
+++ b/mod/search/views/rss/search/comments/entity.php
@@ -6,9 +6,12 @@
*/
$entity = $vars['entity'];
+$comments_data = $entity->getVolatileData('search_comments_data');
+$comment_data = array_shift($comments_data);
+$entity->setVolatileData('search_comments_data', $comments_data);
$author_name = '';
-$comment_author_guid = $entity->getVolatileData('search_matched_comment_owner_guid');
+$comment_author_guid = $comment_data['owner_guid'];
$author = get_user($comment_author_guid);
if ($author) {
$author_name = $author->name;
@@ -34,11 +37,11 @@ if ($entity->getVolatileData('search_unavailable_entity')) {
$title = elgg_echo('search:comment_on', array($title));
$title .= ' ' . elgg_echo('search:comment_by') . ' ' . $author_name;
- $url = $entity->getURL() . '#annotation-' . $entity->getVolatileData('search_match_annotation_id');
+ $url = $entity->getURL() . '#annotation-' . $comment_data['annotation_id'];
}
-$description = $entity->getVolatileData('search_matched_comment');
-$tc = $entity->getVolatileData('search_matched_comment_time_created');;
+$description = $comment_data['text'];
+$tc = $comment_data['time_created'];
?>
diff --git a/mod/thewire/pages/thewire/everyone.php b/mod/thewire/pages/thewire/everyone.php
index 909f0caf2..c7438747e 100644
--- a/mod/thewire/pages/thewire/everyone.php
+++ b/mod/thewire/pages/thewire/everyone.php
@@ -18,7 +18,7 @@ if (elgg_is_logged_in()) {
$content .= elgg_list_entities(array(
'type' => 'object',
'subtype' => 'thewire',
- 'limit' => 15,
+ 'limit' => get_input('limit', 15),
));
$body = elgg_view_layout('content', array(
diff --git a/mod/thewire/pages/thewire/friends.php b/mod/thewire/pages/thewire/friends.php
index e7f5eed59..efa7e7a56 100644
--- a/mod/thewire/pages/thewire/friends.php
+++ b/mod/thewire/pages/thewire/friends.php
@@ -5,7 +5,7 @@
$owner = elgg_get_page_owner_entity();
if (!$owner) {
- forward('thewire/all');
+ forward('', '404');
}
$title = elgg_echo('thewire:friends');
diff --git a/mod/thewire/pages/thewire/owner.php b/mod/thewire/pages/thewire/owner.php
index 6246c1770..dc25940e1 100644
--- a/mod/thewire/pages/thewire/owner.php
+++ b/mod/thewire/pages/thewire/owner.php
@@ -6,7 +6,7 @@
$owner = elgg_get_page_owner_entity();
if (!$owner) {
- forward('thewire/all');
+ forward('', '404');
}
$title = elgg_echo('thewire:user', array($owner->name));
@@ -26,7 +26,7 @@ $content .= elgg_list_entities(array(
'type' => 'object',
'subtype' => 'thewire',
'owner_guid' => $owner->guid,
- 'limit' => 15,
+ 'limit' => get_input('limit', 15),
));
$body = elgg_view_layout('content', array(
diff --git a/pages/account/forgotten_password.php b/pages/account/forgotten_password.php
index bf6ef87e0..f464f98c9 100644
--- a/pages/account/forgotten_password.php
+++ b/pages/account/forgotten_password.php
@@ -17,6 +17,11 @@ $content .= elgg_view_form('user/requestnewpassword', array(
'class' => 'elgg-form-account',
));
-$body = elgg_view_layout("one_column", array('content' => $content));
-
-echo elgg_view_page($title, $body);
+if (elgg_get_config('walled_garden')) {
+ elgg_load_css('elgg.walled_garden');
+ $body = elgg_view_layout('walled_garden', array('content' => $content));
+ echo elgg_view_page($title, $body, 'walled_garden');
+} else {
+ $body = elgg_view_layout('one_column', array('content' => $content));
+ echo elgg_view_page($title, $body);
+}
diff --git a/pages/account/login.php b/pages/account/login.php
index 14f65cc3f..6aa3752d0 100644
--- a/pages/account/login.php
+++ b/pages/account/login.php
@@ -15,6 +15,14 @@ if (elgg_is_logged_in()) {
forward('');
}
-$login_box = elgg_view('core/account/login_box');
-$content = elgg_view_layout('one_column', array('content' => $login_box));
-echo elgg_view_page(elgg_echo('login'), $content);
+$title = elgg_echo('login');
+$content = elgg_view('core/account/login_box');
+
+if (elgg_get_config('walled_garden')) {
+ elgg_load_css('elgg.walled_garden');
+ $body = elgg_view_layout('walled_garden', array('content' => $content));
+ echo elgg_view_page($title, $body, 'walled_garden');
+} else {
+ $body = elgg_view_layout('one_column', array('content' => $content));
+ echo elgg_view_page($title, $body);
+}
diff --git a/pages/account/register.php b/pages/account/register.php
index cf18a635b..2fe8b74c0 100644
--- a/pages/account/register.php
+++ b/pages/account/register.php
@@ -48,6 +48,11 @@ $content .= elgg_view_form('register', $form_params, $body_params);
$content .= elgg_view('help/register');
-$body = elgg_view_layout("one_column", array('content' => $content));
-
-echo elgg_view_page($title, $body);
+if (elgg_get_config('walled_garden')) {
+ elgg_load_css('elgg.walled_garden');
+ $body = elgg_view_layout('walled_garden', array('content' => $content));
+ echo elgg_view_page($title, $body, 'walled_garden');
+} else {
+ $body = elgg_view_layout('one_column', array('content' => $content));
+ echo elgg_view_page($title, $body);
+}
diff --git a/pages/account/reset_password.php b/pages/account/reset_password.php
index 6515bfc5d..3ab8ccf3e 100644
--- a/pages/account/reset_password.php
+++ b/pages/account/reset_password.php
@@ -30,6 +30,11 @@ $form = elgg_view_form('user/passwordreset', array('class' => 'elgg-form-account
$title = elgg_echo('resetpassword');
$content = elgg_view_title(elgg_echo('resetpassword')) . $form;
-$body = elgg_view_layout('one_column', array('content' => $content));
-
-echo elgg_view_page($title, $body);
+if (elgg_get_config('walled_garden')) {
+ elgg_load_css('elgg.walled_garden');
+ $body = elgg_view_layout('walled_garden', array('content' => $content));
+ echo elgg_view_page($title, $body, 'walled_garden');
+} else {
+ $body = elgg_view_layout('one_column', array('content' => $content));
+ echo elgg_view_page($title, $body);
+}
diff --git a/pages/avatar/edit.php b/pages/avatar/edit.php
index c71633b8b..56aede887 100644
--- a/pages/avatar/edit.php
+++ b/pages/avatar/edit.php
@@ -11,6 +11,11 @@ elgg_set_context('profile_edit');
$title = elgg_echo('avatar:edit');
$entity = elgg_get_page_owner_entity();
+if (!elgg_instanceof($entity, 'user') || !$entity->canEdit()) {
+ register_error(elgg_echo('avatar:noaccess'));
+ forward(REFERER);
+}
+
$content = elgg_view('core/avatar/upload', array('entity' => $entity));
// only offer the crop view if an avatar has been uploaded
diff --git a/pages/river.php b/pages/river.php
index 0e1511334..801d9f664 100644
--- a/pages/river.php
+++ b/pages/river.php
@@ -49,6 +49,7 @@ $content = elgg_view('core/river/filter', array('selector' => $selector));
$sidebar = elgg_view('core/river/sidebar');
$params = array(
+ 'title' => $title,
'content' => $content . $activity,
'sidebar' => $sidebar,
'filter_context' => $page_filter,
diff --git a/version.php b/version.php
index a006fe7b6..a94bf9d31 100644
--- a/version.php
+++ b/version.php
@@ -14,4 +14,4 @@
$version = 2013052900;
// Human-friendly version name
-$release = '1.8.15';
+$release = '1.8.16';
diff --git a/views/default/forms/plugins/settings/save.php b/views/default/forms/plugins/settings/save.php
index dc7b2fef7..116529905 100644
--- a/views/default/forms/plugins/settings/save.php
+++ b/views/default/forms/plugins/settings/save.php
@@ -17,11 +17,11 @@ if ($type != 'user') {
$type = '';
}
-if (elgg_view_exists("{$type}settings/$plugin_id/edit")) {
+if (elgg_view_exists("plugins/$plugin_id/{$type}settings")) {
+ echo elgg_view("plugins/$plugin_id/{$type}settings", $vars);
+} elseif (elgg_view_exists("{$type}settings/$plugin_id/edit")) {
elgg_deprecated_notice("{$type}settings/$plugin_id/edit was deprecated in favor of plugins/$plugin_id/{$type}settings", 1.8);
echo elgg_view("{$type}settings/$plugin_id/edit", $vars);
-} else {
- echo elgg_view("plugins/$plugin_id/{$type}settings", $vars);
}
echo '<div class="elgg-foot">';
diff --git a/views/default/forms/profile/edit.php b/views/default/forms/profile/edit.php
index 9538b779e..cb0a37ca4 100644
--- a/views/default/forms/profile/edit.php
+++ b/views/default/forms/profile/edit.php
@@ -13,6 +13,8 @@
</div>
<?php
+$sticky_values = elgg_get_sticky_values('profile:edit');
+
$profile_fields = elgg_get_config('profile_fields');
if (is_array($profile_fields) && count($profile_fields) > 0) {
foreach ($profile_fields as $shortname => $valtype) {
@@ -40,6 +42,14 @@ if (is_array($profile_fields) && count($profile_fields) > 0) {
$access_id = ACCESS_DEFAULT;
}
+ // sticky form values take precedence over saved ones
+ if (isset($sticky_values[$shortname])) {
+ $value = $sticky_values[$shortname];
+ }
+ if (isset($sticky_values['accesslevel'][$shortname])) {
+ $access_id = $sticky_values['accesslevel'][$shortname];
+ }
+
?>
<div>
<label><?php echo elgg_echo("profile:{$shortname}") ?></label>
@@ -59,6 +69,9 @@ if (is_array($profile_fields) && count($profile_fields) > 0) {
<?php
}
}
+
+elgg_clear_sticky_form('profile:edit');
+
?>
<div class="elgg-foot">
<?php
diff --git a/views/default/input/userpicker.php b/views/default/input/userpicker.php
index 91a397e37..8b64d7df5 100644
--- a/views/default/input/userpicker.php
+++ b/views/default/input/userpicker.php
@@ -63,11 +63,13 @@ foreach ($vars['value'] as $user_id) {
?>
<div class="elgg-user-picker">
<input type="text" class="elgg-input-user-picker" size="30"/>
- <input type="checkbox" name="match_on" value="true" />
- <label><?php echo elgg_echo('userpicker:only_friends'); ?></label>
+ <label>
+ <input type="checkbox" name="match_on" value="true" />
+ <?php echo elgg_echo('userpicker:only_friends'); ?>
+ </label>
<ul class="elgg-user-picker-list"><?php echo $user_list; ?></ul>
</div>
<script type="text/javascript">
// @todo grab the values in the init function rather than using inline JS
elgg.userpicker.userList = <?php echo $json_values ?>;
-</script> \ No newline at end of file
+</script>
diff --git a/views/default/js/walled_garden.php b/views/default/js/walled_garden.php
index 7a482fe23..e228df507 100644
--- a/views/default/js/walled_garden.php
+++ b/views/default/js/walled_garden.php
@@ -5,12 +5,11 @@
* @since 1.8
*/
-// note that this assumes the button view is not using single quotes
$cancel_button = elgg_view('input/button', array(
'value' => elgg_echo('cancel'),
'class' => 'elgg-button-cancel mlm',
));
-$cancel_button = trim($cancel_button);
+$cancel_button = json_encode($cancel_button);
if (0) { ?><script><?php }
?>
@@ -23,10 +22,11 @@ elgg.walled_garden.init = function () {
$('.registration_link').click(elgg.walled_garden.load('register'));
$('input.elgg-button-cancel').live('click', function(event) {
- if ($('.elgg-walledgarden-single').is(':visible')) {
+ var $wgs = $('.elgg-walledgarden-single');
+ if ($wgs.is(':visible')) {
$('.elgg-walledgarden-double').fadeToggle();
- $('.elgg-walledgarden-single').fadeToggle();
- $('.elgg-walledgarden-single').remove();
+ $wgs.fadeToggle();
+ $wgs.remove();
}
event.preventDefault();
});
@@ -42,12 +42,22 @@ elgg.walled_garden.load = function(view) {
return function(event) {
var id = '#elgg-walledgarden-' + view;
id = id.replace('_', '-');
+ //@todo display some visual element that indicates that loading of content is running
elgg.get('walled_garden/' + view, {
'success' : function(data) {
- $('.elgg-body-walledgarden').append(data);
- $(id).find('input.elgg-button-submit').after('<?php echo $cancel_button; ?>');
- $('#elgg-walledgarden-login').fadeToggle();
- $(id).fadeToggle();
+ var $wg = $('.elgg-body-walledgarden');
+ $wg.append(data);
+ $(id).find('input.elgg-button-submit').after(<?php echo $cancel_button; ?>);
+
+ if (view == 'register' && $wg.hasClass('hidden')) {
+ // this was a failed register, display the register form ASAP
+ $('#elgg-walledgarden-login').toggle(false);
+ $(id).toggle();
+ $wg.removeClass('hidden');
+ } else {
+ $('#elgg-walledgarden-login').fadeToggle();
+ $(id).fadeToggle();
+ }
}
});
event.preventDefault();
diff --git a/views/default/object/default.php b/views/default/object/default.php
index 110648304..70e098742 100644
--- a/views/default/object/default.php
+++ b/views/default/object/default.php
@@ -41,7 +41,6 @@ $params = array(
'title' => $title,
'metadata' => $metadata,
'subtitle' => $subtitle,
- 'tags' => $vars['entity']->tags,
);
$params = $params + $vars;
$body = elgg_view('object/elements/summary', $params);
diff --git a/views/default/object/elements/full.php b/views/default/object/elements/full.php
index 9b89f9706..b4634fe7e 100644
--- a/views/default/object/elements/full.php
+++ b/views/default/object/elements/full.php
@@ -22,9 +22,9 @@ $summary = elgg_extract('summary', $vars);
$body = elgg_extract('body', $vars);
$class = elgg_extract('class', $vars);
if ($class) {
- $class = "elgg-content $class";
+ $class = "elgg-content clearfix $class";
} else {
- $class = "elgg-content";
+ $class = "elgg-content clearfix";
}
$header = elgg_view_image_block($icon, $summary);
diff --git a/views/default/object/elements/summary.php b/views/default/object/elements/summary.php
index c0f3ad340..63ab8f816 100644
--- a/views/default/object/elements/summary.php
+++ b/views/default/object/elements/summary.php
@@ -27,7 +27,7 @@ if ($title_link === '') {
$text = $entity->name;
}
$params = array(
- 'text' => $text,
+ 'text' => elgg_get_excerpt($text, 100),
'href' => $entity->getURL(),
'is_trusted' => true,
);
diff --git a/views/default/page/walled_garden.php b/views/default/page/walled_garden.php
index ff8e317c7..b280cf6b2 100644
--- a/views/default/page/walled_garden.php
+++ b/views/default/page/walled_garden.php
@@ -5,6 +5,12 @@
* Used for the walled garden index page
*/
+$is_sticky_register = elgg_is_sticky_form('register');
+$wg_body_class = 'elgg-body-walledgarden';
+if ($is_sticky_register) {
+ $wg_body_class .= ' hidden';
+}
+
// Set the content type
header("Content-type: text/html; charset=UTF-8");
?>
@@ -18,10 +24,17 @@ header("Content-type: text/html; charset=UTF-8");
<div class="elgg-page-messages">
<?php echo elgg_view('page/elements/messages', array('object' => $vars['sysmessages'])); ?>
</div>
- <div class="elgg-body-walledgarden">
+ <div class="<?php echo $wg_body_class; ?>">
<?php echo $vars['body']; ?>
</div>
</div>
+<?php if ($is_sticky_register): ?>
+<script type="text/javascript">
+elgg.register_hook_handler('init', 'system', function() {
+ $('.registration_link').trigger('click');
+});
+</script>
+<?php endif; ?>
<?php echo elgg_view('page/elements/foot'); ?>
</body>
</html> \ No newline at end of file
diff --git a/views/default/river/elements/summary.php b/views/default/river/elements/summary.php
index 416bc708b..d7bde51dd 100644
--- a/views/default/river/elements/summary.php
+++ b/views/default/river/elements/summary.php
@@ -18,9 +18,10 @@ $subject_link = elgg_view('output/url', array(
'is_trusted' => true,
));
+$object_text = $object->title ? $object->title : $object->name;
$object_link = elgg_view('output/url', array(
'href' => $object->getURL(),
- 'text' => $object->title ? $object->title : $object->name,
+ 'text' => elgg_get_excerpt($object_text, 100),
'class' => 'elgg-river-object',
'is_trusted' => true,
));