diff options
Diffstat (limited to 'engine')
78 files changed, 1429 insertions, 806 deletions
diff --git a/engine/classes/ElggBatch.php b/engine/classes/ElggBatch.php index 62128e34f..0cb13eb32 100644 --- a/engine/classes/ElggBatch.php +++ b/engine/classes/ElggBatch.php @@ -3,47 +3,51 @@   * Efficiently run operations on batches of results for any function   * that supports an options array.   * - * This is usually used with elgg_get_entities() and friends, elgg_get_annotations() - * and elgg_get_metadata(). + * This is usually used with elgg_get_entities() and friends, + * elgg_get_annotations(), and elgg_get_metadata().   * - * If you pass a valid PHP callback, all results will be run through that callback. - * You can still foreach() through the result set after.  Valid PHP callbacks - * can be a string, an array, or a closure. + * If you pass a valid PHP callback, all results will be run through that + * callback. You can still foreach() through the result set after.  Valid + * PHP callbacks can be a string, an array, or a closure.   * {@link http://php.net/manual/en/language.pseudo-types.php}   * - * The callback function must accept 3 arguments: an entity, the getter used, and the options used. + * The callback function must accept 3 arguments: an entity, the getter + * used, and the options used.   * - * Results from the callback are stored in callbackResult. - * If the callback returns only booleans, callbackResults will be the combined - * result of all calls. + * Results from the callback are stored in callbackResult. If the callback + * returns only booleans, callbackResults will be the combined result of + * all calls.   * - * If the callback returns anything else, callbackresult will be an indexed array - * of whatever the callback returns.  If returning error handling information, - * you should include enough information to determine which result you're referring - * to. + * If the callback returns anything else, callbackresult will be an indexed + * array of whatever the callback returns.  If returning error handling + * information, you should include enough information to determine which + * result you're referring to.   *   * Don't combine returning bools and returning something else.   *   * Note that returning false will not stop the foreach.   * + * @warning If your callback or foreach loop deletes or disable entities + * you MUST call setIncrementOffset(false) or set that when instantiating. + * This forces the offset to stay what it was in the $options array. + *   * @example   * <code> + * // using foreach   * $batch = new ElggBatch('elgg_get_entities', array()); + * $batch->setIncrementOffset(false);   *   * foreach ($batch as $entity) {   * 	$entity->disable();   * }   * + * // using both a callback   * $callback = function($result, $getter, $options) { - * 	var_dump("Going to delete annotation id: $result->id"); + * 	var_dump("Looking at annotation id: $result->id");   *  return true;   * }   *   * $batch = new ElggBatch('elgg_get_annotations', array('guid' => 2), $callback); - * - * foreach ($batch as $annotation) { - * 	$annotation->delete(); - * }   * </code>   *   * @package    Elgg.Core @@ -92,7 +96,7 @@ class ElggBatch  	/**  	 * Stop after this many results.  	 * -	 * @var unknown_type +	 * @var int  	 */  	private $limit = 0; @@ -139,6 +143,13 @@ class ElggBatch  	public $callbackResult = null;  	/** +	 * If false, offset will not be incremented. This is used for callbacks/loops that delete. +	 * +	 * @var bool +	 */ +	private $incrementOffset = true; + +	/**  	 * Batches operations on any elgg_get_*() or compatible function that supports  	 * an options array.  	 * @@ -147,19 +158,27 @@ class ElggBatch  	 *  	 * @param string $getter     The function used to get objects.  Usually  	 *                           an elgg_get_*() function, but can be any valid PHP callback. -	 * @param array  $options    The options array to pass to the getter function +	 * @param array  $options    The options array to pass to the getter function. If limit is +	 *                           not set, 10 is used as the default. In most cases that is not +	 *                           what you want.  	 * @param mixed  $callback   An optional callback function that all results will be passed  	 *                           to upon load.  The callback needs to accept $result, $getter,  	 *                           $options.  	 * @param int    $chunk_size The number of entities to pull in before requesting more.  	 *                           You have to balance this between running out of memory in PHP  	 *                           and hitting the db server too often. +	 * @param bool   $inc_offset Increment the offset on each fetch. This must be false for +	 *                           callbacks that delete rows. You can set this after the +	 *                           object is created with {@see ElggBatch::setIncrementOffset()}.  	 */ -	public function __construct($getter, $options, $callback = null, $chunk_size = 25) { +	public function __construct($getter, $options, $callback = null, $chunk_size = 25, +			$inc_offset = true) { +		  		$this->getter = $getter;  		$this->options = $options;  		$this->callback = $callback;  		$this->chunkSize = $chunk_size; +		$this->setIncrementOffset($inc_offset);  		if ($this->chunkSize <= 0) {  			$this->chunkSize = 25; @@ -172,7 +191,7 @@ class ElggBatch  		// if passed a callback, create a new ElggBatch with the same options  		// and pass each to the callback.  		if ($callback && is_callable($callback)) { -			$batch = new ElggBatch($getter, $options, null, $chunk_size); +			$batch = new ElggBatch($getter, $options, null, $chunk_size, $inc_offset);  			$all_results = null; @@ -234,20 +253,24 @@ class ElggBatch  			}  			// if original limit < chunk size, set limit to original limit +			// else if the number of results we'll fetch if greater than the original limit  			if ($this->limit < $this->chunkSize) {  				$limit = $this->limit; -			} - -			// if the number of results we'll fetch is greater than the original limit, -			// set the limit to the number of results remaining in the original limit -			elseif ($this->retrievedResults + $this->chunkSize > $this->limit) { +			} elseif ($this->retrievedResults + $this->chunkSize > $this->limit) { +				// set the limit to the number of results remaining in the original limit  				$limit = $this->limit - $this->retrievedResults;  			}  		} +		if ($this->incrementOffset) { +			$offset = $this->offset + $this->retrievedResults; +		} else { +			$offset = $this->offset; +		} +  		$current_options = array(  			'limit' => $limit, -			'offset' => $this->offset + $this->retrievedResults +			'offset' => $offset  		);  		$options = array_merge($this->options, $current_options); @@ -270,6 +293,16 @@ class ElggBatch  	}  	/** +	 * Increment the offset from the original options array? Setting to +	 * false is required for callbacks that delete rows. +	 * +	 * @param bool $increment +	 */ +	public function setIncrementOffset($increment = true) { +		$this->incrementOffset = (bool) $increment; +	} + +	/**  	 * Implements Iterator  	 */ @@ -319,13 +352,13 @@ class ElggBatch  	 */  	public function next() {  		// if we'll be at the end. -		if ($this->processedResults + 1 >= $this->limit && $this->limit > 0) { +		if (($this->processedResults + 1) >= $this->limit && $this->limit > 0) {  			$this->results = array();  			return false;  		}  		// if we'll need new results. -		if ($this->resultIndex + 1 >= $this->chunkSize) { +		if (($this->resultIndex + 1) >= $this->chunkSize) {  			if (!$this->getNextResultsChunk()) {  				$this->results = array();  				return false; @@ -356,4 +389,4 @@ class ElggBatch  		$key = key($this->results);  		return ($key !== NULL && $key !== FALSE);  	} -}
\ No newline at end of file +} diff --git a/engine/classes/ElggCache.php b/engine/classes/ElggCache.php index 5c2cafcb7..4317f4be9 100644 --- a/engine/classes/ElggCache.php +++ b/engine/classes/ElggCache.php @@ -29,7 +29,7 @@ abstract class ElggCache implements ArrayAccess {  	 *  	 * @return void  	 * -	 * @deprecated 1.8 Use ElggAccess:setVariable() +	 * @deprecated 1.8 Use ElggCache:setVariable()  	 */  	public function set_variable($variable, $value) {  		elgg_deprecated_notice('ElggCache::set_variable() is deprecated by ElggCache::setVariable()', 1.8); @@ -191,8 +191,8 @@ abstract class ElggCache implements ArrayAccess {  	 *  	 * @see ArrayAccess::offsetSet()  	 * -	 * @param mixed $key    The key (offset) to assign the value to. -	 * @param mixed $value  The value to set. +	 * @param mixed $key   The key (offset) to assign the value to. +	 * @param mixed $value The value to set.  	 *  	 * @return void  	 */ @@ -205,7 +205,7 @@ abstract class ElggCache implements ArrayAccess {  	 *  	 * @see ArrayAccess::offsetGet()  	 * -	 * @param mixed $offset The key (offset) to retrieve. +	 * @param mixed $key The key (offset) to retrieve.  	 *  	 * @return mixed  	 */ diff --git a/engine/classes/ElggDiskFilestore.php b/engine/classes/ElggDiskFilestore.php index 11b2bd947..f00376481 100644 --- a/engine/classes/ElggDiskFilestore.php +++ b/engine/classes/ElggDiskFilestore.php @@ -205,7 +205,7 @@ class ElggDiskFilestore extends ElggFilestore {  			$owner = elgg_get_logged_in_user_entity();  		} -		if ((!$owner) || (!$owner->username)) { +		if (!$owner) {  			$msg = elgg_echo('InvalidParameterException:MissingOwner',  				array($file->getFilename(), $file->guid));  			throw new InvalidParameterException($msg); diff --git a/engine/classes/ElggEntity.php b/engine/classes/ElggEntity.php index df87082fe..dc38dafbe 100644 --- a/engine/classes/ElggEntity.php +++ b/engine/classes/ElggEntity.php @@ -1311,12 +1311,16 @@ abstract class ElggEntity extends ElggData implements  	/**  	 * Loads attributes from the entities table into the object.  	 * -	 * @param int $guid GUID of Entity +	 * @param mixed $guid GUID of entity or stdClass object from entities table  	 *  	 * @return bool  	 */  	protected function load($guid) { -		$row = get_entity_as_row($guid); +		if ($guid instanceof stdClass) { +			$row = $guid; +		} else { +			$row = get_entity_as_row($guid); +		}  		if ($row) {  			// Create the array if necessary - all subclasses should test before creating @@ -1583,36 +1587,36 @@ abstract class ElggEntity extends ElggData implements  		foreach ($this->attributes as $k => $v) {  			$meta = NULL; -			if (in_array( $k, $exportable_values)) { +			if (in_array($k, $exportable_values)) {  				switch ($k) { -					case 'guid' : 			// Dont use guid in OpenDD -					case 'type' :			// Type and subtype already taken care of -					case 'subtype' : -					break; +					case 'guid':			// Dont use guid in OpenDD +					case 'type':			// Type and subtype already taken care of +					case 'subtype': +						break; -					case 'time_created' :	// Created = published +					case 'time_created':	// Created = published  						$odd->setAttribute('published', date("r", $v)); -					break; +						break; -					case 'site_guid' : // Container +					case 'site_guid':	// Container  						$k = 'site_uuid';  						$v = guid_to_uuid($v);  						$meta = new ODDMetaData($uuid . "attr/$k/", $uuid, $k, $v); -					break; +						break; -					case 'container_guid' : // Container +					case 'container_guid':	// Container  						$k = 'container_uuid';  						$v = guid_to_uuid($v);  						$meta = new ODDMetaData($uuid . "attr/$k/", $uuid, $k, $v); -					break; +						break; -					case 'owner_guid' :			// Convert owner guid to uuid, this will be stored in metadata +					case 'owner_guid':			// Convert owner guid to uuid, this will be stored in metadata  						$k = 'owner_uuid';  						$v = guid_to_uuid($v);  						$meta = new ODDMetaData($uuid . "attr/$k/", $uuid, $k, $v); -					break; +						break; -					default : +					default:  						$meta = new ODDMetaData($uuid . "attr/$k/", $uuid, $k, $v);  				} diff --git a/engine/classes/ElggExtender.php b/engine/classes/ElggExtender.php index d6f79d18d..d94bad837 100644 --- a/engine/classes/ElggExtender.php +++ b/engine/classes/ElggExtender.php @@ -3,8 +3,7 @@   * The base class for ElggEntity extenders.   *   * Extenders allow you to attach extended information to an - * ElggEntity.  Core supports two: ElggAnnotation, ElggMetadata, - * and ElggRelationship + * ElggEntity.  Core supports two: ElggAnnotation and ElggMetadata.   *   * Saving the extender data to database is handled by the child class.   * @@ -16,9 +15,24 @@   * @link       http://docs.elgg.org/DataModel/Extenders   * @see        ElggAnnotation   * @see        ElggMetadata + *  + * @property string $type         annotation or metadata (read-only after save) + * @property int    $id           The unique identifier (read-only) + * @property int    $entity_guid  The GUID of the entity that this extender describes + * @property int    $access_id    Specifies the visibility level of this extender + * @property string $name         The name of this extender + * @property mixed  $value        The value of the extender (int or string) + * @property int    $time_created A UNIX timestamp of when the extender was created (read-only, set on first save)   */ -abstract class ElggExtender extends ElggData -{ +abstract class ElggExtender extends ElggData { + +	/** +	 * (non-PHPdoc) +	 * +	 * @see ElggData::initializeAttributes() +	 * +	 * @return void +	 */  	protected function initializeAttributes() {  		parent::initializeAttributes(); diff --git a/engine/classes/ElggFileCache.php b/engine/classes/ElggFileCache.php index 8304372dc..34178d452 100644 --- a/engine/classes/ElggFileCache.php +++ b/engine/classes/ElggFileCache.php @@ -161,12 +161,25 @@ class ElggFileCache extends ElggCache {  	}  	/** -	 * This was probably meant to delete everything? +	 * Delete all files in the directory of this file cache  	 *  	 * @return void  	 */  	public function clear() { -		// @todo writeme +		$dir = $this->getVariable("cache_path"); + +		$exclude = array(".", ".."); + +		$files = scandir($dir); +		if (!$files) { +			return; +		} + +		foreach ($files as $f) { +			if (!in_array($f, $exclude)) { +				unlink($dir . $f); +			} +		}  	}  	/** @@ -184,7 +197,7 @@ class ElggFileCache extends ElggCache {  			return;  		} -		$exclude = array(".",".."); +		$exclude = array(".", "..");  		$files = scandir($dir);  		if (!$files) { diff --git a/engine/classes/ElggGroup.php b/engine/classes/ElggGroup.php index 0190e5eac..f7f67bf41 100644 --- a/engine/classes/ElggGroup.php +++ b/engine/classes/ElggGroup.php @@ -5,6 +5,9 @@   *   * @package    Elgg.Core   * @subpackage Groups + *  + * @property string $name        A short name that captures the purpose of the group + * @property string $description A longer body of content that gives more details about the group   */  class ElggGroup extends ElggEntity  	implements Friendable { @@ -26,12 +29,12 @@ class ElggGroup extends ElggEntity  	}  	/** -	 * Construct a new user entity, optionally from a given id value. +	 * Construct a new group entity, optionally from a given guid value.  	 *  	 * @param mixed $guid If an int, load that GUID. -	 * 	If a db row then will attempt to load the rest of the data. +	 * 	If an entity table db row, then will load the rest of the data.  	 * -	 * @throws Exception if there was a problem creating the user. +	 * @throws Exception if there was a problem creating the group.  	 */  	function __construct($guid = null) {  		$this->initializeAttributes(); @@ -40,15 +43,15 @@ class ElggGroup extends ElggEntity  		$this->initialise_attributes(false);  		if (!empty($guid)) { -			// Is $guid is a DB row - either a entity row, or a user table row. +			// Is $guid is a entity table DB row  			if ($guid instanceof stdClass) {  				// Load the rest -				if (!$this->load($guid->guid)) { +				if (!$this->load($guid)) {  					$msg = elgg_echo('IOException:FailedToLoadGUID', array(get_class(), $guid->guid));  					throw new IOException($msg);  				} -				// Is $guid is an ElggGroup? Use a copy constructor +			// Is $guid is an ElggGroup? Use a copy constructor  			} else if ($guid instanceof ElggGroup) {  				elgg_deprecated_notice('This type of usage of the ElggGroup constructor was deprecated. Please use the clone method.', 1.7); @@ -56,11 +59,11 @@ class ElggGroup extends ElggEntity  					$this->attributes[$key] = $value;  				} -				// Is this is an ElggEntity but not an ElggGroup = ERROR! +			// Is this is an ElggEntity but not an ElggGroup = ERROR!  			} else if ($guid instanceof ElggEntity) {  				throw new InvalidParameterException(elgg_echo('InvalidParameterException:NonElggGroup')); -				// We assume if we have got this far, $guid is an int +			// Is it a GUID  			} else if (is_numeric($guid)) {  				if (!$this->load($guid)) {  					throw new IOException(elgg_echo('IOException:FailedToLoadGUID', array(get_class(), $guid))); @@ -316,11 +319,9 @@ class ElggGroup extends ElggEntity  	}  	/** -	 * Override the load function. -	 * This function will ensure that all data is loaded (were possible), so -	 * if only part of the ElggGroup is loaded, it'll load the rest. +	 * Load the ElggGroup data from the database  	 * -	 * @param int $guid GUID of an ElggGroup entity +	 * @param mixed $guid GUID of an ElggGroup entity or database row from entity table  	 *  	 * @return bool  	 */ @@ -330,6 +331,11 @@ class ElggGroup extends ElggEntity  			return false;  		} +		// Only work with GUID from here +		if ($guid instanceof stdClass) { +			$guid = $guid->guid; +		} +  		// Check the type  		if ($this->attributes['type'] != 'group') {  			$msg = elgg_echo('InvalidClassException:NotValidElggStar', array($guid, get_class())); diff --git a/engine/classes/ElggMemcache.php b/engine/classes/ElggMemcache.php index a54c29723..f27b017d0 100644 --- a/engine/classes/ElggMemcache.php +++ b/engine/classes/ElggMemcache.php @@ -114,27 +114,11 @@ class ElggMemcache extends ElggSharedMemoryCache {  	 * Combine a key with the namespace.  	 * Memcache can only accept <250 char key. If the given key is too long it is shortened.  	 * -	 * @deprecated 1.8 Use ElggMemcache::_makeMemcacheKey() -	 * -	 * @param string $key The key -	 * -	 * @return string The new key. -	 */ -	private function make_memcache_key($key) { -		elgg_deprecated_notice('ElggMemcache::make_memcache_key() is deprecated by ::_makeMemcacheKey()', 1.8); - -		return $this->_makeMemcacheKey($key); -	} - -	/** -	 * Combine a key with the namespace. -	 * Memcache can only accept <250 char key. If the given key is too long it is shortened. -	 *  	 * @param string $key The key  	 *  	 * @return string The new key.  	 */ -	private function _makeMemcacheKey($key) { +	private function makeMemcacheKey($key) {  		$prefix = $this->getNamespace() . ":";  		if (strlen($prefix . $key) > 250) { @@ -154,7 +138,7 @@ class ElggMemcache extends ElggSharedMemoryCache {  	 * @return bool  	 */  	public function save($key, $data, $expires = null) { -		$key = $this->_makeMemcacheKey($key); +		$key = $this->makeMemcacheKey($key);  		if ($expires === null) {  			$expires = $this->expires; @@ -178,7 +162,7 @@ class ElggMemcache extends ElggSharedMemoryCache {  	 * @return mixed  	 */  	public function load($key, $offset = 0, $limit = null) { -		$key = $this->_makeMemcacheKey($key); +		$key = $this->makeMemcacheKey($key);  		$result = $this->memcache->get($key);  		if ($result === false) { @@ -196,7 +180,7 @@ class ElggMemcache extends ElggSharedMemoryCache {  	 * @return bool  	 */  	public function delete($key) { -		$key = $this->_makeMemcacheKey($key); +		$key = $this->makeMemcacheKey($key);  		return $this->memcache->delete($key, 0);  	} diff --git a/engine/classes/ElggMenuBuilder.php b/engine/classes/ElggMenuBuilder.php index cadfee7f5..de0017599 100644 --- a/engine/classes/ElggMenuBuilder.php +++ b/engine/classes/ElggMenuBuilder.php @@ -4,8 +4,7 @@   *   * @package    Elgg.Core   * @subpackage Navigation - * - * @since 1.8.0 + * @since      1.8.0   */  class ElggMenuBuilder { @@ -16,16 +15,16 @@ class ElggMenuBuilder {  	/**  	 * ElggMenuBuilder constructor  	 * -	 * @param string $name  Identifier of the menu +	 * @param array $menu Array of ElggMenuItem objects  	 */ -	public function __construct($menu) { +	public function __construct(array $menu) {  		$this->menu = $menu;  	}  	/**  	 * Get a prepared menu array  	 * -	 * @param mixed $sort_by +	 * @param mixed $sort_by Method to sort the menu by. @see ElggMenuBuilder::sort()  	 * @return array  	 */  	public function getMenu($sort_by = 'text') { @@ -80,6 +79,7 @@ class ElggMenuBuilder {  	/**  	 * Group the menu items into sections +	 *   	 * @return void  	 */  	protected function setupSections() { diff --git a/engine/classes/ElggMenuItem.php b/engine/classes/ElggMenuItem.php index 62547134a..4bc9144d4 100644 --- a/engine/classes/ElggMenuItem.php +++ b/engine/classes/ElggMenuItem.php @@ -2,12 +2,11 @@  /**   * Elgg Menu Item   * - * @package    Elgg.Core - * @subpackage Navigation - *   * To create a menu item that is not a link, pass false for $href.   * - * @since 1.8.0 + * @package    Elgg.Core + * @subpackage Navigation + * @since      1.8.0   */  class ElggMenuItem { @@ -70,9 +69,9 @@ class ElggMenuItem {  	/**  	 * ElggMenuItem constructor  	 * -	 * @param string $name  Identifier of the menu item -	 * @param string $text  Display text of the menu item -	 * @param string $href  URL of the menu item (false if not a link) +	 * @param string $name Identifier of the menu item +	 * @param string $text Display text of the menu item +	 * @param string $href URL of the menu item (false if not a link)  	 */  	public function __construct($name, $text, $href) {  		//$this->name = $name; @@ -182,7 +181,7 @@ class ElggMenuItem {  	/**  	 * Set the identifier of the menu item  	 * -	 * @param string Unique identifier +	 * @param string $name Unique identifier  	 * @return void  	 */  	public function setName($name) { @@ -491,7 +490,7 @@ class ElggMenuItem {  	/**  	 * Set the parent menu item  	 * -	 * @param ElggMenuItem $parent +	 * @param ElggMenuItem $parent The parent of this menu item  	 * @return void  	 */  	public function setParent($parent) { @@ -510,7 +509,7 @@ class ElggMenuItem {  	/**  	 * Add a child menu item  	 * -	 * @param ElggMenuItem $item +	 * @param ElggMenuItem $item A child menu item  	 * @return void  	 */  	public function addChild($item) { @@ -549,9 +548,8 @@ class ElggMenuItem {  	/**  	 * Get the menu item content (usually a link)  	 * -	 * @params array $vars Options to pass to output/url if a link +	 * @param array $vars Options to pass to output/url if a link  	 * @return string -	 *  	 * @todo View code in a model.  How do we feel about that?  	 */  	public function getContent(array $vars = array()) { diff --git a/engine/classes/ElggMetadata.php b/engine/classes/ElggMetadata.php index 32e7b32f1..634a122e5 100644 --- a/engine/classes/ElggMetadata.php +++ b/engine/classes/ElggMetadata.php @@ -9,6 +9,13 @@   */  class ElggMetadata extends ElggExtender { +	/** +	 * (non-PHPdoc) +	 * +	 * @see ElggData::initializeAttributes() +	 * +	 * @return void +	 */  	protected function initializeAttributes() {  		parent::initializeAttributes(); diff --git a/engine/classes/ElggObject.php b/engine/classes/ElggObject.php index 0b8340697..b4bae6825 100644 --- a/engine/classes/ElggObject.php +++ b/engine/classes/ElggObject.php @@ -14,6 +14,10 @@   *   * @package    Elgg.Core   * @subpackage DataModel.Object + *  + * @property string $title       The title, name, or summary of this object + * @property string $description The body, description, or content of the object + * @property array  $tags        Array of tags that describe the object   */  class ElggObject extends ElggEntity { @@ -37,12 +41,12 @@ class ElggObject extends ElggEntity {  	 *  	 * If no arguments are passed, create a new entity.  	 * -	 * If an argument is passed attempt to load a full Object entity.  Arguments -	 * can be: +	 * If an argument is passed, attempt to load a full ElggObject entity. +	 * Arguments can be:  	 *  - The GUID of an object entity. -	 *  - A DB result object with a guid property +	 *  - A DB result object from the entities table with a guid property  	 * -	 * @param mixed $guid If an int, load that GUID.  If a db row then will attempt to +	 * @param mixed $guid If an int, load that GUID.  If a db row, then will attempt to  	 * load the rest of the data.  	 *  	 * @throws IOException If passed an incorrect guid @@ -55,15 +59,15 @@ class ElggObject extends ElggEntity {  		$this->initialise_attributes(false);  		if (!empty($guid)) { -			// Is $guid is a DB row - either a entity row, or a object table row. +			// Is $guid is a DB row from the entity table  			if ($guid instanceof stdClass) {  				// Load the rest -				if (!$this->load($guid->guid)) { +				if (!$this->load($guid)) {  					$msg = elgg_echo('IOException:FailedToLoadGUID', array(get_class(), $guid->guid));  					throw new IOException($msg);  				} -				// Is $guid is an ElggObject? Use a copy constructor +			// Is $guid is an ElggObject? Use a copy constructor  			} else if ($guid instanceof ElggObject) {  				elgg_deprecated_notice('This type of usage of the ElggObject constructor was deprecated. Please use the clone method.', 1.7); @@ -71,11 +75,11 @@ class ElggObject extends ElggEntity {  					$this->attributes[$key] = $value;  				} -				// Is this is an ElggEntity but not an ElggObject = ERROR! +			// Is this is an ElggEntity but not an ElggObject = ERROR!  			} else if ($guid instanceof ElggEntity) {  				throw new InvalidParameterException(elgg_echo('InvalidParameterException:NonElggObject')); -				// We assume if we have got this far, $guid is an int +			// Is it a GUID  			} else if (is_numeric($guid)) {  				if (!$this->load($guid)) {  					throw new IOException(elgg_echo('IOException:FailedToLoadGUID', array(get_class(), $guid))); @@ -89,17 +93,22 @@ class ElggObject extends ElggEntity {  	/**  	 * Loads the full ElggObject when given a guid.  	 * -	 * @param int $guid Guid of an ElggObject +	 * @param mixed $guid GUID of an ElggObject or the stdClass object from entities table  	 *  	 * @return bool  	 * @throws InvalidClassException  	 */  	protected function load($guid) { -		// Test to see if we have the generic stuff +		// Load data from entity table if needed  		if (!parent::load($guid)) {  			return false;  		} +		// Only work with GUID from here +		if ($guid instanceof stdClass) { +			$guid = $guid->guid; +		} +  		// Check the type  		if ($this->attributes['type'] != 'object') {  			$msg = elgg_echo('InvalidClassException:NotValidElggStar', array($guid, get_class())); diff --git a/engine/classes/ElggPlugin.php b/engine/classes/ElggPlugin.php index c4d6ec034..33f14ae37 100644 --- a/engine/classes/ElggPlugin.php +++ b/engine/classes/ElggPlugin.php @@ -707,9 +707,9 @@ class ElggPlugin extends ElggObject {  	 * @throws PluginException  	 */  	public function start($flags) { -//		if (!$this->canActivate()) { -//			return false; -//		} +		//if (!$this->canActivate()) { +		//	return false; +		//}  		// include classes  		if ($flags & ELGG_PLUGIN_REGISTER_CLASSES) { diff --git a/engine/classes/ElggPluginPackage.php b/engine/classes/ElggPluginPackage.php index d240af477..2dc4bdb3d 100644 --- a/engine/classes/ElggPluginPackage.php +++ b/engine/classes/ElggPluginPackage.php @@ -303,6 +303,8 @@ class ElggPluginPackage {  	/**  	 * Returns an array of present and readable text files +	 * +	 * @return array  	 */  	public function getTextFilenames() {  		return $this->textFiles; diff --git a/engine/classes/ElggRelationship.php b/engine/classes/ElggRelationship.php index 2d9a32cbd..efc0f7eff 100644 --- a/engine/classes/ElggRelationship.php +++ b/engine/classes/ElggRelationship.php @@ -4,6 +4,12 @@   *   * @package    Elgg.Core   * @subpackage Core + *  + * @property int    $id           The unique identifier (read-only) + * @property int    $guid_one     The GUID of the subject of the relationship + * @property string $relationship The name of the relationship + * @property int    $guid_two     The GUID of the object of the relationship + * @property int    $time_created A UNIX timestamp of when the relationship was created (read-only, set on first save)   */  class ElggRelationship extends ElggData implements  	Importable diff --git a/engine/classes/ElggRiverItem.php b/engine/classes/ElggRiverItem.php index fcc8f9c85..d3d09cd91 100644 --- a/engine/classes/ElggRiverItem.php +++ b/engine/classes/ElggRiverItem.php @@ -4,9 +4,19 @@   *   * @package    Elgg.Core   * @subpackage Core + *  + * @property int    $id            The unique identifier (read-only) + * @property int    $subject_guid  The GUID of the actor + * @property int    $object_guid   The GUID of the object + * @property int    $annotation_id The ID of the annotation involved in the action + * @property string $type          The type of one of the entities involved in the action + * @property string $subtype       The subtype of one of the entities involved in the action + * @property string $action_type   The name of the action + * @property string $view          The view for displaying this river item + * @property int    $access_id     The visibility of the river item + * @property int    $posted        UNIX timestamp when the action occurred   */ -class ElggRiverItem -{ +class ElggRiverItem {  	public $id;  	public $subject_guid;  	public $object_guid; diff --git a/engine/classes/ElggSite.php b/engine/classes/ElggSite.php index 3ccb146fb..49616f1be 100644 --- a/engine/classes/ElggSite.php +++ b/engine/classes/ElggSite.php @@ -21,6 +21,10 @@   * @package    Elgg.Core   * @subpackage DataMode.Site   * @link       http://docs.elgg.org/DataModel/Sites + *  + * @property string $name        The name or title of the website + * @property string $description A motto, mission statement, or description of the website + * @property string $url         The root web address for the site, including trailing slash   */  class ElggSite extends ElggEntity { @@ -53,8 +57,8 @@ class ElggSite extends ElggEntity {  	 *  - A URL as stored in ElggSite->url  	 *  - A DB result object with a guid property  	 * -	 * @param mixed $guid If an int, load that GUID.  If a db row then will attempt -	 * to load the rest of the data. +	 * @param mixed $guid If an int, load that GUID.  If a db row then will +	 * load the rest of the data.  	 *  	 * @throws IOException If passed an incorrect guid  	 * @throws InvalidParameterException If passed an Elgg* Entity that isn't an ElggSite @@ -66,15 +70,15 @@ class ElggSite extends ElggEntity {  		$this->initialise_attributes(false);  		if (!empty($guid)) { -			// Is $guid is a DB row - either a entity row, or a site table row. +			// Is $guid is a DB entity table row  			if ($guid instanceof stdClass) {  				// Load the rest -				if (!$this->load($guid->guid)) { +				if (!$this->load($guid)) {  					$msg = elgg_echo('IOException:FailedToLoadGUID', array(get_class(), $guid->guid));  					throw new IOException($msg);  				} -				// Is $guid is an ElggSite? Use a copy constructor +			// Is $guid is an ElggSite? Use a copy constructor  			} else if ($guid instanceof ElggSite) {  				elgg_deprecated_notice('This type of usage of the ElggSite constructor was deprecated. Please use the clone method.', 1.7); @@ -82,18 +86,18 @@ class ElggSite extends ElggEntity {  					$this->attributes[$key] = $value;  				} -				// Is this is an ElggEntity but not an ElggSite = ERROR! +			// Is this is an ElggEntity but not an ElggSite = ERROR!  			} else if ($guid instanceof ElggEntity) {  				throw new InvalidParameterException(elgg_echo('InvalidParameterException:NonElggSite')); -				// See if this is a URL +			// See if this is a URL  			} else if (strpos($guid, "http") !== false) {  				$guid = get_site_by_url($guid);  				foreach ($guid->attributes as $key => $value) {  					$this->attributes[$key] = $value;  				} -				// We assume if we have got this far, $guid is an int +			// Is it a GUID  			} else if (is_numeric($guid)) {  				if (!$this->load($guid)) {  					throw new IOException(elgg_echo('IOException:FailedToLoadGUID', array(get_class(), $guid))); @@ -107,7 +111,7 @@ class ElggSite extends ElggEntity {  	/**  	 * Loads the full ElggSite when given a guid.  	 * -	 * @param int $guid Guid of ElggSite entity +	 * @param mixed $guid GUID of ElggSite entity or database row object  	 *  	 * @return bool  	 * @throws InvalidClassException @@ -118,6 +122,11 @@ class ElggSite extends ElggEntity {  			return false;  		} +		// Only work with GUID from here +		if ($guid instanceof stdClass) { +			$guid = $guid->guid; +		} +  		// Check the type  		if ($this->attributes['type'] != 'site') {  			$msg = elgg_echo('InvalidClassException:NotValidElggStar', array($guid, get_class())); @@ -192,7 +201,7 @@ class ElggSite extends ElggEntity {  	 *  	 * @note You cannot disable the current site.  	 * -	 * @param string $reason Optional reason for disabling +	 * @param string $reason    Optional reason for disabling  	 * @param bool   $recursive Recursively disable all contained entities?  	 *  	 * @return bool @@ -215,7 +224,7 @@ class ElggSite extends ElggEntity {  	 *                       accepted by elgg_get_entities(). Common parameters  	 *                       include 'limit', and 'offset'.  	 *                       Note: this was $limit before version 1.8 -	 * @param int $offset Offset @deprecated parameter +	 * @param int   $offset  Offset @deprecated parameter  	 *  	 * @todo remove $offset in 2.0  	 * @@ -231,6 +240,7 @@ class ElggSite extends ElggEntity {  		}  		$defaults = array( +			'site_guids' => ELGG_ENTITIES_ANY_VALUE,  			'relationship' => 'member_of_site',  			'relationship_guid' => $this->getGUID(),  			'inverse_relationship' => TRUE, @@ -254,6 +264,7 @@ class ElggSite extends ElggEntity {  	 */  	public function listMembers($options = array()) {  		$defaults = array( +			'site_guids' => ELGG_ENTITIES_ANY_VALUE,  			'relationship' => 'member_of_site',  			'relationship_guid' => $this->getGUID(),  			'inverse_relationship' => TRUE, diff --git a/engine/classes/ElggUser.php b/engine/classes/ElggUser.php index a1c7147a5..d7bb89265 100644 --- a/engine/classes/ElggUser.php +++ b/engine/classes/ElggUser.php @@ -6,6 +6,15 @@   *   * @package    Elgg.Core   * @subpackage DataModel.User + *  + * @property string $name     The display name that the user will be known by in the network + * @property string $username The short, reference name for the user in the network + * @property string $email    The email address to which Elgg will send email notifications + * @property string $language The language preference of the user (ISO 639-1 formatted) + * @property string $banned   'yes' if the user is banned from the network, 'no' otherwise + * @property string $admin    'yes' if the user is an administrator of the network, 'no' otherwise + * @property string $password The hashed password of the user + * @property string $salt     The salt used to secure the password before hashing   */  class ElggUser extends ElggEntity  	implements Friendable { @@ -38,7 +47,7 @@ class ElggUser extends ElggEntity  	 * Construct a new user entity, optionally from a given id value.  	 *  	 * @param mixed $guid If an int, load that GUID. -	 * 	If a db row then will attempt to load the rest of the data. +	 * 	If an entity table db row then will load the rest of the data.  	 *  	 * @throws Exception if there was a problem creating the user.  	 */ @@ -49,15 +58,15 @@ class ElggUser extends ElggEntity  		$this->initialise_attributes(false);  		if (!empty($guid)) { -			// Is $guid is a DB row - either a entity row, or a user table row. +			// Is $guid is a DB entity row  			if ($guid instanceof stdClass) {  				// Load the rest -				if (!$this->load($guid->guid)) { +				if (!$this->load($guid)) {  					$msg = elgg_echo('IOException:FailedToLoadGUID', array(get_class(), $guid->guid));  					throw new IOException($msg);  				} -				// See if this is a username +			// See if this is a username  			} else if (is_string($guid)) {  				$user = get_user_by_username($guid);  				if ($user) { @@ -66,7 +75,7 @@ class ElggUser extends ElggEntity  					}  				} -				// Is $guid is an ElggUser? Use a copy constructor +			// Is $guid is an ElggUser? Use a copy constructor  			} else if ($guid instanceof ElggUser) {  				elgg_deprecated_notice('This type of usage of the ElggUser constructor was deprecated. Please use the clone method.', 1.7); @@ -74,11 +83,11 @@ class ElggUser extends ElggEntity  					$this->attributes[$key] = $value;  				} -				// Is this is an ElggEntity but not an ElggUser = ERROR! +			// Is this is an ElggEntity but not an ElggUser = ERROR!  			} else if ($guid instanceof ElggEntity) {  				throw new InvalidParameterException(elgg_echo('InvalidParameterException:NonElggUser')); -				// We assume if we have got this far, $guid is an int +			// Is it a GUID  			} else if (is_numeric($guid)) {  				if (!$this->load($guid)) {  					throw new IOException(elgg_echo('IOException:FailedToLoadGUID', array(get_class(), $guid))); @@ -90,13 +99,11 @@ class ElggUser extends ElggEntity  	}  	/** -	 * Override the load function. -	 * This function will ensure that all data is loaded (were possible), so -	 * if only part of the ElggUser is loaded, it'll load the rest. +	 * Load the ElggUser data from the database  	 * -	 * @param int $guid ElggUser GUID +	 * @param mixed $guid ElggUser GUID or stdClass database row from entity table  	 * -	 * @return true|false +	 * @return bool  	 */  	protected function load($guid) {  		// Test to see if we have the generic stuff @@ -104,6 +111,11 @@ class ElggUser extends ElggEntity  			return false;  		} +		// Only work with GUID from here +		if ($guid instanceof stdClass) { +			$guid = $guid->guid; +		} +  		// Check the type  		if ($this->attributes['type'] != 'user') {  			$msg = elgg_echo('InvalidClassException:NotValidElggStar', array($guid, get_class())); @@ -132,7 +144,7 @@ class ElggUser extends ElggEntity  	/**  	 * Saves this user to the database.  	 * -	 * @return true|false +	 * @return bool  	 */  	public function save() {  		// Save generic stuff @@ -252,7 +264,7 @@ class ElggUser extends ElggEntity  	 * @param int    $limit   The number of results to return  	 * @param int    $offset  Any indexing offset  	 * -	 * @return bool +	 * @return array  	 */  	function getSites($subtype = "", $limit = 10, $offset = 0) {  		return get_user_sites($this->getGUID(), $subtype, $limit, $offset); @@ -263,7 +275,7 @@ class ElggUser extends ElggEntity  	 *  	 * @param int $site_guid The guid of the site to add it to  	 * -	 * @return true|false +	 * @return bool  	 */  	function addToSite($site_guid) {  		return add_site_user($site_guid, $this->getGUID()); @@ -274,7 +286,7 @@ class ElggUser extends ElggEntity  	 *  	 * @param int $site_guid The guid of the site to remove it from  	 * -	 * @return true|false +	 * @return bool  	 */  	function removeFromSite($site_guid) {  		return remove_site_user($site_guid, $this->getGUID()); @@ -285,7 +297,7 @@ class ElggUser extends ElggEntity  	 *  	 * @param int $friend_guid The GUID of the user to add  	 * -	 * @return true|false Depending on success +	 * @return bool  	 */  	function addFriend($friend_guid) {  		return user_add_friend($this->getGUID(), $friend_guid); @@ -296,7 +308,7 @@ class ElggUser extends ElggEntity  	 *  	 * @param int $friend_guid The GUID of the user to remove  	 * -	 * @return true|false Depending on success +	 * @return bool  	 */  	function removeFriend($friend_guid) {  		return user_remove_friend($this->getGUID(), $friend_guid); @@ -305,8 +317,7 @@ class ElggUser extends ElggEntity  	/**  	 * Determines whether or not this user is a friend of the currently logged in user  	 * -	 * -	 * @return true|false +	 * @return bool  	 */  	function isFriend() {  		return $this->isFriendOf(elgg_get_logged_in_user_guid()); @@ -317,7 +328,7 @@ class ElggUser extends ElggEntity  	 *  	 * @param int $user_guid The GUID of the user to check against  	 * -	 * @return true|false +	 * @return bool  	 */  	function isFriendsWith($user_guid) {  		return user_is_friend($this->getGUID(), $user_guid); @@ -328,7 +339,7 @@ class ElggUser extends ElggEntity  	 *  	 * @param int $user_guid The GUID of the user to check against  	 * -	 * @return true|false +	 * @return bool  	 */  	function isFriendOf($user_guid) {  		return user_is_friend($user_guid, $this->getGUID()); @@ -376,7 +387,6 @@ class ElggUser extends ElggEntity  			'relationship' => 'friend',  			'relationship_guid' => $this->guid,  			'limit' => $limit, -			'offset' => get_input('offset', 0),  			'full_view' => false,  		); @@ -450,7 +460,14 @@ class ElggUser extends ElggEntity  	 * @return array|false  	 */  	public function getObjects($subtype = "", $limit = 10, $offset = 0) { -		return get_user_objects($this->getGUID(), $subtype, $limit, $offset); +		$params = array( +			'type' => 'object', +			'subtype' => $subtype, +			'owner_guid' => $this->getGUID(), +			'limit' => $limit, +			'offset' => $offset +		); +		return elgg_get_entities($params);  	}  	/** diff --git a/engine/classes/ElggWidget.php b/engine/classes/ElggWidget.php index 0eb83913b..99708f66a 100644 --- a/engine/classes/ElggWidget.php +++ b/engine/classes/ElggWidget.php @@ -115,6 +115,8 @@ class ElggWidget extends ElggObject {  		$options = array(  			'type' => 'object',  			'subtype' => 'widget', +			'container_guid' => $this->container_guid, +			'limit' => false,  			'private_setting_name_value_pairs' => array(  				array('name' => 'context', 'value' => $this->getContext()),  				array('name' => 'column', 'value' => $column) @@ -129,21 +131,60 @@ class ElggWidget extends ElggObject {  		usort($widgets, create_function('$a,$b','return (int)$a->order > (int)$b->order;')); +		// remove widgets from inactive plugins +		$widget_types = elgg_get_widget_types($this->context); +		$inactive_widgets = array(); +		foreach ($widgets as $index => $widget) { +			if (!array_key_exists($widget->handler, $widget_types)) { +				$inactive_widgets[] = $widget; +				unset($widgets[$index]); +			} +		} +  		if ($rank == 0) {  			// top of the column -			$this->order = $widgets[0]->order - 10; -		} elseif ($rank == count($widgets)) { -			// bottom of the column +			$this->order = reset($widgets)->order - 10; +		} elseif ($rank == (count($widgets) - 1)) { +			// bottom of the column of active widgets  			$this->order = end($widgets)->order + 10;  		} else { -			// reorder widgets that are below -			$this->order = $widgets[$rank]->order; -			for ($index = $rank; $index < count($widgets); $index++) { -				if ($widgets[$index]->guid != $this->guid) { -					$widgets[$index]-> order += 10; +			// reorder widgets + +			// remove the widget that's being moved from the array +			foreach ($widgets as $index => $widget) { +				if ($widget->guid == $this->guid) { +					unset($widgets[$index]); +				} +			} + +			// split the array in two and recombine with the moved widget in middle +			$before = array_slice($widgets, 0, $rank); +			array_push($before, $this); +			$after = array_slice($widgets, $rank); +			$widgets = array_merge($before, $after); +			ksort($widgets); +			$order = 0; +			foreach ($widgets as $widget) { +				$widget->order = $order; +				$order += 10; +			} +		} + +		// put inactive widgets at the bottom +		if ($inactive_widgets) { +			$bottom = 0; +			foreach ($widgets as $widget) { +				if ($widget->order > $bottom) { +					$bottom = $widget->order;  				}  			} +			$bottom += 10; +			foreach ($inactive_widgets as $widget) { +				$widget->order = $bottom; +				$bottom += 10; +			}  		} +  		$this->column = $column;  	} diff --git a/engine/classes/ODDDocument.php b/engine/classes/ODDDocument.php index 4d185aba5..540c35a3b 100644 --- a/engine/classes/ODDDocument.php +++ b/engine/classes/ODDDocument.php @@ -70,8 +70,8 @@ class ODDDocument implements Iterator {  	public function addElement(ODD $element) {  		if (!is_array($this->elements)) {  			$this->elements = array(); -			$this->elements[] = $element;  		} +		$this->elements[] = $element;  	}  	/** diff --git a/engine/classes/ODDEntity.php b/engine/classes/ODDEntity.php index ab3a49168..e9bb5da6a 100644 --- a/engine/classes/ODDEntity.php +++ b/engine/classes/ODDEntity.php @@ -32,75 +32,3 @@ class ODDEntity extends ODD {  		return "entity";  	}  } - -/** - * ODD Metadata class. - * - * @package    Elgg.Core - * @subpackage ODD - */ -class ODDMetaData extends ODD { - -	/** -	 * New ODD metadata -	 * -	 * @param unknown_type $uuid        Unique ID -	 * @param unknown_type $entity_uuid Another unique ID -	 * @param unknown_type $name        Name -	 * @param unknown_type $value       Value -	 * @param unknown_type $type        Type -	 * @param unknown_type $owner_uuid  Owner ID -	 */ -	function __construct($uuid, $entity_uuid, $name, $value, $type = "", $owner_uuid = "") { -		parent::__construct(); - -		$this->setAttribute('uuid', $uuid); -		$this->setAttribute('entity_uuid', $entity_uuid); -		$this->setAttribute('name', $name); -		$this->setAttribute('type', $type); -		$this->setAttribute('owner_uuid', $owner_uuid); -		$this->setBody($value); -	} - -	/** -	 * Returns 'metadata' -	 * -	 * @return 'metadata' -	 */ -	protected function getTagName() { -		return "metadata"; -	} -} - -/** - * ODD Relationship class. - * - * @package    Elgg - * @subpackage Core - */ -class ODDRelationship extends ODD { - -	/** -	 * New ODD Relationship -	 * -	 * @param unknown_type $uuid1 First UUID -	 * @param unknown_type $type  Type of telationship -	 * @param unknown_type $uuid2 Second UUId -	 */ -	function __construct($uuid1, $type, $uuid2) { -		parent::__construct(); - -		$this->setAttribute('uuid1', $uuid1); -		$this->setAttribute('type', $type); -		$this->setAttribute('uuid2', $uuid2); -	} - -	/** -	 * Returns 'relationship' -	 * -	 * @return 'relationship' -	 */ -	protected function getTagName() { -		return "relationship"; -	} -} diff --git a/engine/classes/ODDMetaData.php b/engine/classes/ODDMetaData.php new file mode 100644 index 000000000..58862e0fb --- /dev/null +++ b/engine/classes/ODDMetaData.php @@ -0,0 +1,39 @@ +<?php +/** + * ODD Metadata class. + * + * @package    Elgg.Core + * @subpackage ODD + */ +class ODDMetaData extends ODD { + +	/** +	 * New ODD metadata +	 * +	 * @param unknown_type $uuid        Unique ID +	 * @param unknown_type $entity_uuid Another unique ID +	 * @param unknown_type $name        Name +	 * @param unknown_type $value       Value +	 * @param unknown_type $type        Type +	 * @param unknown_type $owner_uuid  Owner ID +	 */ +	function __construct($uuid, $entity_uuid, $name, $value, $type = "", $owner_uuid = "") { +		parent::__construct(); + +		$this->setAttribute('uuid', $uuid); +		$this->setAttribute('entity_uuid', $entity_uuid); +		$this->setAttribute('name', $name); +		$this->setAttribute('type', $type); +		$this->setAttribute('owner_uuid', $owner_uuid); +		$this->setBody($value); +	} + +	/** +	 * Returns 'metadata' +	 * +	 * @return 'metadata' +	 */ +	protected function getTagName() { +		return "metadata"; +	} +} diff --git a/engine/classes/ODDRelationship.php b/engine/classes/ODDRelationship.php new file mode 100644 index 000000000..2906b1c73 --- /dev/null +++ b/engine/classes/ODDRelationship.php @@ -0,0 +1,33 @@ +<?php +/** + * ODD Relationship class. + * + * @package    Elgg + * @subpackage Core + */ +class ODDRelationship extends ODD { + +	/** +	 * New ODD Relationship +	 * +	 * @param unknown_type $uuid1 First UUID +	 * @param unknown_type $type  Type of telationship +	 * @param unknown_type $uuid2 Second UUId +	 */ +	function __construct($uuid1, $type, $uuid2) { +		parent::__construct(); + +		$this->setAttribute('uuid1', $uuid1); +		$this->setAttribute('type', $type); +		$this->setAttribute('uuid2', $uuid2); +	} + +	/** +	 * Returns 'relationship' +	 * +	 * @return 'relationship' +	 */ +	protected function getTagName() { +		return "relationship"; +	} +} diff --git a/engine/classes/SuccessResult.php b/engine/classes/SuccessResult.php index c8578a2cf..ab5468ad8 100644 --- a/engine/classes/SuccessResult.php +++ b/engine/classes/SuccessResult.php @@ -15,7 +15,7 @@ class SuccessResult extends GenericResult {  	 *  	 * @param string $result The result  	 */ -	public function SuccessResult($result) { +	public function __construct($result) {  		$this->setResult($result);  		$this->setStatusCode(SuccessResult::$RESULT_SUCCESS);  	} diff --git a/engine/classes/XMLRPCCall.php b/engine/classes/XMLRPCCall.php index 8eeba0c29..fd28f1e3e 100644 --- a/engine/classes/XMLRPCCall.php +++ b/engine/classes/XMLRPCCall.php @@ -18,7 +18,7 @@ class XMLRPCCall {  	 * @param string $xml XML  	 */  	function __construct($xml) { -		$this->_parse($xml); +		$this->parse($xml);  	}  	/** @@ -45,7 +45,7 @@ class XMLRPCCall {  	 *  	 * @return void  	 */ -	private function _parse($xml) { +	private function parse($xml) {  		$xml = xml_to_object($xml);  		// sanity check diff --git a/engine/handlers/cache_handler.php b/engine/handlers/cache_handler.php index 94a0e64e9..b332ec379 100644 --- a/engine/handlers/cache_handler.php +++ b/engine/handlers/cache_handler.php @@ -60,26 +60,31 @@ preg_match($regex, $request, $matches);  $type = $matches[1];  $viewtype = $matches[2];  $view = $matches[3]; +$ts = $matches[4]; + +// If is the same ETag, content didn't changed. +$etag = $ts; +if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) { +	header("HTTP/1.1 304 Not Modified"); +	exit; +}  switch ($type) {  	case 'css':  		header("Content-type: text/css", true); -		header('Expires: ' . date('r', strtotime("+6 months")), true); -		header("Pragma: public", true); -		header("Cache-Control: public", true); -  		$view = "css/$view";  		break;  	case 'js':  		header('Content-type: text/javascript', true); -		header('Expires: ' . date('r', strtotime("+6 months")), true); -		header("Pragma: public", true); -		header("Cache-Control: public", true); -  		$view = "js/$view";  		break;  } +header('Expires: ' . date('r', strtotime("+6 months")), true); +header("Pragma: public", true); +header("Cache-Control: public", true); +header("ETag: $etag"); +  $filename = $dataroot . 'views_simplecache/' . md5($viewtype . $view);  if (file_exists($filename)) { diff --git a/engine/handlers/export_handler.php b/engine/handlers/export_handler.php index b91a037e8..aa5214c23 100644 --- a/engine/handlers/export_handler.php +++ b/engine/handlers/export_handler.php @@ -72,8 +72,10 @@ if (($guid != "") && ($type == "") && ($id_or_name == "")) {  			$r = get_relationship($id_or_name);  			break;  		case 'volatile' : -			$m = elgg_trigger_plugin_hook('volatile', 'metadata', -				array('guid' => $guid, 'varname' => $id_or_name)); +			$m = elgg_trigger_plugin_hook('volatile', 'metadata', array( +				'guid' => $guid, +				'varname' => $id_or_name, +			));  			break;  		default : diff --git a/engine/lib/access.php b/engine/lib/access.php index 08b9283cd..6be252c6a 100644 --- a/engine/lib/access.php +++ b/engine/lib/access.php @@ -671,8 +671,10 @@ function add_user_to_access_collection($user_guid, $collection_id) {  		return false;  	} +	// if someone tries to insert the same data twice, we do a no-op on duplicate key  	$q = "INSERT INTO {$CONFIG->dbprefix}access_collection_membership -			SET access_collection_id = {$collection_id}, user_guid = {$user_guid}"; +			SET access_collection_id = $collection_id, user_guid = $user_guid +			ON DUPLICATE KEY UPDATE user_guid = user_guid";  	$result = insert_data($q);  	return $result !== false; @@ -838,7 +840,7 @@ function elgg_list_entities_from_access_id(array $options = array()) {   *   * @param int $entity_access_id The entity's access id   * - * @return string 'Public', 'Private', etc. or false if error. + * @return string 'Public', 'Private', etc.   * @since 1.7.0   * @todo I think this probably wants get_access_array() instead of get_write_access_array(),   * but those two functions return different types of arrays. @@ -849,15 +851,12 @@ function get_readable_access_level($entity_access_id) {  	//get the access level for object in readable string  	$options = get_write_access_array(); -	//@todo Really?  Use array_key_exists() -	foreach ($options as $key => $option) { -		if ($key == $access) { -			$entity_acl = htmlentities($option, ENT_QUOTES, 'UTF-8'); -			return $entity_acl; -			break; -		} +	if (array_key_exists($access, $options)) { +		return $options[$access];  	} -	return false; + +	// return 'Limited' if the user does not have access to the access collection +	return elgg_echo('access:limited:label');  }  /** @@ -987,9 +986,9 @@ function elgg_override_permissions($hook, $type, $value, $params) {  	}  	// don't do this so ignore access still works with no one logged in -//	if (!$user instanceof ElggUser) { -//		return false; -//	} +	//if (!$user instanceof ElggUser) { +	//	return false; +	//}  	// check for admin  	if ($user_guid && elgg_is_admin_user($user_guid)) { diff --git a/engine/lib/actions.php b/engine/lib/actions.php index f415842ab..c6613e6d6 100644 --- a/engine/lib/actions.php +++ b/engine/lib/actions.php @@ -459,8 +459,7 @@ function ajax_forward_hook($hook, $type, $reason, $params) {  		// however some browsers will not accept the JSON MIME type.  		if (stripos($_SERVER['HTTP_ACCEPT'], 'application/json') === FALSE) {  			header("Content-type: text/plain"); -		} -		else { +		} else {  			header("Content-type: application/json");  		} diff --git a/engine/lib/admin.php b/engine/lib/admin.php index a191d740b..928101fc5 100644 --- a/engine/lib/admin.php +++ b/engine/lib/admin.php @@ -79,6 +79,10 @@ function elgg_add_admin_notice($id, $message) {  		if (elgg_admin_notice_exists($id)) {  			return false;  		} + +		// need to handle when no one is logged in +		$old_ia = elgg_set_ignore_access(true); +  		$admin_notice = new ElggObject();  		$admin_notice->subtype = 'admin_notice';  		// admins can see ACCESS_PRIVATE but no one else can. @@ -86,13 +90,16 @@ function elgg_add_admin_notice($id, $message) {  		$admin_notice->admin_notice_id = $id;  		$admin_notice->description = $message; -		return $admin_notice->save(); +		$result = $admin_notice->save(); + +		elgg_set_ignore_access($old_ia); + +		return (bool)$result;  	} -	return FALSE; +	return false;  } -  /**   * Remove an admin notice by ID.   * @@ -172,10 +179,10 @@ function elgg_admin_notice_exists($id) {   *   * This function handles registering the parent if it has not been registered.   * - * @param string $section    The menu section to add to - * @param string $menu_id    The unique ID of section - * @param string $parent_id  If a child section, the parent section id - * @param int    $priority   The menu item priority + * @param string $section   The menu section to add to + * @param string $menu_id   The unique ID of section + * @param string $parent_id If a child section, the parent section id + * @param int    $priority  The menu item priority   *   * @return bool   * @since 1.8.0 @@ -255,6 +262,7 @@ function admin_init() {  	// statistics  	elgg_register_admin_menu_item('administer', 'statistics', null, 20);  	elgg_register_admin_menu_item('administer', 'overview', 'statistics'); +	elgg_register_admin_menu_item('administer', 'server', 'statistics');  	// users  	elgg_register_admin_menu_item('administer', 'users', null, 20); diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php index bfd40d1e8..f32dee0f0 100644 --- a/engine/lib/annotations.php +++ b/engine/lib/annotations.php @@ -163,13 +163,9 @@ function update_annotation($annotation_id, $name, $value, $value_type, $owner_gu  		where id=$annotation_id and $access");  	if ($result !== false) { +		// @todo add plugin hook that sends old and new annotation information before db access  		$obj = elgg_get_annotation_from_id($annotation_id); -		if (elgg_trigger_event('update', 'annotation', $obj)) { -			return true; -		} else { -			// @todo add plugin hook that sends old and new annotation information before db access -			elgg_delete_annotation_by_id($annotation_id); -		} +		elgg_trigger_event('update', 'annotation', $obj);  	}  	return $result; @@ -183,21 +179,23 @@ function update_annotation($annotation_id, $name, $value, $value_type, $owner_gu   *   * @param array $options Array in format:   * - * 	annotation_names => NULL|ARR Annotation names - * - * 	annotation_values => NULL|ARR Annotation values - * - * 	annotation_ids => NULL|ARR annotation ids - * - * 	annotation_case_sensitive => BOOL Overall Case sensitive - * - *  annotation_owner_guids => NULL|ARR guids for annotation owners + * annotation_names              => NULL|ARR Annotation names + * annotation_values             => NULL|ARR Annotation values + * annotation_ids                => NULL|ARR annotation ids + * annotation_case_sensitive     => BOOL Overall Case sensitive + * annotation_owner_guids        => NULL|ARR guids for annotation owners + * annotation_created_time_lower => INT Lower limit for created time. + * annotation_created_time_upper => INT Upper limit for created time. + * annotation_calculation        => STR Perform the MySQL function on the annotation values returned. + *                                   Do not confuse this "annotation_calculation" option with the + *                                   "calculation" option to elgg_get_entities_from_annotation_calculation(). + *                                   The "annotation_calculation" option causes this function to + *                                   return the result of performing a mathematical calculation on + *                                   all annotations that match the query instead of ElggAnnotation + *                                   objects. + *                                   See the docs for elgg_get_entities_from_annotation_calculation() + *                                   for the proper use of the "calculation" option.   * - *  annotation_created_time_lower => INT Lower limit for created time. - * - *  annotation_created_time_upper => INT Upper limit for created time. - * - *  annotation_calculation => STR Perform the MySQL function on the annotation values returned.   *   * @return mixed   * @since 1.8.0 @@ -211,9 +209,11 @@ function elgg_get_annotations(array $options = array()) {   * Deletes annotations based on $options.   *   * @warning Unlike elgg_get_annotations() this will not accept an empty options array! + *          This requires at least one constraint: annotation_owner_guid(s), + *          annotation_name(s), annotation_value(s), or guid(s) must be set.   *   * @param array $options An options array. {@See elgg_get_annotations()} - * @return mixed + * @return mixed Null if the metadata name is invalid. Bool on success or fail.   * @since 1.8.0   */  function elgg_delete_annotations(array $options) { @@ -239,7 +239,7 @@ function elgg_disable_annotations(array $options) {  		return false;  	} -	$options['metastrings_type'] = 'annotations'; +	$options['metastring_type'] = 'annotations';  	return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback');  } @@ -388,8 +388,14 @@ function elgg_list_entities_from_annotations($options = array()) {   * Get entities ordered by a mathematical calculation on annotation values   *   * @param array $options An options array: - * 	'annotation_calculation' => The calculation to use. Must be a valid MySQL function. + * 	'calculation'            => The calculation to use. Must be a valid MySQL function.   *                              Defaults to sum.  Result selected as 'annotation_calculation'. + *                              Don't confuse this "calculation" option with the + *                              "annotation_calculation" option to elgg_get_annotations(). + *                              This "calculation" option is applied to each entity's set of + *                              annotations and is selected as annotation_calculation for that row. + *                              See the docs for elgg_get_annotations() for proper use of the + *                              "annotation_calculation" option.   *	'order_by'               => The order for the sorting. Defaults to 'annotation_calculation desc'.   *	'annotation_names'       => The names of annotations on the entity.   *	'annotation_values'	     => The values of annotations on the entity. @@ -545,8 +551,8 @@ function elgg_comment_url_handler(ElggAnnotation $comment) {  /**   * Register an annotation url handler.   * - * @param string $function_name The function.   * @param string $extender_name The name, default 'all'. + * @param string $function_name The function.   *   * @return string   */ diff --git a/engine/lib/cache.php b/engine/lib/cache.php index a6ebe2a30..c117b9ec9 100644 --- a/engine/lib/cache.php +++ b/engine/lib/cache.php @@ -10,15 +10,14 @@  /* Filepath Cache */  /** - * Returns an ElggCache object suitable for caching view - * file load paths to disk under $CONFIG->dataroot. + * Returns an ElggCache object suitable for caching system information   *   * @todo Can this be done in a cleaner way?   * @todo Swap to memcache etc?   * - * @return ElggFileCache A cache object suitable for caching file load paths. + * @return ElggFileCache   */ -function elgg_get_filepath_cache() { +function elgg_get_system_cache() {  	global $CONFIG;  	/** @@ -27,35 +26,34 @@ function elgg_get_filepath_cache() {  	static $FILE_PATH_CACHE;  	if (!$FILE_PATH_CACHE) { -		$FILE_PATH_CACHE = new ElggFileCache($CONFIG->dataroot); +		$FILE_PATH_CACHE = new ElggFileCache($CONFIG->dataroot . 'system_cache/');  	}  	return $FILE_PATH_CACHE;  }  /** - * Function which resets the file path cache. + * Reset the system cache by deleting the caches   * + * @return void   */ -function elgg_filepath_cache_reset() { -	$cache = elgg_get_filepath_cache(); -	$view_types_result = $cache->delete('view_types'); -	$views_result = $cache->delete('views'); -	return $view_types_result && $views_result; +function elgg_reset_system_cache() { +	$cache = elgg_get_system_cache(); +	$cache->clear();  }  /** - * Saves a filepath cache. + * Saves a system cache.   * - * @param string $type - * @param string $data + * @param string $type The type or identifier of the cache + * @param string $data The data to be saved   * @return bool   */ -function elgg_filepath_cache_save($type, $data) { +function elgg_save_system_cache($type, $data) {  	global $CONFIG; -	if ($CONFIG->viewpath_cache_enabled) { -		$cache = elgg_get_filepath_cache(); +	if ($CONFIG->system_cache_enabled) { +		$cache = elgg_get_system_cache();  		return $cache->save($type, $data);  	} @@ -63,16 +61,16 @@ function elgg_filepath_cache_save($type, $data) {  }  /** - * Retrieve the contents of the filepath cache. + * Retrieve the contents of a system cache.   *   * @param string $type The type of cache to load   * @return string   */ -function elgg_filepath_cache_load($type) { +function elgg_load_system_cache($type) {  	global $CONFIG; -	if ($CONFIG->viewpath_cache_enabled) { -		$cache = elgg_get_filepath_cache(); +	if ($CONFIG->system_cache_enabled) { +		$cache = elgg_get_system_cache();  		$cached_data = $cache->load($type);  		if ($cached_data) { @@ -84,35 +82,74 @@ function elgg_filepath_cache_load($type) {  }  /** - * Enables the views file paths disk cache. + * Enables the system disk cache.   * - * Uses the 'viewpath_cache_enabled' datalist with a boolean value. - * Resets the views paths cache. + * Uses the 'system_cache_enabled' datalist with a boolean value. + * Resets the system cache.   *   * @return void   */ -function elgg_enable_filepath_cache() { +function elgg_enable_system_cache() {  	global $CONFIG; -	datalist_set('viewpath_cache_enabled', 1); -	$CONFIG->viewpath_cache_enabled = 1; -	elgg_filepath_cache_reset(); +	datalist_set('system_cache_enabled', 1); +	$CONFIG->system_cache_enabled = 1; +	elgg_reset_system_cache();  }  /** - * Disables the views file paths disk cache. + * Disables the system disk cache.   * - * Uses the 'viewpath_cache_enabled' datalist with a boolean value. - * Resets the views paths cache. + * Uses the 'system_cache_enabled' datalist with a boolean value. + * Resets the system cache.   *   * @return void   */ -function elgg_disable_filepath_cache() { +function elgg_disable_system_cache() {  	global $CONFIG; -	datalist_set('viewpath_cache_enabled', 0); -	$CONFIG->viewpath_cache_enabled = 0; -	elgg_filepath_cache_reset(); +	datalist_set('system_cache_enabled', 0); +	$CONFIG->system_cache_enabled = 0; +	elgg_reset_system_cache(); +} + +/** @todo deprecate in Elgg 1.9 **/ + +/** + * @access private + */ +function elgg_get_filepath_cache() { +	return elgg_get_system_cache(); +} +/** + * @access private + */ +function elgg_filepath_cache_reset() { +	return elgg_reset_system_cache(); +} +/** + * @access private + */ +function elgg_filepath_cache_save($type, $data) { +	return elgg_save_system_cache($type, $data); +} +/** + * @access private + */ +function elgg_filepath_cache_load($type) { +	return elgg_load_system_cache($type); +} +/** + * @access private + */ +function elgg_enable_filepath_cache() { +	return elgg_enable_system_cache(); +} +/** + * @access private + */ +function elgg_disable_filepath_cache() { +	return elgg_disable_system_cache();  }  /* Simplecache */ @@ -332,7 +369,7 @@ function elgg_invalidate_simplecache() {  	$return = true;  	while (false !== ($file = readdir($handle))) {  		if ($file != "." && $file != "..") { -			$return = $return && unlink($CONFIG->dataroot . 'views_simplecache/' . $file); +			$return &= unlink($CONFIG->dataroot . 'views_simplecache/' . $file);  		}  	}  	closedir($handle); @@ -345,9 +382,70 @@ function elgg_invalidate_simplecache() {  	}  	foreach ($viewtypes as $viewtype) { -		$return = $return && datalist_set("simplecache_lastupdate_$viewtype", 0); -		$return = $return && datalist_set("simplecache_lastcached_$viewtype", 0); +		$return &= datalist_set("simplecache_lastupdate_$viewtype", 0); +		$return &= datalist_set("simplecache_lastcached_$viewtype", 0);  	}  	return $return;  } + +/** + * @see elgg_reset_system_cache() + * @access private + */ +function _elgg_load_cache() { +	global $CONFIG; + +	$CONFIG->system_cache_loaded = false; + +	$CONFIG->views = new stdClass(); +	$data = elgg_load_system_cache('view_locations'); +	if (!is_string($data)) { +		return; +	} +	$CONFIG->views->locations = unserialize($data); +	 +	$data = elgg_load_system_cache('view_types'); +	if (!is_string($data)) { +		return; +	} +	$CONFIG->view_types = unserialize($data); + +	$CONFIG->system_cache_loaded = true; +} + +/** + * @access private + */ +function _elgg_cache_init() { +	global $CONFIG; + +	$viewtype = elgg_get_viewtype(); + +	// Regenerate the simple cache if expired. +	// Don't do it on upgrade because upgrade does it itself. +	// @todo - move into function and perhaps run off init system event +	if (!defined('UPGRADING')) { +		$lastupdate = datalist_get("simplecache_lastupdate_$viewtype"); +		$lastcached = datalist_get("simplecache_lastcached_$viewtype"); +		if ($lastupdate == 0 || $lastcached < $lastupdate) { +			elgg_regenerate_simplecache($viewtype); +			$lastcached = datalist_get("simplecache_lastcached_$viewtype"); +		} +		$CONFIG->lastcache = $lastcached; +	} + +	// cache system data if enabled and not loaded +	if ($CONFIG->system_cache_enabled && !$CONFIG->system_cache_loaded) { +		elgg_save_system_cache('view_locations', serialize($CONFIG->views->locations)); +		elgg_save_system_cache('view_types', serialize($CONFIG->view_types)); +	} + +	if ($CONFIG->system_cache_enabled && !$CONFIG->i18n_loaded_from_cache) { +		foreach ($CONFIG->translations as $lang => $map) { +			elgg_save_system_cache("$lang.php", serialize($map)); +		} +	} +} + +elgg_register_event_handler('ready', 'system', '_elgg_cache_init'); diff --git a/engine/lib/configuration.php b/engine/lib/configuration.php index 615063f3d..9bf1529d6 100644 --- a/engine/lib/configuration.php +++ b/engine/lib/configuration.php @@ -3,8 +3,9 @@   * Elgg configuration procedural code.   *   * Includes functions for manipulating the configuration values stored in the database - * Plugin authors should use the {@link get_config()}, {@link set_config()}, - * and {@unset_config()} functions to access or update config values. + * Plugin authors should use the {@link elgg_get_config()}, {@link elgg_set_config()}, + * {@link elgg_save_config()}, and {@unset_config()} functions to access or update + * config values.   *   * Elgg's configuration is split among 2 tables and 1 file:   * - dbprefix_config @@ -302,7 +303,7 @@ function datalist_set($name, $value) {  		. " set name = '{$sanitised_name}', value = '{$sanitised_value}'"  		. " ON DUPLICATE KEY UPDATE value='{$sanitised_value}'"); -	if ($success) { +	if ($success !== FALSE) {  		$DATALIST_CACHE[$name] = $value;  		return true;  	} else { @@ -517,10 +518,10 @@ function get_all_config($site_guid = 0) {  	$site_guid = (int) $site_guid;  	if ($site_guid == 0) { -		$site_guid = (int) $CONFIG->site_id; +		$site_guid = (int) $CONFIG->site_guid;  	} -	if ($result = get_data("SELECT * from {$CONFIG->dbprefix}config where site_guid = {$site_guid}")) { +	if ($result = get_data("SELECT * FROM {$CONFIG->dbprefix}config WHERE site_guid = $site_guid")) {  		foreach ($result as $r) {  			$name = $r->name;  			$value = $r->value; @@ -533,37 +534,49 @@ function get_all_config($site_guid = 0) {  }  /** - * Sets defaults for or attempts to autodetect some common config values and - * loads them into $CONFIG. + * Loads configuration related to this site   * - * @return true + * This loads from the config database table and the site entity   * @access private   */ -function set_default_config() { +function _elgg_load_site_config() {  	global $CONFIG; -	$install_root = str_replace("\\", "/", dirname(dirname(dirname(__FILE__)))); - -	// @todo this seldom works right. -	$pathpart = str_replace("//", "/", str_replace($_SERVER['DOCUMENT_ROOT'], "", $install_root)); -	if (substr($pathpart, 0, 1) != "/") { -		$pathpart = "/" . $pathpart; +	$CONFIG->site_guid = (int) datalist_get('default_site'); +	$CONFIG->site_id = $CONFIG->site_guid; +	$CONFIG->site = get_entity($CONFIG->site_guid); +	if (!$CONFIG->site) { +		throw new InstallationException(elgg_echo('InstallationException:SiteNotInstalled'));  	} -	$www_root = "http://" . $_SERVER['HTTP_HOST'] . $pathpart; +	$CONFIG->wwwroot = $CONFIG->site->url; +	$CONFIG->sitename = $CONFIG->site->name; +	$CONFIG->sitedescription = $CONFIG->site->description; +	$CONFIG->siteemail = $CONFIG->site->email; +	$CONFIG->url = $CONFIG->wwwroot; + +	get_all_config(); +} + +/** + * Loads configuration related to Elgg as an application + * + * This loads from the datalists database table + * @access private + */ +function _elgg_load_application_config() { +	global $CONFIG; + +	$install_root = str_replace("\\", "/", dirname(dirname(dirname(__FILE__))));  	$defaults = array(  		'path'			=>	"$install_root/",  		'view_path'		=>	"$install_root/views/",  		'plugins_path'	=>	"$install_root/mod/", -		'wwwroot'		=> 	$www_root, -		'url'			=>	$www_root, -		'site_name'		=>	'New Elgg site',  		'language'		=>	'en', -		// compatibility with old names for ppl not using get_config() +		// compatibility with old names for plugins not using elgg_get_config()  		'viewpath'		=>	"$install_root/views/",  		'pluginspath'	=>	"$install_root/mod/", -		'sitename'		=>	'New Elgg site',  	);  	foreach ($defaults as $name => $value) { @@ -572,25 +585,6 @@ function set_default_config() {  		}  	} -	$CONFIG->context = array(); - -	return true; -} - -/** - * Loads values into $CONFIG. - * - * If Elgg is installed, this function pulls all rows from dbprefix_config - * and cherry picks some values from dbprefix_datalists.  This also extracts - * some commonly used values from the default site object. - * - * @elgg_event boot system - * @return true|null - * @access private - */ -function configuration_boot() { -	global $CONFIG; -  	$path = datalist_get('path');  	if (!empty($path)) {  		$CONFIG->path = $path; @@ -605,22 +599,23 @@ function configuration_boot() {  	} else {  		$CONFIG->simplecache_enabled = 1;  	} -	$viewpath_cache_enabled = datalist_get('viewpath_cache_enabled'); -	if ($viewpath_cache_enabled !== false) { -		$CONFIG->viewpath_cache_enabled = $viewpath_cache_enabled; +	$system_cache_enabled = datalist_get('system_cache_enabled'); +	if ($system_cache_enabled !== false) { +		$CONFIG->system_cache_enabled = $system_cache_enabled;  	} else { -		$CONFIG->viewpath_cache_enabled = 1; +		$CONFIG->system_cache_enabled = 1;  	} -	if (isset($CONFIG->site) && ($CONFIG->site instanceof ElggSite)) { -		$CONFIG->wwwroot = $CONFIG->site->url; -		$CONFIG->sitename = $CONFIG->site->name; -		$CONFIG->sitedescription = $CONFIG->site->description; -		$CONFIG->siteemail = $CONFIG->site->email; -	} -	$CONFIG->url = $CONFIG->wwwroot; -	// Load default settings from database -	get_all_config(); -} +	// initialize context here so it is set before the get_input call +	$CONFIG->context = array(); + +	// needs to be set before system, init for links in html head +	$viewtype = get_input('view', 'default'); +	$lastcached = datalist_get("simplecache_lastcached_$viewtype"); +	$CONFIG->lastcache = $lastcached; -elgg_register_event_handler('boot', 'system', 'configuration_boot', 10); +	$CONFIG->i18n_loaded_from_cache = false; + +	// this must be synced with the enum for the entities table +	$CONFIG->entity_types = array('group', 'object', 'site', 'user'); +} diff --git a/engine/lib/database.php b/engine/lib/database.php index c44fdf1fd..cc2b99f6a 100644 --- a/engine/lib/database.php +++ b/engine/lib/database.php @@ -189,22 +189,6 @@ function db_delayedexecution_shutdown_hook() {  }  /** - * Registers shutdown functions for database profiling and delayed queries. - * - * @note Database connections are established upon first call to database. - * - * @return true - * @elgg_event_handler boot system - * @access private - */ -function init_db() { -	register_shutdown_function('db_delayedexecution_shutdown_hook'); -	register_shutdown_function('db_profiling_shutdown_hook'); - -	return true; -} - -/**   * Returns (if required, also creates) a database link resource.   *   * Database link resources are stored in the {@link $dblink} global.  These @@ -728,9 +712,9 @@ function sanitize_string($string) {  /**   * Sanitises an integer for database use.   * - * @param int $int Integer - * @param bool[optional] $signed Whether negative values should be allowed (true) - * @return int Sanitised integer + * @param int  $int    Value to be sanitized + * @param bool $signed Whether negative values should be allowed (true) + * @return int   */  function sanitise_int($int, $signed = true) {  	$int = (int) $int; @@ -745,18 +729,25 @@ function sanitise_int($int, $signed = true) {  }  /** - * Sanitises an integer for database use. + * Sanitizes an integer for database use.   * Wrapper function for alternate English spelling (@see sanitise_int)   * - * @param int $int Integer - * @param bool[optional] $signed Whether negative values should be allowed (true) - * @return int Sanitised integer + * @param int  $int    Value to be sanitized + * @param bool $signed Whether negative values should be allowed (true) + * @return int   */  function sanitize_int($int, $signed = true) {  	return sanitise_int($int, $signed);  }  /** - * @elgg_register_event boot system init_db + * Registers shutdown functions for database profiling and delayed queries. + * + * @access private   */ -elgg_register_event_handler('boot', 'system', 'init_db', 0); +function init_db() { +	register_shutdown_function('db_delayedexecution_shutdown_hook'); +	register_shutdown_function('db_profiling_shutdown_hook'); +} + +elgg_register_event_handler('init', 'system', 'init_db'); diff --git a/engine/lib/deprecated-1.8.php b/engine/lib/deprecated-1.8.php index e1866498b..4b9d41543 100644 --- a/engine/lib/deprecated-1.8.php +++ b/engine/lib/deprecated-1.8.php @@ -1674,7 +1674,7 @@ function get_plugin_list() {   * otherwise you may experience view display artifacts. Do this with the following code:   *   * 		elgg_regenerate_simplecache(); - *		elgg_filepath_cache_reset(); + *		elgg_reset_system_cache();   *   * @deprecated 1.8 Use elgg_generate_plugin_entities() and elgg_set_plugin_priorities()   * @@ -1841,7 +1841,7 @@ function get_installed_plugins($status = 'all') {   * otherwise you may experience view display artifacts. Do this with the following code:   *   * 		elgg_regenerate_simplecache(); - *		elgg_filepath_cache_reset(); + *		elgg_reset_system_cache();   *   * @deprecated 1.8 Use ElggPlugin->activate()   * @@ -1882,7 +1882,7 @@ function enable_plugin($plugin, $site_guid = null) {   * otherwise you may experience view display artifacts. Do this with the following code:   *   * 		elgg_regenerate_simplecache(); - *		elgg_filepath_cache_reset(); + *		elgg_reset_system_cache();   *   * @deprecated 1.8 Use ElggPlugin->deactivate()   * diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php index 57d602450..11bdc7285 100644 --- a/engine/lib/elgglib.php +++ b/engine/lib/elgglib.php @@ -995,7 +995,8 @@ function elgg_trigger_plugin_hook($hook, $type, $params = null, $returnvalue = n   * @access private   */  function _elgg_php_exception_handler($exception) { -	error_log("*** FATAL EXCEPTION *** : " . $exception); +	$timestamp = time(); +	error_log("Exception #$timestamp: $exception");  	// Wipe any existing output buffer  	ob_end_clean(); @@ -1011,7 +1012,17 @@ function _elgg_php_exception_handler($exception) {  		$CONFIG->pagesetupdone = true;  		elgg_set_viewtype('failsafe'); -		$body = elgg_view("messages/exceptions/exception", array('object' => $exception)); +		if (elgg_is_admin_logged_in()) { +			$body = elgg_view("messages/exceptions/admin_exception", array( +				'object' => $exception, +				'ts' => $timestamp +			)); +		} else { +			$body = elgg_view("messages/exceptions/exception", array( +				'object' => $exception, +				'ts' => $timestamp +			)); +		}  		echo elgg_view_page(elgg_echo('exception:title'), $body);  	} catch (Exception $e) {  		$timestamp = time(); @@ -1144,9 +1155,11 @@ function elgg_dump($value, $to_screen = TRUE, $level = 'NOTICE') {  	global $CONFIG;  	// plugin can return false to stop the default logging method -	$params = array('level' => $level, -					'msg' => $value, -					'to_screen' => $to_screen); +	$params = array( +		'level' => $level, +		'msg' => $value, +		'to_screen' => $to_screen, +	);  	if (!elgg_trigger_plugin_hook('debug', 'log', $params, true)) {  		return;  	} @@ -1172,7 +1185,9 @@ function elgg_dump($value, $to_screen = TRUE, $level = 'NOTICE') {   *   * This function either displays or logs the deprecation message,   * depending upon the deprecation policies in {@link CODING.txt}. - * Logged messages are sent with the level of 'WARNING'. + * Logged messages are sent with the level of 'WARNING'. Only admins + * get visual deprecation notices. When non-admins are logged in, the + * notices are sent to PHP's log through elgg_dump().   *   * A user-visual message will be displayed if $dep_version is greater   * than 1 minor releases lower than the current Elgg version, or at all @@ -1183,11 +1198,12 @@ function elgg_dump($value, $to_screen = TRUE, $level = 'NOTICE') {   *   * @see CODING.txt   * - * @param str $msg             Message to log / display. - * @param str $dep_version     Human-readable *release* version: 1.7, 1.7.3 - * @param int $backtrace_level How many levels back to display the backtrace. Useful if calling from - *                             functions that are called from other places (like elgg_view()). Set - *                             to -1 for a full backtrace. + * @param string $msg             Message to log / display. + * @param string $dep_version     Human-readable *release* version: 1.7, 1.8, ... + * @param int    $backtrace_level How many levels back to display the backtrace. + *                                Useful if calling from functions that are called + *                                from other places (like elgg_view()). Set to -1 + *                                for a full backtrace.   *   * @return bool   * @since 1.7.0 @@ -1196,13 +1212,13 @@ function elgg_deprecated_notice($msg, $dep_version, $backtrace_level = 1) {  	// if it's a major release behind, visual and logged  	// if it's a 1 minor release behind, visual and logged  	// if it's for current minor release, logged. -	// bugfixes don't matter because you're not deprecating between them, RIGHT? +	// bugfixes don't matter because we are not deprecating between them  	if (!$dep_version) { -		return FALSE; +		return false;  	} -	$elgg_version = get_version(TRUE); +	$elgg_version = get_version(true);  	$elgg_version_arr = explode('.', $elgg_version);  	$elgg_major_version = (int)$elgg_version_arr[0];  	$elgg_minor_version = (int)$elgg_version_arr[1]; @@ -1210,16 +1226,16 @@ function elgg_deprecated_notice($msg, $dep_version, $backtrace_level = 1) {  	$dep_major_version = (int)$dep_version;  	$dep_minor_version = 10 * ($dep_version - $dep_major_version); -	$visual = FALSE; +	$visual = false;  	if (($dep_major_version < $elgg_major_version) ||  		($dep_minor_version < $elgg_minor_version)) { -		$visual = TRUE; +		$visual = true;  	}  	$msg = "Deprecated in $dep_major_version.$dep_minor_version: $msg"; -	if ($visual) { +	if ($visual && elgg_is_admin_logged_in()) {  		register_error($msg);  	} @@ -1247,9 +1263,9 @@ function elgg_deprecated_notice($msg, $dep_version, $backtrace_level = 1) {  	$msg .= implode("<br /> -> ", $stack); -	elgg_log($msg, 'WARNING'); +	elgg_dump($msg, elgg_is_admin_logged_in(), 'WARNING'); -	return TRUE; +	return true;  }  /** @@ -1772,6 +1788,12 @@ function elgg_ajax_page_handler($page) {  		unset($page[0]);  		$view = implode('/', $page); +		$allowed_views = elgg_get_config('allowed_ajax_views'); +		if (!array_key_exists($view, $allowed_views)) { +			header('HTTP/1.1 403 Forbidden'); +			exit; +		} +  		// pull out GET parameters through filter  		$vars = array();  		foreach ($_GET as $name => $value) { @@ -1948,7 +1970,7 @@ function elgg_is_valid_options_for_batch_operation($options, $type) {  	// at least one of these is required.  	$required = array(  		// generic restraints -		'guid', 'guids', 'limit' +		'guid', 'guids'  	);  	switch ($type) { @@ -1996,9 +2018,7 @@ function elgg_is_valid_options_for_batch_operation($options, $type) {   * @access private   */  function elgg_walled_garden_index() { -	elgg_register_css('elgg.walled_garden', '/css/walled_garden.css');  	elgg_load_css('elgg.walled_garden'); -	elgg_register_js('elgg.walled_garden', '/js/walled_garden.js');  	elgg_load_js('elgg.walled_garden');  	$body = elgg_view('core/walled_garden/body'); @@ -2026,6 +2046,9 @@ function elgg_walled_garden_index() {  function elgg_walled_garden() {  	global $CONFIG; +	elgg_register_css('elgg.walled_garden', '/css/walled_garden.css'); +	elgg_register_js('elgg.walled_garden', '/js/walled_garden.js'); +  	// check for external page view  	if (isset($CONFIG->site) && $CONFIG->site instanceof ElggSite) {  		$CONFIG->site->checkWalledGarden(); @@ -2033,6 +2056,36 @@ function elgg_walled_garden() {  }  /** + * Boots the engine + * + * 1. sets error handlers + * 2. connects to database + * 3. verifies the installation suceeded + * 4. loads application configuration + * 5. loads i18n data + * 6. loads site configuration + * + * @access private + */ +function _elgg_engine_boot() { +	// Register the error handlers +	set_error_handler('_elgg_php_error_handler'); +	set_exception_handler('_elgg_php_exception_handler'); + +	setup_db_connections(); + +	verify_installation(); + +	_elgg_load_application_config(); + +	register_translations(dirname(dirname(dirname(__FILE__))) . "/languages/"); + +	_elgg_load_site_config(); + +	_elgg_load_cache(); +} + +/**   * Elgg's main init.   *   * Handles core actions for comments, the JS pagehandler, and the shutdown function. @@ -2155,6 +2208,7 @@ define('REFERRER', -1);  define('REFERER', -1);  elgg_register_event_handler('init', 'system', 'elgg_init'); +elgg_register_event_handler('boot', 'system', '_elgg_engine_boot', 1);  elgg_register_plugin_hook_handler('unit_test', 'system', 'elgg_api_test');  elgg_register_event_handler('init', 'system', 'add_custom_menu_items', 1000); diff --git a/engine/lib/entities.php b/engine/lib/entities.php index daced6740..4875b2c2f 100644 --- a/engine/lib/entities.php +++ b/engine/lib/entities.php @@ -738,6 +738,7 @@ function elgg_entity_exists($guid) {   *           Joined with subtypes by AND. See below)   *   * 	subtypes => NULL|STR entity subtype (SQL: subtype IN ('subtype1', 'subtype2)) + *              Use ELGG_ENTITIES_NO_VALUE for no subtype.   *   * 	type_subtype_pairs => NULL|ARR (array('type' => 'subtype'))   *                        (type = '$type' AND subtype = '$subtype') pairs @@ -923,7 +924,7 @@ function elgg_get_entities(array $options = array()) {  		}  		if ($options['limit']) { -			$limit = sanitise_int($options['limit']); +			$limit = sanitise_int($options['limit'], false);  			$offset = sanitise_int($options['offset'], false);  			$query .= " LIMIT $offset, $limit";  		} @@ -960,8 +961,8 @@ function elgg_get_entity_type_subtype_where_sql($table, $types, $subtypes, $pair  		return '';  	} -	// these are the only valid types for entities in elgg as defined in the DB. -	$valid_types = array('object', 'user', 'group', 'site'); +	// these are the only valid types for entities in elgg +	$valid_types = elgg_get_config('entity_types');  	// pairs override  	$wheres = array(); @@ -1378,34 +1379,33 @@ function disable_entity($guid, $reason = "", $recursive = true) {  				}  				if ($recursive) { -					// Temporary token overriding access controls -					// @todo Do this better. -					static $__RECURSIVE_DELETE_TOKEN; -					// Make it slightly harder to guess -					$__RECURSIVE_DELETE_TOKEN = md5(elgg_get_logged_in_user_guid()); - -					$sub_entities = get_data("SELECT * from {$CONFIG->dbprefix}entities -						WHERE container_guid=$guid -						or owner_guid=$guid -						or site_guid=$guid", 'entity_row_to_elggstar'); +					$hidden = access_get_show_hidden_status(); +					access_show_hidden_entities(true); +					$ia = elgg_set_ignore_access(true); +					 +					$sub_entities = get_data("SELECT * FROM {$CONFIG->dbprefix}entities +						WHERE ( +						container_guid = $guid +						OR owner_guid = $guid +						OR site_guid = $guid +						) AND enabled='yes'", 'entity_row_to_elggstar');  					if ($sub_entities) {  						foreach ($sub_entities as $e) { +							add_entity_relationship($e->guid, 'disabled_with', $entity->guid);  							$e->disable($reason);  						}  					} - -					$__RECURSIVE_DELETE_TOKEN = null; +					access_show_hidden_entities($hidden); +					elgg_set_ignore_access($ia);  				}  				$entity->disableMetadata();  				$entity->disableAnnotations(); -				// relationships can't be disabled. hope they join to the entities table. -				//$entity->disableRelationships();  				$res = update_data("UPDATE {$CONFIG->dbprefix}entities -					set enabled='no' -					where guid={$guid}"); +					SET enabled = 'no' +					WHERE guid = $guid");  				return $res;  			} @@ -1420,40 +1420,51 @@ function disable_entity($guid, $reason = "", $recursive = true) {   * @warning In order to enable an entity using ElggEntity::enable(),   * you must first use {@link access_show_hidden_entities()}.   * - * @param int $guid GUID of entity to enable + * @param int  $guid      GUID of entity to enable + * @param bool $recursive Recursively enable all entities disabled with the entity?   *   * @return bool   */ -function enable_entity($guid) { +function enable_entity($guid, $recursive = true) {  	global $CONFIG;  	$guid = (int)$guid;  	// Override access only visible entities -	$access_status = access_get_show_hidden_status(); +	$old_access_status = access_get_show_hidden_status();  	access_show_hidden_entities(true); +	$result = false;  	if ($entity = get_entity($guid)) {  		if (elgg_trigger_event('enable', $entity->type, $entity)) {  			if ($entity->canEdit()) { -				access_show_hidden_entities($access_status); -  				$result = update_data("UPDATE {$CONFIG->dbprefix}entities -					set enabled='yes' -					where guid={$guid}"); +					SET enabled = 'yes' +					WHERE guid = $guid");  				$entity->deleteMetadata('disable_reason');  				$entity->enableMetadata();  				$entity->enableAnnotations(); -				return $result; +				if ($recursive) { +					$disabled_with_it = elgg_get_entities_from_relationship(array( +						'relationship' => 'disabled_with', +						'relationship_guid' => $entity->guid, +						'inverse_relationship' => true, +					)); + +					foreach ($disabled_with_it as $e) { +						$e->enable(); +						remove_entity_relationship($e->guid, 'disabled_with', $entity->guid); +					} +				}  			}  		}  	} -	access_show_hidden_entities($access_status); -	return false; +	access_show_hidden_entities($old_access_status); +	return $result;  }  /** @@ -1510,18 +1521,23 @@ function delete_entity($guid, $recursive = true) {  					$entity_disable_override = access_get_show_hidden_status();  					access_show_hidden_entities(true);  					$ia = elgg_set_ignore_access(true); -					$sub_entities = get_data("SELECT * from {$CONFIG->dbprefix}entities -						WHERE container_guid=$guid -							or owner_guid=$guid -							or site_guid=$guid", 'entity_row_to_elggstar'); -					if ($sub_entities) { -						foreach ($sub_entities as $e) { -							// check for equality so that an entity that is its own -							// owner or container does not cause infinite loop -							if ($e->guid != $guid) { -								$e->delete(true); -							} -						} + +					// @todo there was logic in the original code that ignored +					// entities with owner or container guids of themselves. +					// this should probably be prevented in ElggEntity instead of checked for here +					$options = array( +						'wheres' => array( +							"((container_guid = $guid OR owner_guid = $guid OR site_guid = $guid)" +							. " AND guid != $guid)" +							), +						'limit' => 0 +					); + +					$batch = new ElggBatch('elgg_get_entities', $options); +					$batch->setIncrementOffset(false); + +					foreach ($batch as $e) { +						$e->delete(true);  					}  					access_show_hidden_entities($entity_disable_override); @@ -1955,7 +1971,7 @@ function elgg_register_entity_type($type, $subtype = null) {  	global $CONFIG;  	$type = strtolower($type); -	if (!in_array($type, array('object', 'site', 'group', 'user'))) { +	if (!in_array($type, $CONFIG->entity_types)) {  		return FALSE;  	} @@ -1990,7 +2006,7 @@ function unregister_entity_type($type, $subtype) {  	global $CONFIG;  	$type = strtolower($type); -	if (!in_array($type, array('object', 'site', 'group', 'user'))) { +	if (!in_array($type, $CONFIG->entity_types)) {  		return FALSE;  	} @@ -2158,31 +2174,8 @@ function elgg_list_registered_entities(array $options = array()) {  		$entities = array();  	} -	return elgg_view_entity_list($entities, $count, $options['offset'], -		$options['limit'], $options['full_view'], $options['list_type_toggle'], $options['pagination']); -} - -/** - * Check the recursive delete permissions token. - * - * If an entity is deleted recursively, a permissions override is required to allow - * contained or owned entities to be removed. - * - * @return bool - * @elgg_plugin_hook_handler permissions_check all - * @elgg_plugin_hook_handler permissions_check:metadata all - * @access private - */ -function recursive_delete_permissions_check() { -	static $__RECURSIVE_DELETE_TOKEN; - -	if ((elgg_is_logged_in()) && ($__RECURSIVE_DELETE_TOKEN) -	&& (strcmp($__RECURSIVE_DELETE_TOKEN, md5(elgg_get_logged_in_user_guid())))) { -		return true; -	} - -	// consult next function -	return NULL; +	$options['count'] = $count; +	return elgg_view_entity_list($entities, $options);  }  /** @@ -2299,11 +2292,6 @@ function entities_init() {  	elgg_register_plugin_hook_handler('unit_test', 'system', 'entities_test'); -	// Allow a permission override for recursive entity deletion -	// @todo Can this be done better? -	elgg_register_plugin_hook_handler('permissions_check', 'all', 'recursive_delete_permissions_check'); -	elgg_register_plugin_hook_handler('permissions_check:metadata', 'all', 'recursive_delete_permissions_check'); -  	elgg_register_plugin_hook_handler('gc', 'system', 'entities_gc');  } @@ -2318,3 +2306,4 @@ elgg_register_plugin_hook_handler('volatile', 'metadata', 'volatile_data_export_  /** Register init system event **/  elgg_register_event_handler('init', 'system', 'entities_init'); + diff --git a/engine/lib/extender.php b/engine/lib/extender.php index 51fc62c30..ffd3c1357 100644 --- a/engine/lib/extender.php +++ b/engine/lib/extender.php @@ -164,9 +164,9 @@ function can_edit_extender($extender_id, $type, $user_guid = 0) {   * It is recommended that you do not call this directly, instead use   * one of the wrapper functions such as elgg_register_annotation_url_handler().   * - * @param string $function_name The function to register   * @param string $extender_type Extender type ('annotation', 'metadata')   * @param string $extender_name The name of the extender + * @param string $function_name The function to register   *   * @return bool   */ diff --git a/engine/lib/filestore.php b/engine/lib/filestore.php index a13d8aa27..86f6d9baa 100644 --- a/engine/lib/filestore.php +++ b/engine/lib/filestore.php @@ -18,7 +18,7 @@   */  function get_dir_size($dir, $totalsize = 0) {  	$handle = @opendir($dir); -	while ($file = @readdir ($handle)) { +	while ($file = @readdir($handle)) {  		if (eregi("^\.{1,2}$", $file)) {  			continue;  		} diff --git a/engine/lib/group.php b/engine/lib/group.php index 29330eeca..feb1f1e7f 100644 --- a/engine/lib/group.php +++ b/engine/lib/group.php @@ -261,16 +261,24 @@ function group_gatekeeper($forward = true) {  	if ($group = elgg_get_page_owner_entity()) {  		if ($group instanceof ElggGroup) {  			$url = $group->getURL(); -			if ( -				((!elgg_is_logged_in()) && (!$group->isPublicMembership())) || -				((!$group->isMember(elgg_get_logged_in_user_entity()) && (!$group->isPublicMembership()))) -			) { -				$allowed = false; -			} +			if (!$group->isPublicMembership()) { +				// closed group so must be member or an admin + +				if (!elgg_is_logged_in()) { +					$allowed = false; +					if ($forward == true) { +						$_SESSION['last_forward_from'] = current_page_url(); +						register_error(elgg_echo('loggedinrequired')); +						forward('', 'login'); +					} +				} else if (!$group->isMember(elgg_get_logged_in_user_entity())) { +					$allowed = false; +				} -			// Admin override -			if (elgg_is_admin_logged_in()) { -				$allowed = true; +				// Admin override +				if (elgg_is_admin_logged_in()) { +					$allowed = true; +				}  			}  		}  	} diff --git a/engine/lib/input.php b/engine/lib/input.php index 57e35786f..dda8211b6 100644 --- a/engine/lib/input.php +++ b/engine/lib/input.php @@ -188,8 +188,8 @@ function elgg_get_sticky_value($form_name, $variable = '', $default = NULL, $fil  /**   * Get all the values in a sticky form in an array   * - * @param string $form_name    The name of the form - * @param bool $filter_result  Filter for bad input if true + * @param string $form_name     The name of the form + * @param bool   $filter_result Filter for bad input if true   *   * @return array   * @since 1.8.0 diff --git a/engine/lib/languages.php b/engine/lib/languages.php index 0400843af..bf6829a39 100644 --- a/engine/lib/languages.php +++ b/engine/lib/languages.php @@ -145,9 +145,16 @@ function elgg_echo($message_key, $args = array(), $language = "") {  function register_translations($path, $load_all = false) {  	global $CONFIG; +	static $load_from_cache; +	static $cache_loaded_langs; +	if (!isset($load_from_cache)) { +		$load_from_cache = $CONFIG->system_cache_enabled; +		$cache_loaded_langs = array(); +	} +  	$path = sanitise_filepath($path); -	// Make a note of this path just incase we need to register this language later +	// Make a note of this path just in case we need to register this language later  	if (!isset($CONFIG->language_paths)) {  		$CONFIG->language_paths = array();  	} @@ -155,7 +162,6 @@ function register_translations($path, $load_all = false) {  	// Get the current language based on site defaults and user preference  	$current_language = get_current_language(); -	elgg_log("Translations loaded from: $path");  	// only load these files unless $load_all is true.  	$load_language_files = array( @@ -165,6 +171,32 @@ function register_translations($path, $load_all = false) {  	$load_language_files = array_unique($load_language_files); +	if ($load_from_cache && !$load_all) { +		// load language files from cache +		$data = array(); +		foreach ($load_language_files as $lang_file) { +			$lang = substr($lang_file, 0, strpos($lang_file, '.')); +			if (!isset($cache_loaded_langs[$lang])) { +				$data[$lang] = elgg_load_system_cache($lang_file); +				if ($data[$lang]) { +					$cache_loaded_langs[$lang] = true; +				} else { +					// this language file not cached yet +					$load_from_cache = false; +				} +			} +		} + +		// are we still suppose to load from cache +		if ($load_from_cache) { +			foreach ($data as $lang => $map) { +				add_translation($lang, unserialize($map)); +			} +			$CONFIG->i18n_loaded_from_cache = true; +			return true; +		} +	} +  	$handle = opendir($path);  	if (!$handle) {  		elgg_log("Could not open language path: $path", 'ERROR'); @@ -186,6 +218,11 @@ function register_translations($path, $load_all = false) {  		}  	} +	elgg_log("Translations loaded from: $path"); + +	// make sure caching code saves language data if system cache is on +	$CONFIG->i18n_loaded_from_cache = false; +  	return $return;  } @@ -311,5 +348,3 @@ function elgg_languages_init() {  }  elgg_register_event_handler('init', 'system', 'elgg_languages_init'); - -register_translations(dirname(dirname(dirname(__FILE__))) . "/languages/"); diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php index 050e69526..34a36d86e 100644 --- a/engine/lib/metadata.php +++ b/engine/lib/metadata.php @@ -216,12 +216,11 @@ function update_metadata($id, $name, $value, $value_type, $owner_guid, $access_i  	$result = update_data($query);  	if ($result !== false) { +		// @todo this event tells you the metadata has been updated, but does not +		// let you do anything about it. What is needed is a plugin hook before +		// the update that passes old and new values.  		$obj = elgg_get_metadata_from_id($id); -		if (elgg_trigger_event('update', 'metadata', $obj)) { -			return true; -		} else { -			elgg_delete_metadata_by_id($id); -		} +		elgg_trigger_event('update', 'metadata', $obj);  	}  	return $result; @@ -270,21 +269,18 @@ $access_id = ACCESS_PRIVATE, $allow_multiple = false) {   *   * @param array $options Array in format:   * - * 	metadata_names => NULL|ARR metadata names - * - * 	metadata_values => NULL|ARR metadata values - * -* 	metadata_ids => NULL|ARR metadata ids - * - * 	metadata_case_sensitive => BOOL Overall Case sensitive - * - *  metadata_owner_guids => NULL|ARR guids for metadata owners - * - *  metadata_created_time_lower => INT Lower limit for created time. - * - *  metadata_created_time_upper => INT Upper limit for created time. - * - *  metadata_calculation => STR Perform the MySQL function on the metadata values returned. + * metadata_names               => NULL|ARR metadata names + * metadata_values              => NULL|ARR metadata values + * metadata_ids                 => NULL|ARR metadata ids + * metadata_case_sensitive      => BOOL Overall Case sensitive + * metadata_owner_guids         => NULL|ARR guids for metadata owners + * metadata_created_time_lower  => INT Lower limit for created time. + * metadata_created_time_upper  => INT Upper limit for created time. + * metadata_calculation         => STR Perform the MySQL function on the metadata values returned. + *                                   The "metadata_calculation" option causes this function to + *                                   return the result of performing a mathematical calculation on + *                                   all metadata that match the query instead of returning + *                                   ElggMetadata objects.   *   * @return mixed   * @since 1.8.0 @@ -298,11 +294,11 @@ function elgg_get_metadata(array $options = array()) {   * Deletes metadata based on $options.   *   * @warning Unlike elgg_get_metadata() this will not accept an empty options array! - *          This requires some constraints: metadata_owner_guid(s), - *          metadata_name(s), metadata_value(s), or limit must be set. + *          This requires at least one constraint: metadata_owner_guid(s), + *          metadata_name(s), metadata_value(s), or guid(s) must be set.   * - * @param array $options An options array. {@See elgg_get_metadata()} - * @return mixed + * @param array $options An options array. {@see elgg_get_metadata()} + * @return mixed Null if the metadata name is invalid. Bool on success or fail.   * @since 1.8.0   */  function elgg_delete_metadata(array $options) { @@ -311,7 +307,8 @@ function elgg_delete_metadata(array $options) {  	}  	$options['metastring_type'] = 'metadata'; -	return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback'); +	$result = elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback'); +	return $result;  }  /** @@ -328,7 +325,7 @@ function elgg_disable_metadata(array $options) {  		return false;  	} -	$options['metastrings_type'] = 'metadata'; +	$options['metastring_type'] = 'metadata';  	return elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback');  } @@ -403,15 +400,15 @@ function elgg_enable_metadata(array $options) {   */  function elgg_get_entities_from_metadata(array $options = array()) {  	$defaults = array( -		'metadata_names'					=>	ELGG_ENTITIES_ANY_VALUE, -		'metadata_values'					=>	ELGG_ENTITIES_ANY_VALUE, -		'metadata_name_value_pairs'			=>	ELGG_ENTITIES_ANY_VALUE, +		'metadata_names'                     => ELGG_ENTITIES_ANY_VALUE, +		'metadata_values'                    => ELGG_ENTITIES_ANY_VALUE, +		'metadata_name_value_pairs'          => ELGG_ENTITIES_ANY_VALUE, -		'metadata_name_value_pairs_operator'=>	'AND', -		'metadata_case_sensitive' 			=>	TRUE, -		'order_by_metadata'					=>	array(), +		'metadata_name_value_pairs_operator' => 'AND', +		'metadata_case_sensitive'            => TRUE, +		'order_by_metadata'                  => array(), -		'metadata_owner_guids'				=>	ELGG_ENTITIES_ANY_VALUE, +		'metadata_owner_guids'               => ELGG_ENTITIES_ANY_VALUE,  	);  	$options = array_merge($defaults, $options); @@ -634,7 +631,7 @@ $owner_guids = NULL) {  			$i++;  		} -		if ($where = implode (" $pair_operator ", $pair_wheres)) { +		if ($where = implode(" $pair_operator ", $pair_wheres)) {  			$wheres[] = "($where)";  		}  	} @@ -749,7 +746,7 @@ function export_metadata_plugin_hook($hook, $entity_type, $returnvalue, $params)  /**   * Takes in a comma-separated string and returns an array of tags - * which have been trimmed and set to lower case + * which have been trimmed   *   * @param string $string Comma-separated tag string   * @@ -758,12 +755,7 @@ function export_metadata_plugin_hook($hook, $entity_type, $returnvalue, $params)  function string_to_tag_array($string) {  	if (is_string($string)) {  		$ar = explode(",", $string); -		// trim blank spaces  		$ar = array_map('trim', $ar); -		// make lower case : [Marcus Povey 20090605 - Using mb wrapper function -		// using UTF8 safe function where available] -		$ar = array_map('elgg_strtolower', $ar); -		// Remove null values  		$ar = array_filter($ar, 'is_not_null');  		return $ar;  	} @@ -872,8 +864,8 @@ function metadata_update($event, $object_type, $object) {  /**   * Register a metadata url handler.   * - * @param string $function_name The function.   * @param string $extender_name The name, default 'all'. + * @param string $function      The function name.   *   * @return bool   */ diff --git a/engine/lib/metastrings.php b/engine/lib/metastrings.php index 9fe9b4bff..d7cc4e0bc 100644 --- a/engine/lib/metastrings.php +++ b/engine/lib/metastrings.php @@ -609,8 +609,7 @@ function elgg_get_metastring_sql($table, $names = null, $values = null,  }  /** - * Normalizes metadata / annotation option names to their - * corresponding metastrings name. + * Normalizes metadata / annotation option names to their corresponding metastrings name.   *   * @param array $options An options array   * @since 1.8.0 @@ -631,10 +630,10 @@ function elgg_normalize_metastrings_options(array $options = array()) {  	// map the metadata_* options to metastring_* options  	$map = array( -		'names' 				=>	'metastring_names', -		'values' 				=>	'metastring_values', -		'case_sensitive' 		=>	'metastring_case_sensitive', -		'owner_guids' 			=>	'metastring_owner_guids', +		'names'					=>	'metastring_names', +		'values'				=>	'metastring_values', +		'case_sensitive'		=>	'metastring_case_sensitive', +		'owner_guids'			=>	'metastring_owner_guids',  		'created_time_lower'	=>	'metastring_created_time_lower',  		'created_time_upper'	=>	'metastring_created_time_upper',  		'calculation'			=>	'metastring_calculation', @@ -728,7 +727,8 @@ function elgg_batch_metastring_based_objects(array $options, $callback) {  		return false;  	} -	$batch = new ElggBatch('elgg_get_metastring_based_objects', $options, $callback); +	// @todo restore once ElggBatch supports callbacks that delete rows. +	$batch = new ElggBatch('elgg_get_metastring_based_objects', $options, $callback, 50, false);  	$r = $batch->callbackResult;  	return $r; diff --git a/engine/lib/navigation.php b/engine/lib/navigation.php index 956ca220a..a7984ce5a 100644 --- a/engine/lib/navigation.php +++ b/engine/lib/navigation.php @@ -78,7 +78,11 @@   *                          link_class  => STR  A class or classes for the <a> tag   *                          item_class  => STR  A class or classes for the <li> tag   * - *                          Custom options can be added as key value pairs. + *                          Additional options that the view output/url takes can be + *							passed in the array. If the 'confirm' key is passed, the + *							menu link uses the 'output/confirmlink' view. Custom + *							options can be added by using the 'data' key with the + *							value being an associative array.   *   * @return bool   * @since 1.8.0 @@ -301,7 +305,7 @@ function elgg_site_menu_setup($hook, $type, $return, $params) {  		// if only one item on more menu, stick it with the rest  		$num_menu_items = count($return['default']);  		if ($num_menu_items > ($max_display_items + 1)) { -			$return['more'] =  array_splice($return['default'], $max_display_items); +			$return['more'] = array_splice($return['default'], $max_display_items);  		}  	} diff --git a/engine/lib/notification.php b/engine/lib/notification.php index eb7e594c6..5a2f5f8ac 100644 --- a/engine/lib/notification.php +++ b/engine/lib/notification.php @@ -487,6 +487,7 @@ function object_notifications($event, $object_type, $object) {  			// (Person defined by container_guid so we can also subscribe to groups if we want)  			foreach ($NOTIFICATION_HANDLERS as $method => $foo) {  				$interested_users = elgg_get_entities_from_relationship(array( +					'site_guids' => ELGG_ENTITIES_ANY_VALUE,  					'relationship' => 'notify' . $method,  					'relationship_guid' => $object->container_guid,  					'inverse_relationship' => TRUE, diff --git a/engine/lib/objects.php b/engine/lib/objects.php index 63d0f5cef..f186c66cb 100644 --- a/engine/lib/objects.php +++ b/engine/lib/objects.php @@ -52,11 +52,8 @@ function create_object_entity($guid, $title, $description) {  			if ($result != false) {  				// Update succeeded, continue  				$entity = get_entity($guid); -				if (elgg_trigger_event('update', $entity->type, $entity)) { -					return $guid; -				} else { -					$entity->delete(); -				} +				elgg_trigger_event('update', $entity->type, $entity); +				return $guid;  			}  		} else {  			// Update failed, attempt an insert. diff --git a/engine/lib/output.php b/engine/lib/output.php index 6554481f5..b96cf354c 100644 --- a/engine/lib/output.php +++ b/engine/lib/output.php @@ -67,7 +67,7 @@ function autop($pee, $br = 1) {  	$pee = preg_replace('/\n?(.+?)(?:\n\s*\n|\z)/s', "<p>$1</p>\n", $pee); // make paragraphs, including one at the end  	$pee = preg_replace('|<p>\s*?</p>|', '', $pee); // under certain strange conditions it could create a P of entirely whitespace  	$pee = preg_replace('!<p>([^<]+)\s*?(</(?:div|address|form)[^>]*>)!', "<p>$1</p>$2", $pee); -	$pee = preg_replace( '|<p>|', "$1<p>", $pee ); +	$pee = preg_replace('|<p>|', "$1<p>", $pee);  	$pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); // don't pee all over a tag  	$pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); // problem with nested lists  	$pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee); @@ -81,11 +81,11 @@ function autop($pee, $br = 1) {  	}  	$pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee);  	$pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee); -//	if (strpos($pee, '<pre') !== false) { -//		mind the space between the ? and >.  Only there because of the comment. -//		$pee = preg_replace_callback('!(<pre.*? >)(.*?)</pre>!is', 'clean_pre', $pee ); -//	} -	$pee = preg_replace( "|\n</p>$|", '</p>', $pee ); +	//if (strpos($pee, '<pre') !== false) { +	//	mind the space between the ? and >.  Only there because of the comment. +	//	$pee = preg_replace_callback('!(<pre.*? >)(.*?)</pre>!is', 'clean_pre', $pee ); +	//} +	$pee = preg_replace("|\n</p>$|", '</p>', $pee);  	return $pee;  } diff --git a/engine/lib/pagehandler.php b/engine/lib/pagehandler.php index ffcfc5b6a..a675d976a 100644 --- a/engine/lib/pagehandler.php +++ b/engine/lib/pagehandler.php @@ -120,6 +120,7 @@ function elgg_unregister_page_handler($handler) {   * @param string $type   The type of the hook   * @param bool   $result The current value of the hook   * @param array  $params Parameters related to the hook + * @return void   */  function elgg_error_page_handler($hook, $type, $result, $params) {  	if (elgg_view_exists("errors/$type")) { diff --git a/engine/lib/pageowner.php b/engine/lib/pageowner.php index 9d41d74c1..0cf0e0625 100644 --- a/engine/lib/pageowner.php +++ b/engine/lib/pageowner.php @@ -54,7 +54,7 @@ function elgg_get_page_owner_entity() {   * Set the guid of the entity that owns this page   *   * @param int $guid The guid of the page owner - * + * @return void   * @since 1.8.0   */  function elgg_set_page_owner_guid($guid) { @@ -173,7 +173,7 @@ function default_page_owner_handler($hook, $entity_type, $returnvalue, $params)   * @warning The context is not available until the page_handler runs (after   * the 'init, system' event processing has completed).   * - * @param  string $context The context of the page + * @param string $context The context of the page   * @return bool   * @since 1.8.0   */ @@ -216,6 +216,7 @@ function elgg_get_context() {   * Push a context onto the top of the stack   *   * @param string $context The context string to add to the context stack + * @return void   * @since 1.8.0   */  function elgg_push_context($context) { @@ -244,7 +245,7 @@ function elgg_pop_context() {   * itself differently based on being on the dashboard or profile pages, it   * can check the stack.   * - * @param  string $context The context string to check for + * @param string $context The context string to check for   * @return bool   * @since 1.8.0   */ diff --git a/engine/lib/plugins.php b/engine/lib/plugins.php index be871d025..123fb18d8 100644 --- a/engine/lib/plugins.php +++ b/engine/lib/plugins.php @@ -62,7 +62,7 @@ function elgg_get_plugin_ids_in_dir($dir = null) {  		$dir = elgg_get_plugins_path();  	} -	$plugin_idss = array(); +	$plugin_ids = array();  	$handle = opendir($dir);  	if ($handle) { @@ -298,19 +298,13 @@ function elgg_load_plugins() {  	// temporary disable all plugins if there is a file called 'disabled' in the plugin dir  	if (file_exists("$plugins_path/disabled")) { +		if (elgg_is_admin_logged_in() && elgg_in_context('admin')) { +			system_message(elgg_echo('plugins:disabled')); +		}  		return false;  	} -	// Load view caches if available -	$cached_view_paths = elgg_filepath_cache_load('views'); -	$cached_view_types = elgg_filepath_cache_load('view_types'); -	$cached_view_info = is_string($cached_view_paths) && is_string($cached_view_types); - -	if ($cached_view_info) { -		$CONFIG->views = unserialize($cached_view_paths); -		$CONFIG->view_types = unserialize($cached_view_types); - -		// don't need to register views +	if (elgg_get_config('system_cache_loaded')) {  		$start_flags = $start_flags & ~ELGG_PLUGIN_REGISTER_VIEWS;  	} @@ -332,12 +326,6 @@ function elgg_load_plugins() {  		}  	} -	// Cache results -	if (!$cached_view_info) { -		elgg_filepath_cache_save('views', serialize($CONFIG->views)); -		elgg_filepath_cache_save('view_types', serialize($CONFIG->view_types)); -	} -  	return $return;  } @@ -439,9 +427,9 @@ function elgg_set_plugin_priorities(array $order) {  		}  	} -	// set the missing plugins priorities +	// set the missing plugins' priorities  	if ($return && $missing_plugins) { -		if (!$priority) { +		if (!isset($priority)) {  			$priority = 0;  		}  		foreach ($missing_plugins as $plugin) { @@ -480,9 +468,10 @@ function elgg_reindex_plugin_priorities() {   */  function elgg_namespace_plugin_private_setting($type, $name, $id = null) {  	switch ($type) { -//		case 'setting': -//			$name = ELGG_PLUGIN_SETTING_PREFIX . $name; -//			break; +		// commented out because it breaks $plugin->$name access to variables +		//case 'setting': +		//	$name = ELGG_PLUGIN_SETTING_PREFIX . $name; +		//	break;  		case 'user_setting':  			if (!$id) { diff --git a/engine/lib/private_settings.php b/engine/lib/private_settings.php index 386af5279..1fa9bdb66 100644 --- a/engine/lib/private_settings.php +++ b/engine/lib/private_settings.php @@ -240,7 +240,7 @@ $pairs = NULL, $pair_operator = 'AND', $name_prefix = '') {  			$i++;  		} -		$where = implode (" $pair_operator ", $pair_wheres); +		$where = implode(" $pair_operator ", $pair_wheres);  		if ($where) {  			$wheres[] = "($where)";  		} diff --git a/engine/lib/relationships.php b/engine/lib/relationships.php index 5b7080b56..fabe2d2d6 100644 --- a/engine/lib/relationships.php +++ b/engine/lib/relationships.php @@ -399,8 +399,8 @@ function elgg_list_entities_from_relationship_count($options) {  /**   * Sets the URL handler for a particular relationship type   * - * @param string $function_name     The function to register   * @param string $relationship_type The relationship type. + * @param string $function_name     The function to register   *   * @return bool Depending on success   */ diff --git a/engine/lib/river.php b/engine/lib/river.php index 421813441..547d9495e 100644 --- a/engine/lib/river.php +++ b/engine/lib/river.php @@ -44,10 +44,16 @@ $posted = 0, $annotation_id = 0) {  	if ($access_id === "") {  		$access_id = $object->access_id;  	} -	$annotation_id = (int)$annotation_id;  	$type = $object->getType();  	$subtype = $object->getSubtype(); + +	$view = sanitise_string($view);  	$action_type = sanitise_string($action_type); +	$subject_guid = sanitise_int($subject_guid); +	$object_guid = sanitise_int($object_guid); +	$access_id = sanitise_int($access_id); +	$posted = sanitise_int($posted); +	$annotation_id = sanitise_int($annotation_id);  	$params = array(  		'type' => $type, @@ -102,7 +108,7 @@ $posted = 0, $annotation_id = 0) {   *   * @warning not checking access (should we?)   * - * @param array $options + * @param array $options Parameters:   *   ids                  => INT|ARR River item id(s)   *   subject_guids        => INT|ARR Subject guid(s)   *   object_guids         => INT|ARR Object guid(s) @@ -209,7 +215,7 @@ function elgg_delete_river(array $options = array()) {   *   * @note If using types and subtypes in a query, they are joined with an AND.   * - * @param array $options + * @param array $options Parameters:   *   ids                  => INT|ARR River item id(s)   *   subject_guids        => INT|ARR Subject guid(s)   *   object_guids         => INT|ARR Object guid(s) @@ -542,7 +548,7 @@ function elgg_river_get_action_where_sql($types) {  /**   * Get the where clause based on river view strings   * - * @param array $types Array of view strings + * @param array $views Array of view strings   *   * @return string   * @since 1.8.0 diff --git a/engine/lib/sessions.php b/engine/lib/sessions.php index 97a05e2e8..9982d9fe8 100644 --- a/engine/lib/sessions.php +++ b/engine/lib/sessions.php @@ -355,7 +355,7 @@ function logout() {  	session_destroy();  	// starting a default session to store any post-logout messages. -	session_init(NULL, NULL, NULL); +	_elgg_session_boot(NULL, NULL, NULL);  	$_SESSION['msg'] = $old_msg;  	return TRUE; @@ -379,7 +379,7 @@ function logout() {   * @return bool   * @access private   */ -function session_init($event, $object_type, $object) { +function _elgg_session_boot($event, $object_type, $object) {  	global $DB_PREFIX, $CONFIG;  	// Use database for sessions @@ -444,8 +444,8 @@ function session_init($event, $object_type, $object) {  		set_last_action($_SESSION['guid']);  	} -	elgg_register_action("login", '', 'public'); -	elgg_register_action("logout"); +	elgg_register_action('login', '', 'public'); +	elgg_register_action('logout');  	// Register a default PAM handler  	register_pam_handler('pam_auth_userpass'); @@ -655,4 +655,4 @@ function _elgg_session_gc($maxlifetime) {  	return true;  } -elgg_register_event_handler("boot", "system", "session_init", 20); +elgg_register_event_handler('boot', 'system', '_elgg_session_boot', 2); diff --git a/engine/lib/sites.php b/engine/lib/sites.php index 337b2d180..850092cad 100644 --- a/engine/lib/sites.php +++ b/engine/lib/sites.php @@ -231,43 +231,6 @@ function get_site_domain($guid) {  }  /** - * Initialise site handling - * - * Called at the beginning of system running, to set the ID of the current site. - * This is 0 by default, but plugins may alter this behaviour by attaching functions - * to the sites init event and changing $CONFIG->site_id. - * - * @uses $CONFIG - * - * @param string $event       Event API required parameter - * @param string $object_type Event API required parameter - * @param null   $object      Event API required parameter - * - * @return true - * @access private - */ -function sites_boot($event, $object_type, $object) { -	global $CONFIG; - -	$site = elgg_trigger_plugin_hook("siteid", "system"); -	if ($site === null || $site === false) { -		$CONFIG->site_id = (int) datalist_get('default_site'); -	} else { -		$CONFIG->site_id = $site; -	} -	$CONFIG->site_guid = $CONFIG->site_id; -	$CONFIG->site = get_entity($CONFIG->site_guid); - -	return true; -} - -// Register event handlers -elgg_register_event_handler('boot', 'system', 'sites_boot', 2); - -// Register with unit test -elgg_register_plugin_hook_handler('unit_test', 'system', 'sites_test'); - -/**   * Unit tests for sites   *   * @param sting  $hook   unit_test @@ -283,3 +246,6 @@ function sites_test($hook, $type, $value, $params) {  	$value[] = "{$CONFIG->path}engine/tests/objects/sites.php";  	return $value;  } + +// Register with unit test +elgg_register_plugin_hook_handler('unit_test', 'system', 'sites_test'); diff --git a/engine/lib/statistics.php b/engine/lib/statistics.php index 7c170f3bb..e1f95ed97 100644 --- a/engine/lib/statistics.php +++ b/engine/lib/statistics.php @@ -95,14 +95,12 @@ function get_number_users($show_deactivated = false) {   * @return string    */  function get_online_users() { -	$offset = get_input('offset', 0);  	$count = find_active_users(600, 10, $offset, true);  	$objects = find_active_users(600, 10, $offset);  	if ($objects) {  		return elgg_view_entity_list($objects, array(  			'count' => $count, -			'offset' => $offset,  			'limit' => 10  		));  	} diff --git a/engine/lib/system_log.php b/engine/lib/system_log.php index fd5644135..28d90be56 100644 --- a/engine/lib/system_log.php +++ b/engine/lib/system_log.php @@ -11,6 +11,7 @@   * Retrieve the system log based on a number of parameters.   *   * @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.   * @param string    $class      The class of object it effects.   * @param string    $type       The type @@ -21,11 +22,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.   * @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) { +$limit = 10, $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $object_id = 0, +$ip_address = false) {  	global $CONFIG; @@ -37,16 +39,18 @@ $limit = 10, $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $obje  	} else {  		$by_user = (int)$by_user;  	} +	  	$event = sanitise_string($event);  	$class = sanitise_string($class);  	$type = sanitise_string($type);  	$subtype = sanitise_string($subtype); +	$ip_address = sanitise_string($ip_address);  	$limit = (int)$limit;  	$offset = (int)$offset;  	$where = array(); -	if ($by_user_orig !== "") { +	if ($by_user_orig !== "" && $by_user_orig !== false && $by_user_orig !== null) {  		if (is_int($by_user)) {  			$where[] = "performed_by_guid=$by_user";  		} else if (is_array($by_user)) { @@ -75,6 +79,9 @@ $limit = 10, $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $obje  	if ($object_id) {  		$where[] = "object_id = " . ((int) $object_id);  	} +	if ($ip_address) { +		$where[] = "ip_address = '$ip_address'"; +	}  	$select = "*";  	if ($count) { @@ -91,7 +98,8 @@ $limit = 10, $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $obje  	}  	if ($count) { -		if ($numrows = get_data_row($query)) { +		$numrows = get_data_row($query); +		if ($numrows) {  			return $numrows->count;  		}  	} else { @@ -171,6 +179,7 @@ function system_log($object, $event) {  		$object_subtype = $object->getSubtype();  		$event = sanitise_string($event);  		$time = time(); +		$ip_address = sanitise_string($_SERVER['REMOTE_ADDR']);  		$performed_by = elgg_get_logged_in_user_guid();  		if (isset($object->access_id)) { @@ -194,10 +203,10 @@ function system_log($object, $event) {  		if (!isset($log_cache[$time][$object_id][$event])) {  			$query = "INSERT DELAYED into {$CONFIG->dbprefix}system_log  				(object_id, object_class, object_type, object_subtype, event, -				performed_by_guid, owner_guid, access_id, enabled, time_created) +				performed_by_guid, owner_guid, access_id, enabled, time_created, ip_address)  			VALUES  				('$object_id','$object_class','$object_type', '$object_subtype', '$event', -				$performed_by, $owner_guid, $access_id, '$enabled', '$time')"; +				$performed_by, $owner_guid, $access_id, '$enabled', '$time', '$ip_address')";  			insert_data($query); diff --git a/engine/lib/upgrades/2011010101.php b/engine/lib/upgrades/2011010101.php index b063c249b..a1ee92622 100644 --- a/engine/lib/upgrades/2011010101.php +++ b/engine/lib/upgrades/2011010101.php @@ -66,7 +66,7 @@ if ($old_enabled_plugins) {  // invalidate caches  elgg_invalidate_simplecache(); -elgg_filepath_cache_reset(); +elgg_reset_system_cache();  // clean up.  remove_metadata($site->guid, 'pluginorder'); diff --git a/engine/lib/upgrades/2011030700-1.8_svn-blog_status_metadata-4645225d7b440876.php b/engine/lib/upgrades/2011030700-1.8_svn-blog_status_metadata-4645225d7b440876.php index e4ab9c137..fe2af9928 100644 --- a/engine/lib/upgrades/2011030700-1.8_svn-blog_status_metadata-4645225d7b440876.php +++ b/engine/lib/upgrades/2011030700-1.8_svn-blog_status_metadata-4645225d7b440876.php @@ -9,7 +9,8 @@  $ia = elgg_set_ignore_access(true);  $options = array(  	'type' => 'object', -	'subtype' => 'blog' +	'subtype' => 'blog', +	'limit' => 0,  );  $batch = new ElggBatch('elgg_get_entities', $options); diff --git a/engine/lib/upgrades/2011061200-1.8b1-sites_need_a_site_guid-6d9dcbf46c0826cc.php b/engine/lib/upgrades/2011061200-1.8b1-sites_need_a_site_guid-6d9dcbf46c0826cc.php index 4fc59ac41..41ab29998 100644 --- a/engine/lib/upgrades/2011061200-1.8b1-sites_need_a_site_guid-6d9dcbf46c0826cc.php +++ b/engine/lib/upgrades/2011061200-1.8b1-sites_need_a_site_guid-6d9dcbf46c0826cc.php @@ -16,6 +16,7 @@ access_show_hidden_entities(true);  $options = array(  	'type' => 'site',  	'site_guid' => 0, +	'limit' => 0,  );  $batch = new ElggBatch('elgg_get_entities', $options); diff --git a/engine/lib/upgrades/2011123100-1.8.2-fix_friend_river-b17e7ff8345c2269.php b/engine/lib/upgrades/2011123100-1.8.2-fix_friend_river-b17e7ff8345c2269.php new file mode 100644 index 000000000..4dc43cd32 --- /dev/null +++ b/engine/lib/upgrades/2011123100-1.8.2-fix_friend_river-b17e7ff8345c2269.php @@ -0,0 +1,12 @@ +<?php +/** + * Elgg 1.8.2 upgrade 2011123100 + * fix_friend_river + * + * Action type was incorrect due to previoud friends river upgrade + */ + +$query = "UPDATE {$CONFIG->dbprefix}river +			SET action_type='friend' +			WHERE view='river/relationship/friend/create' AND action_type='create'"; +update_data($query); diff --git a/engine/lib/upgrades/2011123101-1.8.2-fix_blog_status-b14c2a0e7b9e7d55.php b/engine/lib/upgrades/2011123101-1.8.2-fix_blog_status-b14c2a0e7b9e7d55.php new file mode 100644 index 000000000..e351c6ac9 --- /dev/null +++ b/engine/lib/upgrades/2011123101-1.8.2-fix_blog_status-b14c2a0e7b9e7d55.php @@ -0,0 +1,25 @@ +<?php +/** + * Elgg 1.8.2 upgrade 2011123101 + * fix_blog_status + * + * Most blog posts did not have their status properly set with 1.8 upgrade so we run + * the blog status upgrade again + */ + +$ia = elgg_set_ignore_access(true); +$options = array( +	'type' => 'object', +	'subtype' => 'blog', +	'limit' => 0, +); +$batch = new ElggBatch('elgg_get_entities', $options); + +foreach ($batch as $entity) { +	if (!$entity->status) { +		// create metadata owned by the original owner +		create_metadata($entity->getGUID(), 'status', 'published', '', $entity->owner_guid, +			$entity->access_id); +	} +} +elgg_set_ignore_access($ia);
\ No newline at end of file diff --git a/engine/lib/upgrades/2012012000-1.8.3-ip_in_syslog-87fe0f068cf62428.php b/engine/lib/upgrades/2012012000-1.8.3-ip_in_syslog-87fe0f068cf62428.php new file mode 100644 index 000000000..b9514e156 --- /dev/null +++ b/engine/lib/upgrades/2012012000-1.8.3-ip_in_syslog-87fe0f068cf62428.php @@ -0,0 +1,12 @@ +<?php +/** + * Elgg 1.8.3 upgrade 2012012000 + * ip_in_syslog + * + * Adds a field for an IP address in the system log table + */ + +$db_prefix = elgg_get_config('dbprefix'); +$q = "ALTER TABLE {$db_prefix}system_log ADD ip_address VARCHAR(15) NOT NULL AFTER time_created"; + +update_data($q);
\ No newline at end of file diff --git a/engine/lib/upgrades/2012012100-1.8.3-system_cache-93100e7d55a24a11.php b/engine/lib/upgrades/2012012100-1.8.3-system_cache-93100e7d55a24a11.php new file mode 100644 index 000000000..3a9aae2a1 --- /dev/null +++ b/engine/lib/upgrades/2012012100-1.8.3-system_cache-93100e7d55a24a11.php @@ -0,0 +1,13 @@ +<?php +/** + * Elgg 1.8.3 upgrade 2012012100 + * system_cache + * + * Convert viewpath cache to system cache + */ + +$value = datalist_get('viewpath_cache_enabled'); +datalist_set('system_cache_enabled', $value); + +$query = "DELETE FROM {$CONFIG->dbprefix}datalists WHERE name='viewpath_cache_enabled'"; +delete_data($query); diff --git a/engine/lib/users.php b/engine/lib/users.php index 1b3cca799..f1d42e25e 100644 --- a/engine/lib/users.php +++ b/engine/lib/users.php @@ -60,13 +60,12 @@ function create_user_entity($guid, $name, $username, $password, $salt, $email, $  	$row = get_entity_as_row($guid);  	if ($row) {  		// Exists and you have access to it -  		$query = "SELECT guid from {$CONFIG->dbprefix}users_entity where guid = {$guid}";  		if ($exists = get_data_row($query)) {  			$query = "UPDATE {$CONFIG->dbprefix}users_entity -				set name='$name', username='$username', password='$password', salt='$salt', -				email='$email', language='$language', code='$code', last_action = " -				. time() . " where guid = {$guid}"; +				SET name='$name', username='$username', password='$password', salt='$salt', +				email='$email', language='$language', code='$code' +				WHERE guid = $guid";  			$result = update_data($query);  			if ($result != false) { @@ -79,7 +78,7 @@ function create_user_entity($guid, $name, $username, $password, $salt, $email, $  				}  			}  		} else { -			// Update failed, attempt an insert. +			// Exists query failed, attempt an insert.  			$query = "INSERT into {$CONFIG->dbprefix}users_entity  				(guid, name, username, password, salt, email, language, code)  				values ($guid, '$name', '$username', '$password', '$salt', '$email', '$language', '$code')"; @@ -90,7 +89,7 @@ function create_user_entity($guid, $name, $username, $password, $salt, $email, $  				if (elgg_trigger_event('create', $entity->type, $entity)) {  					return $guid;  				} else { -					$entity->delete(); //delete_entity($guid); +					$entity->delete();  				}  			}  		} @@ -299,13 +298,14 @@ function get_user_sites($user_guid, $limit = 10, $offset = 0) {  	$offset = (int)$offset;  	return elgg_get_entities_from_relationship(array( +		'site_guids' => ELGG_ENTITIES_ANY_VALUE,  		'relationship' => 'member_of_site',  		'relationship_guid' => $user_guid,  		'inverse_relationship' => FALSE,  		'types' => 'site',  		'limit' => $limit, -		'offset' => $offset) -	); +		'offset' => $offset, +	));  }  /** @@ -497,20 +497,26 @@ $timelower = 0, $timeupper = 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 string The list in a form suitable to display + * @return string   */  function list_user_friends_objects($user_guid, $subtype = "", $limit = 10, $full_view = true,  $listtypetoggle = true, $pagination = true, $timelower = 0, $timeupper = 0) { -	$offset = (int) get_input('offset'); -	$limit = (int) $limit; -	$count = (int) count_user_friends_objects($user_guid, $subtype, $timelower, $timeupper); +	$offset = (int)get_input('offset'); +	$limit = (int)$limit; +	$count = (int)count_user_friends_objects($user_guid, $subtype, $timelower, $timeupper);  	$entities = get_user_friends_objects($user_guid, $subtype, $limit, $offset,  		$timelower, $timeupper); -	return elgg_view_entity_list($entities, $count, $offset, $limit, $full_view, -		$listtypetoggle, $pagination); +	return elgg_view_entity_list($entities, array( +		'count' => $count, +		'offset' => $offset, +		'limit' => $limit, +		'full_view' => $full_view, +		'list_type_toggle' => $listtypetoggle, +		'pagination' => $pagination, +	));  }  /** @@ -606,11 +612,11 @@ function get_user_by_code($code) {  }  /** - * Get an array of users from their email addresses + * Get an array of users from an email address   *   * @param string $email Email address.   * - * @return Array of users + * @return array   */  function get_user_by_email($email) {  	global $CONFIG; @@ -630,10 +636,10 @@ function get_user_by_email($email) {   * A function that returns a maximum of $limit users who have done something within the last   * $seconds seconds or the total count of active users.   * - * @param int $seconds Number of seconds (default 600 = 10min) - * @param int $limit   Limit, default 10. - * @param int $offset  Offset, default 0. - * @param bool $count  Count, default false. + * @param int  $seconds Number of seconds (default 600 = 10min) + * @param int  $limit   Limit, default 10. + * @param int  $offset  Offset, default 0. + * @param bool $count   Count, default false.   *   * @return mixed   */ @@ -952,6 +958,7 @@ $allow_multiple_emails = false, $friend_guid = 0, $invitecode = '') {  	$user->password = generate_user_password($user, $password);  	$user->owner_guid = 0; // Users aren't owned by anyone, even if they are admin created.  	$user->container_guid = 0; // Users aren't contained by anyone, even if they are admin created. +	$user->language = get_current_language();  	$user->save();  	// If $friend_guid has been set, make mutual friends @@ -1485,7 +1492,7 @@ function users_pagesetup() {  	if ($viewer) {  		elgg_register_menu_item('topbar', array(  			'name' => 'profile', -			'href' =>  $viewer->getURL(), +			'href' => $viewer->getURL(),  			'text' => elgg_view('output/img', array(  				'src' => $viewer->getIconURL('topbar'),  				'alt' => $viewer->name, @@ -1549,6 +1556,7 @@ function users_init() {  	elgg_register_action('friends/remove');  	elgg_register_action('avatar/upload');  	elgg_register_action('avatar/crop'); +	elgg_register_action('avatar/revert');  	elgg_register_action('profile/edit');  	elgg_register_action('friends/collections/add'); diff --git a/engine/lib/views.php b/engine/lib/views.php index b938dd60e..ca0ce7196 100644 --- a/engine/lib/views.php +++ b/engine/lib/views.php @@ -196,6 +196,37 @@ function elgg_does_viewtype_fallback($viewtype) {  	return FALSE;  } +/** + * Register a view to be available for ajax calls + * + * @param string $view The view name + * @return void + * @since 1.8.3 + */ +function elgg_register_ajax_view($view) { +	global $CONFIG; + +	if (!isset($CONFIG->allowed_ajax_views)) { +		$CONFIG->allowed_ajax_views = array(); +	} + +	$CONFIG->allowed_ajax_views[$view] = true; +} + +/** + * Unregister a view for ajax calls + *  + * @param string $view The view name + * @return void + * @since 1.8.3 + */ +function elgg_unregister_ajax_view($view) { +	global $CONFIG; + +	if (isset($CONFIG->allowed_ajax_views[$view])) { +		unset($CONFIG->allowed_ajax_views[$view]); +	} +}  /**   * Returns the file location for a view. @@ -415,7 +446,6 @@ function elgg_view($view, $vars = array(), $bypass = false, $debug = false, $vie  	if (isset($vars['internalname']) && !isset($vars['__ignoreInternalname']) && !isset($vars['name'])) {  		elgg_deprecated_notice('You should pass $vars[\'name\'] now instead of $vars[\'internalname\']', 1.8, 2);  		$vars['name'] = $vars['internalname']; -		$test=false;  	} elseif (isset($vars['name'])) {  		if (!isset($vars['internalname'])) {  			$vars['__ignoreInternalname'] = ''; @@ -530,7 +560,7 @@ function elgg_view($view, $vars = array(), $bypass = false, $debug = false, $vie   *   * @return void   * @since 1.7.0 - * @link http://docs.elgg.org/Views/Ejxtend + * @link http://docs.elgg.org/Views/Extend   * @example views/extend.php   */  function elgg_extend_view($view, $view_extension, $priority = 501, $viewtype = '') { @@ -939,12 +969,7 @@ function elgg_view_annotation(ElggAnnotation $annotation, array $vars = array(),  		return elgg_view($view, $vars, $bypass, $debug);  	} -	// @todo would be better to always make sure name is initialized properly  	$name = $annotation->name; -	$intname = (int) $name; -	if ("{$intname}" == "{$name}") { -		$name = get_metastring($intname); -	}  	if (empty($name)) {  		return false;  	} @@ -1300,21 +1325,18 @@ function elgg_view_form($action, $form_vars = array(), $body_vars = array()) {   * @access private   */  function elgg_view_list_item($item, array $vars = array()) { +	global $CONFIG; -	switch ($item->getType()) { -		case 'user': -		case 'object': -		case 'group': -		case 'site': -			return elgg_view_entity($item, $vars); -		case 'annotation': -			return elgg_view_annotation($item, $vars); -		case 'river': -			return elgg_view_river_item($item, $vars); -		default: -			return false; -			break; +	$type = $item->getType(); +	if (in_array($type, $CONFIG->entity_types)) { +		return elgg_view_entity($item, $vars); +	} else if ($type == 'annotation') { +		return elgg_view_annotation($item, $vars); +	} else if ($type == 'river') { +		return elgg_view_river_item($item, $vars);  	} + +	return false;  }  /** @@ -1611,6 +1633,8 @@ function elgg_views_boot() {  	elgg_register_css('elgg', $elgg_css_url);  	elgg_load_css('elgg'); +	elgg_register_ajax_view('js/languages'); +  	elgg_register_plugin_hook_handler('output:before', 'layout', 'elgg_views_add_rss_link');  	// discover the built-in view types @@ -1628,16 +1652,16 @@ function elgg_views_boot() {  	// set default icon sizes - can be overridden in settings.php or with plugin  	if (!elgg_get_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), -			'small' => array('w'=>40, 'h'=>40, 'square'=>TRUE, 'upscale'=>TRUE), -			'medium' => array('w'=>100, 'h'=>100, 'square'=>TRUE, 'upscale'=>TRUE), -			'large' => array('w'=>200, 'h'=>200, 'square'=>FALSE, 'upscale'=>FALSE), -			'master' => array('w'=>550, 'h'=>550, 'square'=>FALSE, 'upscale'=>FALSE), +			'topbar' => array('w' => 16, 'h' => 16, 'square' => TRUE, 'upscale' => TRUE), +			'tiny' => array('w' => 25, 'h' => 25, 'square' => TRUE, 'upscale' => TRUE), +			'small' => array('w' => 40, 'h' => 40, 'square' => TRUE, 'upscale' => TRUE), +			'medium' => array('w' => 100, 'h' => 100, 'square' => TRUE, 'upscale' => TRUE), +			'large' => array('w' => 200, 'h' => 200, 'square' => FALSE, 'upscale' => FALSE), +			'master' => array('w' => 550, 'h' => 550, 'square' => FALSE, 'upscale' => FALSE),  		);  		elgg_set_config('icon_sizes', $icon_sizes);  	}  } -elgg_register_event_handler('boot', 'system', 'elgg_views_boot', 1000); +elgg_register_event_handler('boot', 'system', 'elgg_views_boot');  elgg_register_event_handler('init', 'system', 'elgg_views_handle_deprecated_views'); diff --git a/engine/lib/web_services.php b/engine/lib/web_services.php index 1c77b757e..07be76ec6 100644 --- a/engine/lib/web_services.php +++ b/engine/lib/web_services.php @@ -1165,7 +1165,7 @@ function list_all_apis() {   * @access private   */  function auth_gettoken($username, $password) { -	if (authenticate($username, $password)) { +	if (elgg_authenticate($username, $password)) {  		$token = create_user_token($username);  		if ($token) {  			return $token; diff --git a/engine/lib/widgets.php b/engine/lib/widgets.php index 46f34391a..d73dd6330 100644 --- a/engine/lib/widgets.php +++ b/engine/lib/widgets.php @@ -316,7 +316,12 @@ function elgg_default_widgets_init() {  		// override permissions for creating widget on logged out / just created entities  		elgg_register_plugin_hook_handler('container_permissions_check', 'object', 'elgg_default_widgets_permissions_override'); +		// only register the callback once per event +		$events = array();  		foreach ($default_widgets as $info) { +			$events[$info['event'] . ',' . $info['entity_type']] = $info; +		} +		foreach ($events as $info) {  			elgg_register_event_handler($info['event'], $info['entity_type'], 'elgg_create_default_widgets');  		}  	} diff --git a/engine/schema/mysql.sql b/engine/schema/mysql.sql index 74cf2ce74..6c6e9db89 100644 --- a/engine/schema/mysql.sql +++ b/engine/schema/mysql.sql @@ -361,6 +361,7 @@ CREATE TABLE `prefix_system_log` (    `access_id` int(11) NOT NULL,    `enabled` enum('yes','no') NOT NULL DEFAULT 'yes',    `time_created` int(11) NOT NULL, +  `ip_address` varchar(15) NOT NULL,    PRIMARY KEY (`id`),    KEY `object_id` (`object_id`),    KEY `object_class` (`object_class`), diff --git a/engine/settings.example.php b/engine/settings.example.php index 011770f89..3b139d710 100644 --- a/engine/settings.example.php +++ b/engine/settings.example.php @@ -107,7 +107,7 @@ $CONFIG->broken_mta = FALSE;   *   * Elgg stores each query and its results in a query cache.   * On large sites or long-running scripts, this cache can grow to be - * large.  To disable query caching, set this to FALSE. + * large.  To disable query caching, set this to TRUE.   *   * @global bool $CONFIG->db_disable_query_cache   */ diff --git a/engine/start.php b/engine/start.php index 00bdc3197..506e27380 100644 --- a/engine/start.php +++ b/engine/start.php @@ -1,12 +1,12 @@  <?php  /** - * Bootstraps and starts the Elgg engine. + * Bootstraps the Elgg engine.   *   * This file loads the full Elgg engine, checks the installation - * state, then emits a series of events to finish booting Elgg: + * state, and triggers a series of events to finish booting Elgg:   * 	- {@elgg_event boot system} - * 	- {@elgg_event plugins_boot system}   * 	- {@elgg_event init system} + * 	- {@elgg_event ready system}   *   * If Elgg is fully uninstalled, the browser will be redirected to an   * installation page. @@ -36,13 +36,12 @@ $START_MICROTIME = microtime(true);   * Configuration values.   *   * The $CONFIG global contains configuration values required - * for running Elgg as defined in the settings.php file.  The following - * array keys are defined by core Elgg: + * for running Elgg as defined in the settings.php file.   * - * Plugin authors are encouraged to use get_config() instead of accessing the - * global directly. + * Plugin authors are encouraged to use elgg_get_config() instead of accessing + * the global directly.   * - * @see get_config() + * @see elgg_get_config()   * @see engine/settings.php   * @global stdClass $CONFIG   */ @@ -53,56 +52,35 @@ if (!isset($CONFIG)) {  $lib_dir = dirname(__FILE__) . '/lib/'; -/** - * The minimum required libs to bootstrap an Elgg installation. - * - * @var array - */ -$required_files = array( -	'elgglib.php', 'views.php', 'access.php', 'system_log.php', 'export.php', -	'sessions.php', 'languages.php', 'pageowner.php', 'input.php', 'cache.php', -	'output.php' -); - -// include bootstraping libs -foreach ($required_files as $file) { -	$path = $lib_dir . $file; -	if (!include($path)) { -		echo "Could not load file '$path'. " -		. 'Please check your Elgg installation for all required files.'; -		exit; -	} +// Load the bootstrapping library +$path = $lib_dir . 'elgglib.php'; +if (!include_once($path)) { +	echo "Could not load file '$path'. Please check your Elgg installation for all required files."; +	exit;  } -// Register the error handler -set_error_handler('_elgg_php_error_handler'); -set_exception_handler('_elgg_php_exception_handler'); - -/** - * Load the system settings - */ +// Load the system settings  if (!include_once(dirname(__FILE__) . "/settings.php")) { -	$msg = elgg_echo('InstallationException:CannotLoadSettings'); +	$msg = 'Elgg could not load the settings file. It does not exist or there is a file permissions issue.';  	throw new InstallationException($msg);  }  // load the rest of the library files from engine/lib/  $lib_files = array( -	// these need to be loaded first. -	'database.php', 'actions.php', - -	'admin.php', 'annotations.php', 'calendar.php', -	'configuration.php', 'cron.php', 'entities.php', 'export.php', -	'extender.php', 'filestore.php', 'group.php',  -	'location.php', 'mb_wrapper.php', 'memcache.php', 'metadata.php', -	'metastrings.php', 'navigation.php', 'notification.php', 'objects.php', -	'opendd.php', 'pagehandler.php', 'pam.php', 'plugins.php', -	'private_settings.php', 'relationships.php', 'river.php', 'sites.php', -	'statistics.php', 'tags.php', 'user_settings.php', 'users.php', -	'upgrade.php', 'web_services.php', 'widgets.php', 'xml.php', 'xml-rpc.php', +	'access.php', 'actions.php', 'admin.php', 'annotations.php', 'cache.php', +	'calendar.php', 'configuration.php', 'cron.php', 'database.php', +	'entities.php', 'export.php', 'extender.php', 'filestore.php', 'group.php', +	'input.php', 'languages.php', 'location.php', 'mb_wrapper.php', +	'memcache.php', 'metadata.php', 'metastrings.php', 'navigation.php', +	'notification.php', 'objects.php', 'opendd.php', 'output.php', +	'pagehandler.php', 'pageowner.php', 'pam.php', 'plugins.php', +	'private_settings.php', 'relationships.php', 'river.php', 'sessions.php', +	'sites.php', 'statistics.php', 'system_log.php', 'tags.php', +	'user_settings.php', 'users.php', 'upgrade.php', 'views.php', +	'web_services.php', 'widgets.php', 'xml.php', 'xml-rpc.php', -	//backwards compatibility +	// backward compatibility  	'deprecated-1.7.php', 'deprecated-1.8.php',  ); @@ -110,48 +88,22 @@ foreach ($lib_files as $file) {  	$file = $lib_dir . $file;  	elgg_log("Loading $file...");  	if (!include_once($file)) { -		$msg = sprintf(elgg_echo('InstallationException:MissingLibrary'), $file); +		$msg = "Could not load $file";  		throw new InstallationException($msg);  	}  } -// connect to db -setup_db_connections(); - -// confirm that the installation completed successfully -verify_installation(); - -// Autodetect some default configuration settings -set_default_config(); - -// needs to be set for links in html head -$viewtype = get_input('view', 'default'); -$lastcached = datalist_get("simplecache_lastcached_$viewtype"); -$CONFIG->lastcache = $lastcached; - -// Trigger boot events for core. Plugins can't hook -// into this because they haven't been loaded yet. +// Connect to database, load language files, load configuration, init session +// Plugins can't use this event because they haven't been loaded yet.  elgg_trigger_event('boot', 'system');  // Load the plugins that are active  elgg_load_plugins(); +// @todo deprecate as plugins can use 'init', 'system' event  elgg_trigger_event('plugins_boot', 'system'); -// Trigger system init event for plugins +// Complete the boot process for both engine and plugins  elgg_trigger_event('init', 'system'); -// Regenerate the simple cache if expired. -// Don't do it on upgrade because upgrade does it itself. -// @todo - move into function and perhaps run off init system event -if (!defined('UPGRADING')) { -	$lastupdate = datalist_get("simplecache_lastupdate_$viewtype"); -	$lastcached = datalist_get("simplecache_lastcached_$viewtype"); -	if ($lastupdate == 0 || $lastcached < $lastupdate) { -		elgg_regenerate_simplecache($viewtype); -		$lastcached = datalist_get("simplecache_lastcached_$viewtype"); -	} -	$CONFIG->lastcache = $lastcached; -} -  // System loaded and ready  elgg_trigger_event('ready', 'system'); diff --git a/engine/tests/api/annotations.php b/engine/tests/api/annotations.php index d7551a0fa..947292970 100644 --- a/engine/tests/api/annotations.php +++ b/engine/tests/api/annotations.php @@ -43,4 +43,28 @@ class ElggCoreAnnotationAPITest extends ElggCoreUnitTest {  		$this->object->delete();  	} + +	public function testElggDeleteAnnotations() { +		$e = new ElggObject(); +		$e->save(); + +		for ($i=0; $i<30; $i++) { +			$e->annotate('test_annotation', rand(0,10000)); +		} + +		$options = array( +			'guid' => $e->getGUID(), +			'limit' => 0 +		); + +		$annotations = elgg_get_annotations($options); +		$this->assertIdentical(30, count($annotations)); + +		$this->assertTrue(elgg_delete_annotations($options)); + +		$annotations = elgg_get_annotations($options); +		$this->assertTrue(empty($annotations)); + +		$this->assertTrue($e->delete()); +	}  } diff --git a/engine/tests/api/helpers.php b/engine/tests/api/helpers.php index 77205138d..62e4471e0 100644 --- a/engine/tests/api/helpers.php +++ b/engine/tests/api/helpers.php @@ -518,4 +518,87 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest {  		$this->assertIdentical($elements_sorted_string, $test_elements);  	} + +	// see http://trac.elgg.org/ticket/4288 +	public function testElggBatchIncOffset() { +		// normal increment +		$options = array( +			'offset' => 0, +			'limit' => 11 +		); +		$batch = new ElggBatch(array('ElggCoreHelpersTest', 'elgg_batch_callback_test'), $options, +				null, 5); +		$j = 0; +		foreach ($batch as $e) { +			$offset = floor($j / 5) * 5; +			$this->assertEqual($offset, $e['offset']); +			$this->assertEqual($j + 1, $e['index']); +			$j++; +		} + +		$this->assertEqual(11, $j); + +		// no increment, 0 start +		ElggCoreHelpersTest::elgg_batch_callback_test(array(), true); +		$options = array( +			'offset' => 0, +			'limit' => 11 +		); +		$batch = new ElggBatch(array('ElggCoreHelpersTest', 'elgg_batch_callback_test'), $options, +				null, 5); +		$batch->setIncrementOffset(false); + +		$j = 0; +		foreach ($batch as $e) { +			$this->assertEqual(0, $e['offset']); +			// should always be the same 5 +			$this->assertEqual($e['index'], $j + 1 - (floor($j / 5) * 5)); +			$j++; +		} +		$this->assertEqual(11, $j); + +		// no increment, 3 start +		ElggCoreHelpersTest::elgg_batch_callback_test(array(), true); +		$options = array( +			'offset' => 3, +			'limit' => 11 +		); +		$batch = new ElggBatch(array('ElggCoreHelpersTest', 'elgg_batch_callback_test'), $options, +				null, 5); +		$batch->setIncrementOffset(false); + +		$j = 0; +		foreach ($batch as $e) { +			$this->assertEqual(3, $e['offset']); +			// same 5 results +			$this->assertEqual($e['index'], $j + 4 - (floor($j / 5) * 5)); +			$j++; +		} + +		$this->assertEqual(11, $j); +	} + +	static function elgg_batch_callback_test($options, $reset = false) { +		static $count = 1; + +		if ($reset) { +			$count = 1; +			return true; +		} + +		if ($count > 20) { +			return false; +		} + +		for ($j = 0; ($options['limit'] < 5) ? $j < $options['limit'] : $j < 5; $j++) { +			$return[] = array( +				'offset' => $options['offset'], +				'limit' => $options['limit'], +				'count' => $count++, +				'index' => 1 + $options['offset'] + $j +			); +		} + +		return $return; +	}  }
\ No newline at end of file diff --git a/engine/tests/api/metadata.php b/engine/tests/api/metadata.php index f5b615ca8..be8ac269c 100644 --- a/engine/tests/api/metadata.php +++ b/engine/tests/api/metadata.php @@ -99,6 +99,31 @@ class ElggCoreMetadataAPITest extends ElggCoreUnitTest {  		$this->object->delete();  	} +	public function testElggDeleteMetadata() { +		$e = new ElggObject(); +		$e->save(); + +		for ($i=0; $i<30; $i++) { +			$name = "test_metadata" . rand(0, 10000); +			$e->$name = rand(0, 10000); +		} + +		$options = array( +			'guid' => $e->getGUID(), +			'limit' => 0 +		); + +		$md = elgg_get_metadata($options); +		$this->assertIdentical(30, count($md)); + +		$this->assertTrue(elgg_delete_metadata($options)); + +		$md = elgg_get_metadata($options); +		$this->assertTrue(empty($md)); + +		$e->delete(); +	} +  	protected function create_metastring($string) {  		global $CONFIG, $METASTRINGS_CACHE, $METASTRINGS_DEADNAME_CACHE; diff --git a/engine/tests/api/metastrings.php b/engine/tests/api/metastrings.php index a96388217..0a8945084 100644 --- a/engine/tests/api/metastrings.php +++ b/engine/tests/api/metastrings.php @@ -132,7 +132,7 @@ class ElggCoreMetastringsTest extends ElggCoreUnitTest {  	public function testKeepMeFromDeletingEverything() {  		foreach ($this->metastringTypes as $type) {  			$required = array( -				'guid', 'guids', 'limit' +				'guid', 'guids'  			);  			switch ($type) { @@ -160,6 +160,10 @@ class ElggCoreMetastringsTest extends ElggCoreUnitTest {  			$options = array();  			$this->assertFalse(elgg_is_valid_options_for_batch_operation($options, $type)); +			// limit alone isn't valid: +			$options = array('limit' => 10); +			$this->assertFalse(elgg_is_valid_options_for_batch_operation($options, $type)); +  			foreach ($required as $key) {  				$options = array(); diff --git a/engine/tests/objects/entities.php b/engine/tests/objects/entities.php index 1772f7c1a..a4dc7946c 100644 --- a/engine/tests/objects/entities.php +++ b/engine/tests/objects/entities.php @@ -226,6 +226,39 @@ class ElggCoreEntityTest extends ElggCoreUnitTest {  		$this->assertTrue($this->entity->delete());  	} +	public function testElggEntityRecursiveDisableAndEnable() { +		global $CONFIG; + +		$this->save_entity(); +		$obj1 = new ElggObject(); +		$obj1->container_guid = $this->entity->getGUID(); +		$obj1->save(); +		$obj2 = new ElggObject(); +		$obj2->container_guid = $this->entity->getGUID(); +		$obj2->save(); + +		// disable $obj2 before disabling the container +		$this->assertTrue($obj2->disable()); + +		// disable entities container by $this->entity +		$this->assertTrue($this->entity->disable()); +		$entity = get_data_row("SELECT * FROM {$CONFIG->dbprefix}entities WHERE guid = '{$obj1->guid}'"); +		$this->assertIdentical($entity->enabled, 'no'); + +		// enable entities that were disabled with the container (but not $obj2) +		$this->assertTrue($this->entity->enable()); +		$entity = get_data_row("SELECT * FROM {$CONFIG->dbprefix}entities WHERE guid = '{$obj1->guid}'"); +		$this->assertIdentical($entity->enabled, 'yes'); +		$entity = get_data_row("SELECT * FROM {$CONFIG->dbprefix}entities WHERE guid = '{$obj2->guid}'"); +		$this->assertIdentical($entity->enabled, 'no'); + +		// cleanup +		$this->assertTrue($obj2->enable()); +		$this->assertTrue($obj2->delete()); +		$this->assertTrue($obj1->delete()); +		$this->assertTrue($this->entity->delete()); +	} +  	public function testElggEntityMetadata() {  		// let's delete a non-existent metadata  		$this->assertFalse($this->entity->deleteMetadata('important')); diff --git a/engine/tests/objects/objects.php b/engine/tests/objects/objects.php index 0d0df6b75..915594e0a 100644 --- a/engine/tests/objects/objects.php +++ b/engine/tests/objects/objects.php @@ -194,7 +194,99 @@ class ElggCoreObjectTest extends ElggCoreUnitTest {  		$old = elgg_set_ignore_access(true);  	} +	// see http://trac.elgg.org/ticket/1196 +	public function testElggEntityRecursiveDisableWhenLoggedOut() { +		$e1 = new ElggObject(); +		$e1->access_id = ACCESS_PUBLIC; +		$e1->owner_guid = 0; +		$e1->container_guid = 0; +		$e1->save(); +		$guid1 = $e1->getGUID(); + +		$e2 = new ElggObject(); +		$e2->container_guid = $guid1; +		$e2->access_id = ACCESS_PUBLIC; +		$e2->owner_guid = 0; +		$e2->save(); +		$guid2 = $e2->getGUID(); + +		// fake being logged out +		$user = $_SESSION['user']; +		unset($_SESSION['user']); +		$ia = elgg_set_ignore_access(true); + +		$this->assertTrue(disable_entity($guid1, null, true)); + +		// "log in" original user +		$_SESSION['user'] = $user; +		elgg_set_ignore_access($ia); + +		$this->assertFalse(get_entity($guid1)); +		$this->assertFalse(get_entity($guid2)); + +		$db_prefix = get_config('dbprefix'); +		$q = "SELECT * FROM {$db_prefix}entities WHERE guid = $guid1"; +		$r = get_data_row($q); +		$this->assertEqual('no', $r->enabled); + +		$q = "SELECT * FROM {$db_prefix}entities WHERE guid = $guid2"; +		$r = get_data_row($q); +		$this->assertEqual('no', $r->enabled); + +		access_show_hidden_entities(true); +		delete_entity($guid1); +		delete_entity($guid2); +		access_show_hidden_entities(false); +	} + +	public function testElggRecursiveDelete() { +		$types = array('ElggGroup', 'ElggObject', 'ElggUser', 'ElggSite'); +		$db_prefix = elgg_get_config('dbprefix'); + +		foreach ($types as $type) { +			$parent = new $type(); +			$this->assertTrue($parent->save()); +			 +			$child = new ElggObject(); +			$child->container_guid = $parent->guid; +			$this->assertTrue($child->save()); + +			$grandchild = new ElggObject(); +			$grandchild->container_guid = $child->guid; +			$this->assertTrue($grandchild->save()); + +			$this->assertTrue($parent->delete(true)); + +			$q = "SELECT * FROM {$db_prefix}entities WHERE guid = $parent->guid"; +			$r = get_data($q); +			$this->assertFalse($r); + +			$q = "SELECT * FROM {$db_prefix}entities WHERE guid = $child->guid"; +			$r = get_data($q); +			$this->assertFalse($r); +			$q = "SELECT * FROM {$db_prefix}entities WHERE guid = $grandchild->guid"; +			$r = get_data($q); +			$this->assertFalse($r); +		} + +		// object that owns itself +		// can't check container_guid because of infinite loops in can_edit_entity() +		$obj = new ElggObject(); +		$obj->save(); +		$obj->owner_guid = $obj->guid; +		$obj->save(); + +		$q = "SELECT * FROM {$db_prefix}entities WHERE guid = $obj->guid"; +		$r = get_data_row($q); +		$this->assertEqual($obj->guid, $r->owner_guid); + +		$this->assertTrue($obj->delete(true)); + +		$q = "SELECT * FROM {$db_prefix}entities WHERE guid = $obj->guid"; +		$r = get_data_row($q); +		$this->assertFalse($r); +	}  	protected function get_object_row($guid) {  		global $CONFIG;  | 
