diff options
Diffstat (limited to 'engine')
26 files changed, 358 insertions, 174 deletions
diff --git a/engine/classes/ElggBatch.php b/engine/classes/ElggBatch.php index 5d59425d0..eb93b0f5d 100644 --- a/engine/classes/ElggBatch.php +++ b/engine/classes/ElggBatch.php @@ -227,11 +227,6 @@ class ElggBatch  	 * @return bool  	 */  	private function getNextResultsChunk() { -		// reset memory caches after first chunk load -		if ($this->chunkIndex > 0) { -			global $DB_QUERY_CACHE, $ENTITY_CACHE; -			$DB_QUERY_CACHE = $ENTITY_CACHE = array(); -		}  		// always reset results.  		$this->results = array(); diff --git a/engine/classes/ElggEntity.php b/engine/classes/ElggEntity.php index 5a63c7b15..8b3ceb551 100644 --- a/engine/classes/ElggEntity.php +++ b/engine/classes/ElggEntity.php @@ -1270,7 +1270,7 @@ abstract class ElggEntity extends ElggData implements  	public function save() {  		$guid = $this->getGUID();  		if ($guid > 0) { -			cache_entity($this); +			_elgg_cache_entity($this);  			return update_entity(  				$guid, @@ -1320,7 +1320,7 @@ abstract class ElggEntity extends ElggData implements  			$this->attributes['subtype'] = get_subtype_id($this->attributes['type'],  				$this->attributes['subtype']); -			cache_entity($this); +			_elgg_cache_entity($this);  			return $this->attributes['guid'];  		} @@ -1362,7 +1362,7 @@ abstract class ElggEntity extends ElggData implements  			// Cache object handle  			if ($this->attributes['guid']) { -				cache_entity($this); +				_elgg_cache_entity($this);  			}  			return true; diff --git a/engine/classes/ElggGroup.php b/engine/classes/ElggGroup.php index 7ab0bfa48..61f9163d5 100644 --- a/engine/classes/ElggGroup.php +++ b/engine/classes/ElggGroup.php @@ -335,7 +335,7 @@ class ElggGroup extends ElggEntity  		$this->attributes = $attrs;  		$this->attributes['tables_loaded'] = 2; -		cache_entity($this); +		_elgg_cache_entity($this);  		return true;  	} diff --git a/engine/classes/ElggLRUCache.php b/engine/classes/ElggLRUCache.php new file mode 100644 index 000000000..f51af2ed7 --- /dev/null +++ b/engine/classes/ElggLRUCache.php @@ -0,0 +1,181 @@ +<?php + +/** + * Least Recently Used Cache + * + * A fixed sized cache that removes the element used last when it reaches its + * size limit. + *  + * Based on https://github.com/cash/LRUCache + *  + * @access private + *  + * @package    Elgg.Core + * @subpackage Cache + */ +class ElggLRUCache implements ArrayAccess { +	/** @var int */ +	protected $maximumSize; + +	/** +	 * The front of the array contains the LRU element +	 * +	 * @var array +	 */ +	protected $data = array(); + +	/** +	 * Create a LRU Cache +	 * +	 * @param int $size The size of the cache +	 * @throws InvalidArgumentException +	 */ +	public function __construct($size) { +		if (!is_int($size) || $size <= 0) { +			throw new InvalidArgumentException(); +		} +		$this->maximumSize = $size; +	} + +	/** +	 * Get the value cached with this key +	 * +	 * @param int|string $key     The key. Strings that are ints are cast to ints. +	 * @param mixed      $default The value to be returned if key not found. (Optional) +	 * @return mixed +	 */ +	public function get($key, $default = null) { +		if (isset($this->data[$key])) { +			$this->recordAccess($key); +			return $this->data[$key]; +		} else { +			return $default; +		} +	} + +	/** +	 * Add something to the cache +	 * +	 * @param int|string $key   The key. Strings that are ints are cast to ints. +	 * @param mixed      $value The value to cache +	 * @return void +	 */ +	public function set($key, $value) { +		if (isset($this->data[$key])) { +			$this->data[$key] = $value; +			$this->recordAccess($key); +		} else { +			$this->data[$key] = $value; +			if ($this->size() > $this->maximumSize) { +				// remove least recently used element (front of array) +				reset($this->data); +				unset($this->data[key($this->data)]); +			} +		} +	} + +	/** +	 * Get the number of elements in the cache +	 * +	 * @return int +	 */ +	public function size() { +		return count($this->data); +	} + +	/** +	 * Does the cache contain an element with this key +	 * +	 * @param int|string $key The key +	 * @return boolean +	 */ +	public function containsKey($key) { +		return isset($this->data[$key]); +	} + +	/** +	 * Remove the element with this key. +	 * +	 * @param int|string $key The key +	 * @return mixed Value or null if not set +	 */ +	public function remove($key) { +		if (isset($this->data[$key])) { +			$value = $this->data[$key]; +			unset($this->data[$key]); +			return $value; +		} else { +			return null; +		} +	} + +	/** +	 * Clear the cache +	 *  +	 * @return void +	 */ +	public function clear() { +		$this->data = array(); +	} + +	/** +	 * Moves the element from current position to end of array +	 *  +	 * @param int|string $key The key +	 * @return void +	 */ +	protected function recordAccess($key) { +		$value = $this->data[$key]; +		unset($this->data[$key]); +		$this->data[$key] = $value; +	} + +	/** +	 * Assigns a value for the specified key +	 * +	 * @see ArrayAccess::offsetSet() +	 * +	 * @param int|string $key   The key to assign the value to. +	 * @param mixed      $value The value to set. +	 * @return void +	 */ +	public function offsetSet($key, $value) { +		$this->set($key, $value); +	} + +	/** +	 * Get the value for specified key +	 * +	 * @see ArrayAccess::offsetGet() +	 * +	 * @param int|string $key The key to retrieve. +	 * @return mixed +	 */ +	public function offsetGet($key) { +		return $this->get($key); +	} + +	/** +	 * Unsets a key. +	 * +	 * @see ArrayAccess::offsetUnset() +	 * +	 * @param int|string $key The key to unset. +	 * @return void +	 */ +	public function offsetUnset($key) { +		$this->remove($key); +	} + +	/** +	 * Does key exist? +	 * +	 * @see ArrayAccess::offsetExists() +	 * +	 * @param int|string $key A key to check for. +	 * @return boolean +	 */ +	public function offsetExists($key) { +		return $this->containsKey($key); +	} +} diff --git a/engine/classes/ElggObject.php b/engine/classes/ElggObject.php index 3cb76ffaf..d54752dca 100644 --- a/engine/classes/ElggObject.php +++ b/engine/classes/ElggObject.php @@ -107,7 +107,7 @@ class ElggObject extends ElggEntity {  		$this->attributes = $attrs;  		$this->attributes['tables_loaded'] = 2; -		cache_entity($this); +		_elgg_cache_entity($this);  		return true;  	} diff --git a/engine/classes/ElggSite.php b/engine/classes/ElggSite.php index deba5087e..dd996fe98 100644 --- a/engine/classes/ElggSite.php +++ b/engine/classes/ElggSite.php @@ -124,7 +124,7 @@ class ElggSite extends ElggEntity {  		$this->attributes = $attrs;  		$this->attributes['tables_loaded'] = 2; -		cache_entity($this); +		_elgg_cache_entity($this);  		return true;  	} diff --git a/engine/classes/ElggStaticVariableCache.php b/engine/classes/ElggStaticVariableCache.php index 17d849400..9c14fdfba 100644 --- a/engine/classes/ElggStaticVariableCache.php +++ b/engine/classes/ElggStaticVariableCache.php @@ -11,7 +11,7 @@ class ElggStaticVariableCache extends ElggSharedMemoryCache {  	/**  	 * The cache.  	 * -	 * @var unknown_type +	 * @var array  	 */  	private static $__cache; @@ -22,7 +22,7 @@ class ElggStaticVariableCache extends ElggSharedMemoryCache {  	 * memory, optionally with a given namespace (to avoid overlap).  	 *  	 * @param string $namespace The namespace for this cache to write to. -	 * @note namespaces of the same name are shared! +	 * @warning namespaces of the same name are shared!  	 */  	function __construct($namespace = 'default') {  		$this->setNamespace($namespace); @@ -80,7 +80,7 @@ class ElggStaticVariableCache extends ElggSharedMemoryCache {  	}  	/** -	 * This was probably meant to delete everything? +	 * Clears the cache for a particular namespace  	 *  	 * @return void  	 */ diff --git a/engine/classes/ElggTranslit.php b/engine/classes/ElggTranslit.php index 601965c11..4ae1d2479 100644 --- a/engine/classes/ElggTranslit.php +++ b/engine/classes/ElggTranslit.php @@ -49,10 +49,19 @@ class ElggTranslit {  		// Internationalization, AND 日本語!  		$string = self::transliterateAscii($string); -		// more translation +		// allow HTML tags in titles +		$string = preg_replace('~<([a-zA-Z][^>]*)>~', ' $1 ', $string); + +		// more substitutions +		// @todo put these somewhere else  		$string = strtr($string, array( -			// Euro/GBP -			"\xE2\x82\xAC" /* € */ => 'E', "\xC2\xA3" /* £ */ => 'GBP', +			// currency +			"\xE2\x82\xAC" /* € */ => ' E ', +			"\xC2\xA3" /* £ */ => ' GBP ', +			 +			"&" => ' and ', +			">" => ' greater than ', +			"<" => ' less than ',  		));  		// remove all ASCII except 0-9a-zA-Z, hyphen, underscore, and whitespace diff --git a/engine/classes/ElggUser.php b/engine/classes/ElggUser.php index b80065b27..6d9f10b57 100644 --- a/engine/classes/ElggUser.php +++ b/engine/classes/ElggUser.php @@ -112,7 +112,7 @@ class ElggUser extends ElggEntity  		$this->attributes = $attrs;  		$this->attributes['tables_loaded'] = 2; -		cache_entity($this); +		_elgg_cache_entity($this);  		return true;  	} diff --git a/engine/lib/actions.php b/engine/lib/actions.php index f78ca63df..56936f582 100644 --- a/engine/lib/actions.php +++ b/engine/lib/actions.php @@ -74,8 +74,7 @@ function action($action, $forwarder = "") {  	);  	if (!in_array($action, $exceptions)) { -		// All actions require a token. -		action_gatekeeper(); +		action_gatekeeper($action);  	}  	$forwarder = str_replace(elgg_get_site_url(), "", $forwarder); @@ -188,6 +187,26 @@ function elgg_unregister_action($action) {  }  /** + * Is the token timestamp within acceptable range? + *  + * @param int $ts timestamp from the CSRF token + *  + * @return bool + */ +function _elgg_validate_token_timestamp($ts) { +	$action_token_timeout = elgg_get_config('action_token_timeout'); +	// default is 2 hours +	$timeout = ($action_token_timeout !== null) ? $action_token_timeout : 2; + +	$hour = 60 * 60; +	$timeout = $timeout * $hour; +	$now = time(); + +	// Validate time to ensure its not crazy +	return ($timeout == 0 || ($ts > $now - $timeout) && ($ts < $now + $timeout)); +} + +/**   * Validate an action token.   *   * Calls to actions will automatically validate tokens. If tokens are not @@ -205,8 +224,6 @@ function elgg_unregister_action($action) {   * @access private   */  function validate_action_token($visibleerrors = TRUE, $token = NULL, $ts = NULL) { -	global $CONFIG; -  	if (!$token) {  		$token = get_input('__elgg_token');  	} @@ -215,29 +232,18 @@ function validate_action_token($visibleerrors = TRUE, $token = NULL, $ts = NULL)  		$ts = get_input('__elgg_ts');  	} -	if (!isset($CONFIG->action_token_timeout)) { -		// default to 2 hours -		$timeout = 2; -	} else { -		$timeout = $CONFIG->action_token_timeout; -	} -  	$session_id = session_id();  	if (($token) && ($ts) && ($session_id)) {  		// generate token, check with input and forward if invalid -		$generated_token = generate_action_token($ts); +		$required_token = generate_action_token($ts);  		// Validate token -		if ($token == $generated_token) { -			$hour = 60 * 60; -			$timeout = $timeout * $hour; -			$now = time(); - -			// Validate time to ensure its not crazy -			if ($timeout == 0 || ($ts > $now - $timeout) && ($ts < $now + $timeout)) { +		if ($token == $required_token) { +			 +			if (_elgg_validate_token_timestamp($ts)) {  				// We have already got this far, so unless anything -				// else says something to the contry we assume we're ok +				// else says something to the contrary we assume we're ok  				$returnval = true;  				$returnval = elgg_trigger_plugin_hook('action_gatekeeper:permissions:check', 'all', array( @@ -293,12 +299,33 @@ function validate_action_token($visibleerrors = TRUE, $token = NULL, $ts = NULL)   * This function verifies form input for security features (like a generated token),   * and forwards if they are invalid.   * + * @param string $action The action being performed + *    * @return mixed True if valid or redirects.   * @access private   */ -function action_gatekeeper() { -	if (validate_action_token()) { -		return TRUE; +function action_gatekeeper($action) { +	if ($action === 'login') { +		if (validate_action_token(false)) { +			return true; +		} +		 +		$token = get_input('__elgg_token'); +		$ts = (int)get_input('__elgg_ts'); +		if ($token && _elgg_validate_token_timestamp($ts)) { +			// The tokens are present and the time looks valid: this is probably a mismatch due to the  +			// login form being on a different domain. +			register_error(elgg_echo('actiongatekeeper:crosssitelogin')); +			 +			 +			forward('login', 'csrf'); +		} +		 +		// let the validator send an appropriate msg +		validate_action_token(); +		 +	} elseif (validate_action_token()) { +		return true;  	}  	forward(REFERER, 'csrf'); diff --git a/engine/lib/database.php b/engine/lib/database.php index 2b348366d..3553d787d 100644 --- a/engine/lib/database.php +++ b/engine/lib/database.php @@ -12,17 +12,19 @@  /**   * Query cache for all queries.   * - * Each query and its results are stored in this array as: + * Each query and its results are stored in this cache as:   * <code> - * $DB_QUERY_CACHE[$query] => array(result1, result2, ... resultN) + * $DB_QUERY_CACHE[query hash] => array(result1, result2, ... resultN)   * </code> + * @see elgg_query_runner() for details on the hash.   * - * @warning be array this var may be an array or ElggStaticVariableCache depending on when called :( + * @warning Elgg used to set this as an empty array to turn off the cache   * - * @global ElggStaticVariableCache|array $DB_QUERY_CACHE + * @global ElggLRUCache|null $DB_QUERY_CACHE + * @access private   */  global $DB_QUERY_CACHE; -$DB_QUERY_CACHE = array(); +$DB_QUERY_CACHE = null;  /**   * Queries to be executed upon shutdown. @@ -40,6 +42,7 @@ $DB_QUERY_CACHE = array();   * </code>   *   * @global array $DB_DELAYED_QUERIES + * @access private   */  global $DB_DELAYED_QUERIES;  $DB_DELAYED_QUERIES = array(); @@ -51,6 +54,7 @@ $DB_DELAYED_QUERIES = array();   * $dblink as $dblink[$name] => resource.  Use get_db_link($name) to retrieve it.   *   * @global resource[] $dblink + * @access private   */  global $dblink;  $dblink = array(); @@ -61,6 +65,7 @@ $dblink = array();   * Each call to the database increments this counter.   *   * @global integer $dbcalls + * @access private   */  global $dbcalls;  $dbcalls = 0; @@ -123,9 +128,8 @@ function establish_db_link($dblinkname = "readwrite") {  	// Set up cache if global not initialized and query cache not turned off  	if ((!$DB_QUERY_CACHE) && (!$db_cache_off)) { -		// @todo everywhere else this is assigned to array(), making it dangerous to call -		// object methods on this. We should consider making this an plain array -		$DB_QUERY_CACHE = new ElggStaticVariableCache('db_query_cache'); +		// @todo if we keep this cache in 1.9, expose the size as a config parameter +		$DB_QUERY_CACHE = new ElggLRUCache(200);		  	}  } @@ -400,11 +404,9 @@ function elgg_query_runner($query, $callback = null, $single = false) {  	// Is cached?  	if ($DB_QUERY_CACHE) { -		$cached_query = $DB_QUERY_CACHE[$hash]; - -		if ($cached_query !== FALSE) { +		if (isset($DB_QUERY_CACHE[$hash])) {  			elgg_log("DB query $query results returned from cache (hash: $hash)", 'NOTICE'); -			return $cached_query; +			return $DB_QUERY_CACHE[$hash];			  		}  	} @@ -456,19 +458,12 @@ function elgg_query_runner($query, $callback = null, $single = false) {   * @access private   */  function insert_data($query) { -	global $DB_QUERY_CACHE;  	elgg_log("DB query $query", 'NOTICE');  	$dblink = get_db_link('write'); -	// Invalidate query cache -	if ($DB_QUERY_CACHE) { -		/* @var ElggStaticVariableCache $DB_QUERY_CACHE */ -		$DB_QUERY_CACHE->clear(); -	} - -	elgg_log("Query cache invalidated", 'NOTICE'); +	_elgg_invalidate_query_cache();  	if (execute_query("$query", $dblink)) {  		return mysql_insert_id($dblink); @@ -488,18 +483,12 @@ function insert_data($query) {   * @access private   */  function update_data($query) { -	global $DB_QUERY_CACHE;  	elgg_log("DB query $query", 'NOTICE');  	$dblink = get_db_link('write'); -	// Invalidate query cache -	if ($DB_QUERY_CACHE) { -		/* @var ElggStaticVariableCache $DB_QUERY_CACHE */ -		$DB_QUERY_CACHE->clear(); -		elgg_log("Query cache invalidated", 'NOTICE'); -	} +	_elgg_invalidate_query_cache();  	if (execute_query("$query", $dblink)) {  		return TRUE; @@ -519,18 +508,12 @@ function update_data($query) {   * @access private   */  function delete_data($query) { -	global $DB_QUERY_CACHE;  	elgg_log("DB query $query", 'NOTICE');  	$dblink = get_db_link('write'); -	// Invalidate query cache -	if ($DB_QUERY_CACHE) { -		/* @var ElggStaticVariableCache $DB_QUERY_CACHE */ -		$DB_QUERY_CACHE->clear(); -		elgg_log("Query cache invalidated", 'NOTICE'); -	} +	_elgg_invalidate_query_cache();  	if (execute_query("$query", $dblink)) {  		return mysql_affected_rows($dblink); @@ -539,6 +522,22 @@ function delete_data($query) {  	return FALSE;  } +/** + * Invalidate the query cache + *  + * @access private + */ +function _elgg_invalidate_query_cache() { +	global $DB_QUERY_CACHE; +	if ($DB_QUERY_CACHE instanceof ElggLRUCache) { +		$DB_QUERY_CACHE->clear(); +		elgg_log("Query cache invalidated", 'NOTICE'); +	} elseif ($DB_QUERY_CACHE) { +		// In case someone sets the cache to an array and primes it with data  +		$DB_QUERY_CACHE = array(); +		elgg_log("Query cache invalidated", 'NOTICE'); +	} +}  /**   * Return tables matching the database prefix {@link $CONFIG->dbprefix}% in the currently diff --git a/engine/lib/entities.php b/engine/lib/entities.php index 156eec040..cb972b282 100644 --- a/engine/lib/entities.php +++ b/engine/lib/entities.php @@ -30,10 +30,10 @@ $SUBTYPE_CACHE = null;   *   * @param int $guid The entity guid   * - * @return null + * @return void   * @access private   */ -function invalidate_cache_for_entity($guid) { +function _elgg_invalidate_cache_for_entity($guid) {  	global $ENTITY_CACHE;  	$guid = (int)$guid; @@ -50,13 +50,13 @@ function invalidate_cache_for_entity($guid) {   *   * @param ElggEntity $entity Entity to cache   * - * @return null - * @see retrieve_cached_entity() - * @see invalidate_cache_for_entity() + * @return void + * @see _elgg_retrieve_cached_entity() + * @see _elgg_invalidate_cache_for_entity()   * @access private - * TODO(evan): Use an ElggCache object + * @todo Use an ElggCache object   */ -function cache_entity(ElggEntity $entity) { +function _elgg_cache_entity(ElggEntity $entity) {  	global $ENTITY_CACHE;  	// Don't cache non-plugin entities while access control is off, otherwise they could be @@ -66,7 +66,7 @@ function cache_entity(ElggEntity $entity) {  	}  	// Don't store too many or we'll have memory problems -	// TODO(evan): Pick a less arbitrary limit +	// @todo Pick a less arbitrary limit  	if (count($ENTITY_CACHE) > 256) {  		$random_guid = array_rand($ENTITY_CACHE); @@ -88,11 +88,11 @@ function cache_entity(ElggEntity $entity) {   * @param int $guid The guid   *   * @return ElggEntity|bool false if entity not cached, or not fully loaded - * @see cache_entity() - * @see invalidate_cache_for_entity() + * @see _elgg_cache_entity() + * @see _elgg_invalidate_cache_for_entity()   * @access private   */ -function retrieve_cached_entity($guid) { +function _elgg_retrieve_cached_entity($guid) {  	global $ENTITY_CACHE;  	if (isset($ENTITY_CACHE[$guid])) { @@ -105,31 +105,6 @@ function retrieve_cached_entity($guid) {  }  /** - * As retrieve_cached_entity, but returns the result as a stdClass - * (compatible with load functions that expect a database row.) - * - * @param int $guid The guid - * - * @return mixed - * @todo unused - * @access private - */ -function retrieve_cached_entity_row($guid) { -	$obj = retrieve_cached_entity($guid); -	if ($obj) { -		$tmp = new stdClass; - -		foreach ($obj as $k => $v) { -			$tmp->$k = $v; -		} - -		return $tmp; -	} - -	return false; -} - -/**   * Return the id for a given subtype.   *   * ElggEntity objects have a type and a subtype.  Subtypes @@ -745,7 +720,7 @@ function get_entity($guid) {  	}  	// Check local cache first -	$new_entity = retrieve_cached_entity($guid); +	$new_entity = _elgg_retrieve_cached_entity($guid);  	if ($new_entity) {  		return $new_entity;  	} @@ -782,7 +757,7 @@ function get_entity($guid) {  	}  	if ($new_entity) { -		cache_entity($new_entity); +		_elgg_cache_entity($new_entity);  	}  	return $new_entity;  } @@ -1037,7 +1012,7 @@ function elgg_get_entities(array $options = array()) {  			foreach ($dt as $item) {  				// A custom callback could result in items that aren't ElggEntity's, so check for them  				if ($item instanceof ElggEntity) { -					cache_entity($item); +					_elgg_cache_entity($item);  					// plugins usually have only settings  					if (!$item instanceof ElggPlugin) {  						$guids[] = $item->guid; @@ -1102,7 +1077,7 @@ function _elgg_fetch_entities_from_sql($sql) {  		if (empty($row->guid) || empty($row->type)) {  			throw new LogicException('Entity row missing guid or type');  		} -		if ($entity = retrieve_cached_entity($row->guid)) { +		if ($entity = _elgg_retrieve_cached_entity($row->guid)) {  			$rows[$i] = $entity;  			continue;  		} @@ -1628,7 +1603,7 @@ function disable_entity($guid, $reason = "", $recursive = true) {  				$entity->disableMetadata();  				$entity->disableAnnotations(); -				invalidate_cache_for_entity($guid); +				_elgg_invalidate_cache_for_entity($guid);  				$res = update_data("UPDATE {$CONFIG->dbprefix}entities  					SET enabled = 'no' @@ -1726,7 +1701,7 @@ function delete_entity($guid, $recursive = true) {  				// delete cache  				if (isset($ENTITY_CACHE[$guid])) { -					invalidate_cache_for_entity($guid); +					_elgg_invalidate_cache_for_entity($guid);  				}  				// If memcache is available then delete this entry from the cache diff --git a/engine/lib/group.php b/engine/lib/group.php index 624029d98..359bc59c2 100644 --- a/engine/lib/group.php +++ b/engine/lib/group.php @@ -242,7 +242,8 @@ function get_users_membership($user_guid) {  	$options = array(  		'relationship' => 'member',  		'relationship_guid' => $user_guid, -		'inverse_relationship' => FALSE +		'inverse_relationship' => false, +		'limit' => false,  	);  	return elgg_get_entities_from_relationship($options);  } diff --git a/engine/lib/output.php b/engine/lib/output.php index da8e1ab86..c5a04989b 100644 --- a/engine/lib/output.php +++ b/engine/lib/output.php @@ -284,11 +284,9 @@ function elgg_get_friendly_title($title) {  		return $result;  	} -	// handle some special cases -	$title = str_replace('&', 'and', $title); -	// quotes and angle brackets stored in the database as html encoded -	$title = htmlspecialchars_decode($title); - +	// titles are often stored HTML encoded +	$title = html_entity_decode($title, ENT_QUOTES, 'UTF-8'); +	  	$title = ElggTranslit::urlize($title);  	return $title; diff --git a/engine/lib/river.php b/engine/lib/river.php index f2ec1e101..4926a85c4 100644 --- a/engine/lib/river.php +++ b/engine/lib/river.php @@ -380,10 +380,10 @@ function _elgg_prefetch_river_entities(array $river_items) {  	// prefetch objects and subjects  	$guids = array();  	foreach ($river_items as $item) { -		if ($item->subject_guid && !retrieve_cached_entity($item->subject_guid)) { +		if ($item->subject_guid && !_elgg_retrieve_cached_entity($item->subject_guid)) {  			$guids[$item->subject_guid] = true;  		} -		if ($item->object_guid && !retrieve_cached_entity($item->object_guid)) { +		if ($item->object_guid && !_elgg_retrieve_cached_entity($item->object_guid)) {  			$guids[$item->object_guid] = true;  		}  	} @@ -402,7 +402,7 @@ function _elgg_prefetch_river_entities(array $river_items) {  	$guids = array();  	foreach ($river_items as $item) {  		$object = $item->getObjectEntity(); -		if ($object->container_guid && !retrieve_cached_entity($object->container_guid)) { +		if ($object->container_guid && !_elgg_retrieve_cached_entity($object->container_guid)) {  			$guids[$object->container_guid] = true;  		}  	} diff --git a/engine/lib/upgrade.php b/engine/lib/upgrade.php index d684af862..0cc1e64dc 100644 --- a/engine/lib/upgrade.php +++ b/engine/lib/upgrade.php @@ -354,16 +354,12 @@ function _elgg_upgrade_unlock() {   * @access private   */  function _elgg_upgrade_is_locked() { -	global $CONFIG, $DB_QUERY_CACHE; -	 +	global $CONFIG; +  	$is_locked = count(get_data("show tables like '{$CONFIG->dbprefix}upgrade_lock'")); -	 -	// Invalidate query cache -	if ($DB_QUERY_CACHE) { -		/* @var ElggStaticVariableCache $DB_QUERY_CACHE */ -		$DB_QUERY_CACHE->clear(); -		elgg_log("Query cache invalidated", 'NOTICE'); -	} -	 + +	// @todo why? +	_elgg_invalidate_query_cache(); +  	return $is_locked;  } diff --git a/engine/lib/upgrades/2009102801.php b/engine/lib/upgrades/2009102801.php index cab9a6835..3ad113fb2 100644 --- a/engine/lib/upgrades/2009102801.php +++ b/engine/lib/upgrades/2009102801.php @@ -203,14 +203,15 @@ function user_file_matrix($guid) {  	return "$time_created/$user->guid/";  } -global $DB_QUERY_CACHE, $DB_PROFILE, $ENTITY_CACHE; +global $ENTITY_CACHE, $CONFIG;  /**   * Upgrade file locations   */  $users = mysql_query("SELECT guid, username  	FROM {$CONFIG->dbprefix}users_entity WHERE username != ''");  while ($user = mysql_fetch_object($users)) { -	$DB_QUERY_CACHE = $DB_PROFILE = $ENTITY_CACHE = array(); +	$ENTITY_CACHE = array(); +	_elgg_invalidate_query_cache();  	$to = $CONFIG->dataroot . user_file_matrix($user->guid);  	foreach (array('1_0', '1_1', '1_6') as $version) { diff --git a/engine/lib/upgrades/2010061501.php b/engine/lib/upgrades/2010061501.php index 9ff7d3102..744c28fd5 100644 --- a/engine/lib/upgrades/2010061501.php +++ b/engine/lib/upgrades/2010061501.php @@ -45,7 +45,7 @@ if ($dbversion < 2009100701) {  			}  		} -		global $DB_QUERY_CACHE, $DB_PROFILE, $ENTITY_CACHE; +		global $ENTITY_CACHE;  		/**  			Upgrade file locations @@ -60,7 +60,9 @@ if ($dbversion < 2009100701) {  		$users = mysql_query("SELECT guid, username FROM {$CONFIG->dbprefix}users_entity  			WHERE username != ''", $link);  		while ($user = mysql_fetch_object($users)) { -			$DB_QUERY_CACHE = $DB_PROFILE = $ENTITY_CACHE = array(); +			$ENTITY_CACHE = array(); +			_elgg_invalidate_query_cache(); +  			$to = $CONFIG->dataroot . user_file_matrix($user->guid);  			foreach (array('1_0', '1_1', '1_6') as $version) { diff --git a/engine/lib/upgrades/2010071001.php b/engine/lib/upgrades/2010071001.php index 1b5d379d8..5594493a8 100644 --- a/engine/lib/upgrades/2010071001.php +++ b/engine/lib/upgrades/2010071001.php @@ -30,11 +30,12 @@ function user_file_matrix_2010071001($guid) {  $sizes = array('large', 'medium', 'small', 'tiny', 'master', 'topbar'); -global $DB_QUERY_CACHE, $DB_PROFILE, $ENTITY_CACHE, $CONFIG; +global $ENTITY_CACHE, $CONFIG;  $users = mysql_query("SELECT guid, username FROM {$CONFIG->dbprefix}users_entity  	WHERE username != ''");  while ($user = mysql_fetch_object($users)) { -	$DB_QUERY_CACHE = $DB_PROFILE = $ENTITY_CACHE = array(); +	$ENTITY_CACHE = array(); +	_elgg_invalidate_query_cache();  	$user_directory = user_file_matrix_2010071001($user->guid);  	if (!$user_directory) { diff --git a/engine/lib/upgrades/2010071002.php b/engine/lib/upgrades/2010071002.php index 30bd6538c..52aa15ef5 100644 --- a/engine/lib/upgrades/2010071002.php +++ b/engine/lib/upgrades/2010071002.php @@ -4,12 +4,13 @@   */  // loop through all users checking collections and notifications -global $DB_QUERY_CACHE, $DB_PROFILE, $ENTITY_CACHE, $CONFIG; +global $ENTITY_CACHE, $CONFIG;  global $NOTIFICATION_HANDLERS;  $users = mysql_query("SELECT guid, username FROM {$CONFIG->dbprefix}users_entity  	WHERE username != ''");  while ($user = mysql_fetch_object($users)) { -	$DB_QUERY_CACHE = $DB_PROFILE = $ENTITY_CACHE = array(); +	$ENTITY_CACHE = array(); +	_elgg_invalidate_query_cache();  	$user = get_entity($user->guid);  	foreach ($NOTIFICATION_HANDLERS as $method => $foo) { diff --git a/engine/lib/upgrades/2011052801.php b/engine/lib/upgrades/2011052801.php index 8084bc06c..b5a8e1018 100644 --- a/engine/lib/upgrades/2011052801.php +++ b/engine/lib/upgrades/2011052801.php @@ -2,7 +2,7 @@  /**   * Make sure all users have the relationship member_of_site   */ -global $DB_QUERY_CACHE, $DB_PROFILE, $ENTITY_CACHE, $CONFIG; +global $ENTITY_CACHE;  $db_prefix = get_config('dbprefix');  $limit = 100; @@ -17,7 +17,8 @@ $q = "SELECT e.* FROM {$db_prefix}entities e  $users = get_data($q);  while ($users) { -	$DB_QUERY_CACHE = $DB_PROFILE = $ENTITY_CACHE = array(); +	$ENTITY_CACHE = array(); +	_elgg_invalidate_query_cache();  	// do manually to not trigger any events because these aren't new users.  	foreach ($users as $user) { diff --git a/engine/lib/upgrades/2013030600-1.8.13-update_user_location-8999eb8bf1bdd9a3.php b/engine/lib/upgrades/2013030600-1.8.13-update_user_location-8999eb8bf1bdd9a3.php index b38eb5100..8eccf05e2 100644 --- a/engine/lib/upgrades/2013030600-1.8.13-update_user_location-8999eb8bf1bdd9a3.php +++ b/engine/lib/upgrades/2013030600-1.8.13-update_user_location-8999eb8bf1bdd9a3.php @@ -7,8 +7,6 @@   * This script turns that back into a string.   */ -global $DB_QUERY_CACHE; -  $ia = elgg_set_ignore_access(true);  $options = array(  	'type' => 'user', @@ -17,7 +15,7 @@ $options = array(  $batch = new ElggBatch('elgg_get_entities', $options);  foreach ($batch as $entity) { -	$DB_QUERY_CACHE = array(); +	_elgg_invalidate_query_cache();  	if (is_array($entity->location)) {  		$entity->location = implode(', ', $entity->location); diff --git a/engine/lib/user_settings.php b/engine/lib/user_settings.php index 3466c25f9..0e36dc46d 100644 --- a/engine/lib/user_settings.php +++ b/engine/lib/user_settings.php @@ -308,7 +308,7 @@ function usersettings_page_handler($page) {  		$user = get_user_by_username($page[1]);  		elgg_set_page_owner_guid($user->guid);  	} else { -		$user = elgg_get_logged_in_user_guid(); +		$user = elgg_get_logged_in_user_entity();  		elgg_set_page_owner_guid($user->guid);  	} diff --git a/engine/lib/users.php b/engine/lib/users.php index 4a585c07f..9a5194896 100644 --- a/engine/lib/users.php +++ b/engine/lib/users.php @@ -237,7 +237,7 @@ function make_user_admin($user_guid) {  			}  			$r = update_data("UPDATE {$CONFIG->dbprefix}users_entity set admin='yes' where guid=$user_guid"); -			invalidate_cache_for_entity($user_guid); +			_elgg_invalidate_cache_for_entity($user_guid);  			return $r;  		} @@ -273,7 +273,7 @@ function remove_user_admin($user_guid) {  			}  			$r = update_data("UPDATE {$CONFIG->dbprefix}users_entity set admin='no' where guid=$user_guid"); -			invalidate_cache_for_entity($user_guid); +			_elgg_invalidate_cache_for_entity($user_guid);  			return $r;  		} @@ -558,8 +558,8 @@ function get_user_by_username($username) {  	// Caching  	if ((isset($USERNAME_TO_GUID_MAP_CACHE[$username])) -			&& (retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]))) { -		return retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]); +			&& (_elgg_retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]))) { +		return _elgg_retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]);  	}  	$query = "SELECT e.* from {$CONFIG->dbprefix}users_entity u @@ -592,9 +592,9 @@ function get_user_by_code($code) {  	// Caching  	if ((isset($CODE_TO_GUID_MAP_CACHE[$code])) -	&& (retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]))) { +	&& (_elgg_retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]))) { -		return retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]); +		return _elgg_retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]);  	}  	$query = "SELECT e.* from {$CONFIG->dbprefix}users_entity u @@ -705,18 +705,18 @@ function send_new_password_request($user_guid) {   * @return bool   */  function force_user_password_reset($user_guid, $password) { -	global $CONFIG; -  	$user = get_entity($user_guid);  	if ($user instanceof ElggUser) { -		$salt = generate_random_cleartext_password(); // Reset the salt -		$user->salt = $salt; +		$ia = elgg_set_ignore_access(); -		$hash = generate_user_password($user, $password); +		$user->salt = generate_random_cleartext_password(); +		$hash = generate_user_password($user, $password);		 +		$user->password = $hash; +		$result = (bool)$user->save(); -		$query = "UPDATE {$CONFIG->dbprefix}users_entity -			set password='$hash', salt='$salt' where guid=$user_guid"; -		return update_data($query); +		elgg_set_ignore_access($ia); + +		return $result;  	}  	return false; diff --git a/engine/tests/api/access_collections.php b/engine/tests/api/access_collections.php index ebcd7d318..4acfae596 100644 --- a/engine/tests/api/access_collections.php +++ b/engine/tests/api/access_collections.php @@ -54,7 +54,6 @@ class ElggCoreAccessCollectionsTest extends ElggCoreUnitTest {  	}  	public function testCreateGetDeleteACL() { -		global $DB_QUERY_CACHE;  		$acl_name = 'test access collection';  		$acl_id = create_access_collection($acl_name); @@ -67,8 +66,6 @@ class ElggCoreAccessCollectionsTest extends ElggCoreUnitTest {  		$this->assertEqual($acl->id, $acl_id);  		if ($acl) { -			$DB_QUERY_CACHE = array(); -			  			$this->assertEqual($acl->name, $acl_name);  			$result = delete_access_collection($acl_id); diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 691433a41..58444dd39 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -206,21 +206,23 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest {  	 */  	public function test_friendly_title() {  		$cases = array( +			// acid test +			"B&N > Amazon, OK? <bold> 'hey!' $34" +			=> "b-and-n-greater-than-amazon-ok-bold-hey-34", +  			// hyphen, underscore and ASCII whitespace replaced by separator,  			// other non-alphanumeric ASCII removed -			"a-a_a a\na\ra\ta\va!a\"a#a\$a%a&a'a(a)a*a+a,a.a/a:a;a<a=a>a?a@a[a\\a]a^a`a{a|a}a~a" -			=> "a-a-a-a-a-a-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - +			"a-a_a a\na\ra\ta\va!a\"a#a\$a%a&a'a(a)a*a+a,a.a/a:a;a=a?a@a[a\\a]a^a`a{a|a}a~a" +			=> "a-a-a-a-a-a-aaaaaaa-and-aaaaaaaaaaaaaaaaaaaaaaa", +			  			// separators trimmed -			"-_ hello _-" => "hello", +			"-_ hello _-"  +			=> "hello",  			// accents removed, lower case, other multibyte chars are URL encoded  			"I\xC3\xB1t\xC3\xABrn\xC3\xA2ti\xC3\xB4n\xC3\xA0liz\xC3\xA6ti\xC3\xB8n, AND \xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E"  				// Iñtërnâtiônàlizætiøn, AND 日本語  			=> 'internationalizaetion-and-%E6%97%A5%E6%9C%AC%E8%AA%9E', - -			// some HTML entity replacements -			"Me & You" => 'me-and-you',  		);  		// where available, string is converted to NFC before transliteration  | 
