diff options
| -rw-r--r-- | engine/classes/ElggPriorityList.php | 384 | ||||
| -rw-r--r-- | engine/lib/elgglib.php | 112 | ||||
| -rw-r--r-- | engine/tests/api/helpers.php | 323 | 
3 files changed, 789 insertions, 30 deletions
| diff --git a/engine/classes/ElggPriorityList.php b/engine/classes/ElggPriorityList.php new file mode 100644 index 000000000..931138106 --- /dev/null +++ b/engine/classes/ElggPriorityList.php @@ -0,0 +1,384 @@ +<?php +/** + * Iterate over elements in a specific priority. + * + * You can add, remove, and access elements using OOP or array interfaces: + * + * // OOP + * $pl = new ElggPriorityList(); + * $pl->add('Element 0'); + * $pl->add('Element -5', -5); + * $pl->add('Element 10', 10); + * $pl->add('Element -10', -10); + * + * $pl->remove('Element -5'); + * + * $elements = $pl->getElements(); + * var_dump($elements); + * + * Yields: + * + * array( + *	-10 => 'Element -10', + * 	0 => 'Element 0', + * 	10 => 'Element 10', + * ) + * + * + * // Array + *  + * $pl = new ElggPriorityList(); + * $pl[] = 'Element 0'; + * $pl[-5] = 'Element -5'; + * $pl[10] = 'Element 10'; + * $pl[-10] = 'Element -10'; + * + * $priority = $pl->getPriority('Element -5'); + * unset($pl[$priority]); + * + * foreach ($pl as $priority => $element) { + *	var_dump("$priority => $element"); + * } + * + * Yields: + * -10 => Element -10 + * 0 => Element 0 + * 10 => Element 10 + * + * + * Collisions with priority are handled by default differently in the OOP and the array interfaces. + *  + * If using the OOP interface, the default is to insert the element as close to the requested + * priority as possible. + * + * $pl = new ElggPriorityList(); + * $pl->add('Element 5', 5); + * $pl->add('Colliding element 5', 5); + * $pl->add('Another colliding element 5', 5); + * + * var_dump($pl->getElements()); + * + * Yields: + * array( + *	5 => 'Element 5', + *	6 => 'Colliding element 5', + *	7 => 'Another colliding element 5' + * ) + * + * If using the array interface, elements are added at exactly the priority, displacing other + * elements if necessary. This behavior is also available by passing true as the 3rd argument to + * ->add(): + * + * $pl = new ElggPriorityList(); + * $pl[5] = 'Element 5'; + * $pl[6] = 'Element 6'; + * $pl[5] = 'Colliding element 5'; // shifts the previous two up by one + * $pl->add('Another colliding element 5', 5, true); // shifts the previous three up by one + * + * var_dump($pl->getElements()); + * + * Yields: + * array( + *	5 => 'Another colliding element 5', + *	6 => 'Colliding element 5', + *	7 => 'Element 5', + *	8 => 'Element 6' + * ) + * + * @package Elgg.Core + * @subpackage Helpers + */ + +class ElggPriorityList +	implements Iterator, ArrayAccess, Countable { + +	/** +	 * The list of elements +	 * +	 * @var array +	 */ +	private $elements = array(); + +	/** +	 * Create a new priority list. +	 * +	 * @param array $elements An optional array of priorities => element +	 */ +	public function __construct(array $elements = array()) { +		if ($elements) { +			foreach ($elements as $priority => $element) { +				$this->add($element, $priority); +			} +		} +	} + +	/** +	 * Adds an element to the list. +	 * +	 * @warning This returns the priority at which the element was added, which can be 0. Use +	 *          !== false to check for success. +	 * +	 * @param mixed $element  The element to add to the list. +	 * @param mixed $priority Priority to add the element. In priority collisions, the original element +	 *                        maintains its priority and the new element is to the next available +	 *                        slot, taking into consideration all previously registered elements. +	 *                        Negative elements are accepted. +	 * @param bool  $exact    If true, will put the element at exactly the priority specified, displacing +	 *                        other elements. +	 * @return int            The priority of the added element. +	 */ +	public function add($element, $priority = null, $exact = false) { +		if ($priority !== null && !is_numeric($priority)) { +			return false; +		} elseif ($exact) { +			$this->shiftElementsSegment($priority); +		} else { +			$priority = $this->getNextPriority($priority); +		} + +		$this->elements[$priority] = $element; +		$this->sorted = false; +		return $priority; +	} + +	/** +	 * Removes an element from the list. +	 * +	 * @warning The element must have the same attributes / values. If using $strict, it must have +	 *          the same types. array(10) will fail in strict against array('10') (str vs int). +	 * +	 * @param type $element +	 * @return bool +	 */ +	public function remove($element, $strict = false) { +		$index = array_search($element, $this->elements, $strict); +		if ($index !== false) { +			unset($this->elements[$index]); +			return true; +		} else { +			return false; +		} +	} + +	/** +	 * Move an existing element to a new priority. +	 * +	 * @param int  $current_priority +	 * @param int  $new_priority +	 * @param bool $exact +	 * @return bool +	 */ +	public function move($current_priority, $new_priority, $exact = false) { +		$current_priority = (int) $current_priority; +		$new_priority = (int) $new_priority; + +		if (!isset($this->elements[$current_priority])) { +			return false; +		} + +		if ($current_priority == $new_priority) { +			return true; +		} + +		$element = $this->elements[$current_priority]; +		unset($this->elements[$current_priority]); + +		return $this->add($element, $new_priority, $exact); +	} + +	/** +	 * Returns the elements +	 * +	 * @param type $elements +	 * @param type $sort +	 */ +	public function getElements() { +		$this->sortIfUnsorted(); +		return $this->elements; +	} + +	/** +	 * Sort the elements optionally by a callback function. +	 * +	 * If no user function is provided the elements are sorted by priority registered. +	 * +	 * The callback function should accept the array of elements as the first argument and should +	 * return a sorted array. +	 * +	 * This function can be called multiple times. +	 * +	 * @param type $callback +	 * @return bool +	 */ +	public function sort($callback = null) { +		if (!$callback) { +			ksort($this->elements, SORT_NUMERIC); +		} else { +			$sorted = call_user_func($callback, $this->elements); + +			if (!$sorted) { +				return false; +			} + +			$this->elements = $sorted; +		} +		 +		$this->sorted = true; +		return true; +	} + +	/** +	 * Sort the elements if they haven't been sorted yet. +	 * +	 * @return bool +	 */ +	private function sortIfUnsorted() { +		if (!$this->sorted) { +			return $this->sort(); +		} +	} + +	/** +	 * Shift a segment of elements starting at $index up by one until the end of the array or +	 * there's a gap in the indexes. This produces a space at $index to insert a new element. +	 * +	 * @param type $index The index to start +	 * @return array +	 */ +	private function shiftElementsSegment($index) { +		$index = (int) $index; +		// @todo probably a better way. +		$replace_elements = array(); +		while (isset($this->elements[$index])) { +			$replace_elements[$index + 1] = $this->elements[$index]; +			unset($this->elements[$index]); +			$index++; +		} + +		// insert old ones +		foreach ($replace_elements as $index => $element) { +			$this->elements[$index] = $element; +		} +	} + +	/** +	 * Returns the next priority available. +	 * +	 * @param int $near Make the priority as close to $near as possible. +	 * @return int +	 */ +	public function getNextPriority($near = 0) { +		$near = (int) $near; +		 +		while (array_key_exists($near, $this->elements)) { +			$near++; +		} + +		return $near; +	} + + +	/** +	 * Returns the priority of an element if it exists in the list. +	 *  +	 * @warning This can return 0 if the element's priority is 0. Use identical operator (===) to +	 * check for false if you want to know if an element exists. +	 * +	 * @param mixed $element +	 * @return mixed False if the element doesn't exists, the priority if it does. +	 */ +	public function getPriority($element, $strict = false) { +		return array_search($element, $this->elements, $strict); +	} + +	/********************** +	 * Interfaces methods * +	 **********************/ + + +	/** +	 * Iterator +	 */ + +	/** +	 * PHP Iterator Interface +	 * +	 * @see Iterator::rewind() +	 * @return void +	 */ +	public function rewind() { +		$this->sortIfUnsorted(); +		return rewind($this->elements); +	} + +	/** +	 * PHP Iterator Interface +	 * +	 * @see Iterator::current() +	 * @return mixed +	 */ +	public function current() { +		$this->sortIfUnsorted(); +		return current($this->elements); +	} + +	/** +	 * PHP Iterator Interface +	 * +	 * @see Iterator::key() +	 * @return int +	 */ +	public function key() { +		$this->sortIfUnsorted(); +		return key($this->elements); +	} + +	/** +	 * PHP Iterator Interface +	 * +	 * @see Iterator::next() +	 * @return mixed +	 */ +	public function next() { +		$this->sortIfUnsorted(); +		return next($this->elements); +	} + +	/** +	 * PHP Iterator Interface +	 * +	 * @see Iterator::valid() +	 * @return bool +	 */ +	public function valid() { +		$this->sortIfUnsorted(); +		$key = key($this->elements); +		return ($key !== NULL && $key !== FALSE); +	} + +	// Coutable +	public function count() { +		return count($this->elements); +	} + +	// ArrayAccess +	public function offsetExists($offset) { +		return isset($this->elements[$offset]); +	} + +	public function offsetGet($offset) { +		return isset($this->elements[$offset]) ? $this->elements[$offset] : null; +	} + +	public function offsetSet($offset, $value) { +		// for $pl[] = 'New element' +		$exact = ($offset !== null); +		return $this->add($value, $offset, $exact); +	} + +	public function offsetUnset($offset) { +		if (isset($this->elements[$offset])) { +			unset($this->elements[$offset]); +		} +	} +}
\ No newline at end of file diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php index cb736f418..b6b603e79 100644 --- a/engine/lib/elgglib.php +++ b/engine/lib/elgglib.php @@ -172,7 +172,7 @@ function forward($location = "", $reason = 'system') {   * @return bool   * @since 1.8.0   */ -function elgg_register_js($name, $url, $location = 'head', $priority = 500) { +function elgg_register_js($name, $url, $location = 'head', $priority = null) {  	return elgg_register_external_file('js', $name, $url, $location, $priority);  } @@ -225,7 +225,7 @@ function elgg_get_loaded_js($location = 'head') {   * @return bool   * @since 1.8.0   */ -function elgg_register_css($name, $url, $priority = 500) { +function elgg_register_css($name, $url, $priority = null) {  	return elgg_register_external_file('css', $name, $url, 'head', $priority);  } @@ -278,7 +278,7 @@ function elgg_get_loaded_css() {   * @return bool   * @since 1.8.0   */ -function elgg_register_external_file($type, $name, $url, $location, $priority = 500) { +function elgg_register_external_file($type, $name, $url, $location, $priority = null) {  	global $CONFIG;  	if (empty($name) || empty($url)) { @@ -292,26 +292,35 @@ function elgg_register_external_file($type, $name, $url, $location, $priority =  		$CONFIG->externals = array();  	} -	if (!isset($CONFIG->externals[$type])) { -		$CONFIG->externals[$type] = array(); +	if (!$CONFIG->externals[$type] instanceof ElggPriorityList) { +		$CONFIG->externals[$type] = new ElggPriorityList();  	}  	$name = trim(strtolower($name)); +	$priority = max((int)$priority, 0); -	if (isset($CONFIG->externals[$type][$name])) { -		// update a registered item -		$item = $CONFIG->externals[$type][$name]; +	$index = elgg_get_external_file_priority($name, $type); + +	if ($index !== false) { +		// updating a registered item +		$item = $CONFIG->externals[$type][$index]; +		$item->url = $url; +		$item->location = $location; +		// remove old saved priority +		elgg_remove_external_file_priority($name, $type); +		$priority = $CONFIG->externals[$type]->move($index, $priority);  	} else {  		$item = new stdClass();  		$item->loaded = false; -	} +		$item->url = $url; +		$item->location = $location; -	$item->url = $url; -	$item->priority = max((int)$priority, 0); -	$item->location = $location; +		$priority = $CONFIG->externals[$type]->add($item, $priority); +	} -	$CONFIG->externals[$type][$name] = $item; +	// save priority map so we can update if added again +	elgg_save_external_file_priority($priority, $name, $type);  	return true;  } @@ -332,14 +341,17 @@ function elgg_unregister_external_file($type, $name) {  		return false;  	} -	if (!isset($CONFIG->externals[$type])) { +	if (!$CONFIG->externals[$type] instanceof ElggPriorityList) {  		return false;  	}  	$name = trim(strtolower($name)); -	if (array_key_exists($name, $CONFIG->externals[$type])) { -		unset($CONFIG->externals[$type][$name]); +	$priority = elgg_get_external_file_priority($name, $type); + +	if ($priority !== false) { +		elgg_remove_external_file_priority($name, $type); +		unset($CONFIG->externals[$type][$priority]);  		return true;  	} @@ -362,24 +374,75 @@ function elgg_load_external_file($type, $name) {  		$CONFIG->externals = array();  	} -	if (!isset($CONFIG->externals[$type])) { -		$CONFIG->externals[$type] = array(); +	if (!$CONFIG->externals[$type] instanceof ElggPriorityList) { +		$CONFIG->externals[$type] = new ElggPriorityList();  	}  	$name = trim(strtolower($name)); -	if (isset($CONFIG->externals[$type][$name])) { +	$priority = elgg_get_external_file_priority($name, $type); + +	if ($priority !== false) {  		// update a registered item -		$CONFIG->externals[$type][$name]->loaded = true; +		$CONFIG->externals[$type][$priority]->loaded = true;  	} else {  		$item = new stdClass();  		$item->loaded = true;  		$item->url = '';  		$item->location = ''; -		$item->priority = 500; -		$CONFIG->externals[$type][$name] = $item; +		$priority = $CONFIG->externals[$type]->add($item); +		elgg_save_external_file_priority($priority, $name, $type); +	} +} + +/** + * Gets the priority of an external by name and type. + * + * @param type $name + * @param type $type + * @return type  + */ +function elgg_get_external_file_priority($name, $type) { +	global $CONFIG; + +	if (!isset($CONFIG->externals_priorities[$type][$name])) { +		return false; +	} + +	return $CONFIG->externals_priorities[$type][$name]; +} + +function elgg_save_external_file_priority($priority, $name, $type) { +	global $CONFIG; + +	if (!isset($CONFIG->externals_priorities)) { +		$CONFIG->externals_priorities = array(); +	} +	 +	if (!isset($CONFIG->externals_priorities[$type])) { +		$CONFIG->externals_priorities[$type] = array(); +	} + +	$CONFIG->externals_priorities[$type][$name] = $priority; + +	return true; +} + +function elgg_remove_external_file_priority($name, $type) { +	global $CONFIG; +	 +	if (!isset($CONFIG->externals_priorities)) { +		$CONFIG->externals_priorities = array();  	} + +	if (!isset($CONFIG->externals_priorities[$type])) { +		$CONFIG->externals_priorities[$type] = array(); +	} + +	unset($CONFIG->externals_priorities[$type][$name]); + +	return true;  }  /** @@ -394,13 +457,12 @@ function elgg_load_external_file($type, $name) {  function elgg_get_loaded_external_files($type, $location) {  	global $CONFIG; -	if (isset($CONFIG->externals) && isset($CONFIG->externals[$type])) { -		$items = array_values($CONFIG->externals[$type]); +	if (isset($CONFIG->externals) && $CONFIG->externals[$type] instanceof ElggPriorityList) { +		$items = $CONFIG->externals[$type]->getElements();  		$callback = "return \$v->loaded == true && \$v->location == '$location';";  		$items = array_filter($items, create_function('$v', $callback));  		if ($items) { -			usort($items, create_function('$a,$b','return $a->priority >= $b->priority;'));  			array_walk($items, create_function('&$v,$k', '$v = $v->url;'));  		}  		return $items; diff --git a/engine/tests/api/helpers.php b/engine/tests/api/helpers.php index 461627547..cceb762be 100644 --- a/engine/tests/api/helpers.php +++ b/engine/tests/api/helpers.php @@ -31,6 +31,7 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest {  		global $CONFIG;  		unset($CONFIG->externals); +		unset($CONFIG->externals_priorities);  	}  	/** @@ -106,7 +107,9 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest {  		// specify name  		$result = elgg_register_js('key', 'http://test1.com', 'footer');  		$this->assertTrue($result); -		$this->assertIdentical('http://test1.com', $CONFIG->externals['js']['key']->url); +		$this->assertTrue(isset($CONFIG->externals_priorities['js']['key'])); +		$index = $CONFIG->externals_priorities['js']['key']; +		$this->assertIdentical('http://test1.com', $CONFIG->externals['js'][$index]->url);  		// send a bad url  		$result = @elgg_register_js('bad'); @@ -122,7 +125,9 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest {  		// specify name  		$result = elgg_register_css('key', 'http://test1.com');  		$this->assertTrue($result); -		$this->assertIdentical('http://test1.com', $CONFIG->externals['css']['key']->url); +		$this->assertTrue(isset($CONFIG->externals_priorities['css']['key'])); +		$index = elgg_get_external_file_priority('css', 'key'); +		$this->assertIdentical('http://test1.com', $CONFIG->externals['css'][$index]->url);  	}  	/** @@ -140,7 +145,13 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest {  		$result = elgg_unregister_js('id1');  		$this->assertTrue($result); -		@$this->assertNULL($CONFIG->externals['js']['head']['id1']); + +		$js = $CONFIG->externals['js']; +		$elements = $js->getElements(); +		$this->assertFalse(isset($CONFIG->externals_priorities['js']['id1'])); +		foreach ($elements as $element) { +			$this->assertFalse($element->name == 'id1'); +		}  		$result = elgg_unregister_js('id1');  		$this->assertFalse($result); @@ -148,7 +159,15 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest {  		$this->assertFalse($result);  		$result = elgg_unregister_js('id2'); -		$this->assertIdentical($urls['id3'], $CONFIG->externals['js']['id3']->url); +		$elements = $js->getElements(); +		$this->assertFalse(isset($CONFIG->externals_priorities['js']['id2'])); +		foreach ($elements as $element) { +			$this->assertFalse($element->name == 'id2'); +		} + +		$this->assertTrue(isset($CONFIG->externals_priorities['js']['id3'])); +		$priority = $CONFIG->externals_priorities['js']['id3']; +		$this->assertIdentical($urls['id3'], $CONFIG->externals['js'][$priority]->url);  	}  	/** @@ -187,4 +206,298 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest {  		$js_urls = elgg_get_loaded_js('footer');  		$this->assertIdentical(array(), $js_urls);  	} -} + +	// test ElggPriorityList +	public function testElggPriorityListAdd() { +		$pl = new ElggPriorityList(); +		$elements = array( +			'Test value', +			'Test value 2', +			'Test value 3' +		); + +		shuffle($elements); + +		foreach ($elements as $element) { +			$this->assertTrue($pl->add($element) !== false); +		} + +		$test_elements = $pl->getElements(); + +		$this->assertTrue(is_array($test_elements)); + +		foreach ($test_elements as $i => $element) { +			// should be in the array +			$this->assertTrue(in_array($element, $elements)); + +			// should be the only element, so priority 0 +			$this->assertEqual($i, array_search($element, $elements)); +		} +	} + +	public function testElggPriorityListAddWithPriority() { +		$pl = new ElggPriorityList(); + +		$elements = array( +			10 => 'Test Element 10', +			5 => 'Test Element 5', +			0 => 'Test Element 0', +			100 => 'Test Element 100', +			-1 => 'Test Element -1', +			-5 => 'Test Element -5' +		); + +		foreach ($elements as $priority => $element) { +			$pl->add($element, $priority); +		} + +		$test_elements = $pl->getElements(); + +		// should be sorted by priority +		$elements_sorted = array( +			-5 => 'Test Element -5', +			-1 => 'Test Element -1', +			0 => 'Test Element 0', +			5 => 'Test Element 5', +			10 => 'Test Element 10', +			100 => 'Test Element 100', +		); + +		$this->assertIdentical($elements_sorted, $test_elements); + +		foreach ($test_elements as $priority => $element) { +			$this->assertIdentical($elements[$priority], $element); +		} +	} + +	public function testElggPriorityListGetNextPriority() { +		$pl = new ElggPriorityList(); + +		$elements = array( +			2 => 'Test Element', +			0 => 'Test Element 2', +			-2 => 'Test Element 3', +		); + +		foreach ($elements as $priority => $element) { +			$pl->add($element, $priority); +		} + +		// we're not specifying a priority so it should be the next consecutive to 0. +		$this->assertEqual(1, $pl->getNextPriority()); + +		// add another one at priority 1 +		$pl->add('Test Element 1'); + +		// next consecutive to 0 is now 3. +		$this->assertEqual(3, $pl->getNextPriority()); +	} + +	public function testElggPriorityListRemove() { +		$pl = new ElggPriorityList(); + +		$elements = array(); +		for ($i=0; $i<3; $i++) { +			$element = new stdClass(); +			$element->name = "Test Element $i"; +			$element->someAttribute = rand(0, 9999); +			$elements[] = $element; +			$pl->add($element); +		} + +		$pl->remove($elements[1]); + +		$test_elements = $pl->getElements(); + +		// make sure it's gone. +		$this->assertTrue(2, count($test_elements)); +		$this->assertIdentical($elements[0], $test_elements[0]); +		$this->assertIdentical($elements[2], $test_elements[2]); +	} + +	public function testElggPriorityListConstructor() { +		$elements = array( +			10 => 'Test Element 10', +			5 => 'Test Element 5', +			0 => 'Test Element 0', +			100 => 'Test Element 100', +			-1 => 'Test Element -1', +			-5 => 'Test Element -5' +		); + +		$pl = new ElggPriorityList($elements); +		$test_elements = $pl->getElements(); + +		$elements_sorted = array( +			-5 => 'Test Element -5', +			-1 => 'Test Element -1', +			0 => 'Test Element 0', +			5 => 'Test Element 5', +			10 => 'Test Element 10', +			100 => 'Test Element 100', +		); + +		$this->assertIdentical($elements_sorted, $test_elements); +	} + +	public function testElggPriorityListGetPriority() { +		$pl = new ElggPriorityList(); + +		$elements = array( +			'Test element 0', +			'Test element 1', +			'Test element 2', +		); + +		foreach ($elements as $element) { +			$pl->add($element); +		} + +		$this->assertIdentical(0, $pl->getPriority($elements[0])); +		$this->assertIdentical(1, $pl->getPriority($elements[1])); +		$this->assertIdentical(2, $pl->getPriority($elements[2])); +	} + +	public function testElggPriorityListPriorityCollision() { +		$pl = new ElggPriorityList(); +		 +		$elements = array( +			5 => 'Test element 5', +			6 => 'Test element 6', +			0 => 'Test element 0', +		); + +		foreach ($elements as $priority => $element) { +			$pl->add($element, $priority); +		} + +		// add at a colliding priority +		$pl->add('Colliding element', 5); + +		// should float to the top closest to 5, so 7 +		$this->assertEqual(7, $pl->getPriority('Colliding element')); +	} + +	public function testElggPriorityListArrayAccess() { +		$pl = new ElggPriorityList(); +		 +		$pl[] = 'Test element 0'; +		$pl[-10] = 'Test element -10'; +		$pl[-1] = 'Test element -1'; +		$pl[] = 'Test element 1'; +		$pl[5] = 'Test element 5'; +		$pl[0] = 'Test element collision with 0'; + +		$elements = array( +			-1 => 'Test element -1', +			0 => 'Test element collision with 0', +			1 => 'Test element 0', +			2 => 'Test element 1', +			5 => 'Test element 5', +		); + +		$priority = $pl->getPriority('Test element -10'); +		unset($pl[$priority]); + +		$test_elements = $pl->getElements(); +		$this->assertIdentical($elements, $test_elements); +	} + +	public function testElggPriorityListIterator() { +		$elements = array( +			-5 => 'Test element -5', +			0 => 'Test element 0', +			5 => 'Test element 5' +		); +		 +		$pl = new ElggPriorityList($elements); + +		foreach ($pl as $priority => $element) { +			$this->assertIdentical($elements[$priority], $element); +		} +	} + +	public function testElggPriorityListCountable() { +		$pl = new ElggPriorityList(); + +		$this->assertEqual(0, count($pl)); + +		$pl[] = 'Test element 0'; +		$this->assertEqual(1, count($pl)); + +		$pl[] = 'Test element 1'; +		$this->assertEqual(2, count($pl)); + +		$pl[] = 'Test element 2'; +		$this->assertEqual(3, count($pl)); +	} + +	public function testElggPriorityListUserSort() { +		$elements = array( +			'A', +			'B', +			'C', +			'D', +			'E', +		); + +		$elements_sorted_string = $elements; + +		shuffle($elements); +		$pl = new ElggPriorityList($elements); + +		// will sort by priority +		$test_elements = $pl->getElements(); +		$this->assertIdentical($elements, $test_elements); + +		function test_sort($elements) { +			sort($elements, SORT_LOCALE_STRING); +			return $elements; +		} + +		// force a new sort using our function +		$pl->sort('test_sort'); +		$test_elements = $pl->getElements(); + +		$this->assertIdentical($elements_sorted_string, $test_elements); +	} + +	function testElggPriorityListShiftElementsSegment() { +		$elements = array( +			0 => 'Element 0', +			1 => 'Element 1', +			2 => 'Element 2', +			4 => 'Element 4', +		); + +		$pl = new ElggPriorityList($elements); + +		// add a new element directly at 1. +		$pl->add('New Element', 1, true); + +		$elements_sorted = array( +			0 => 'Element 0', +			1 => 'New Element', +			2 => 'Element 1', +			3 => 'Element 2', +			4 => 'Element 4', +		); + +		$test_elements = $pl->getElements(); +		$this->assertIdentical($elements_sorted, $test_elements); + +		$pl->add('New Element 10', 10, true); + +		$elements_sorted = array( +			0 => 'Element 0', +			1 => 'New Element', +			2 => 'Element 1', +			3 => 'Element 2', +			4 => 'Element 4', +			10 => 'New Element 10' +		); + +		$test_elements = $pl->getElements(); +		$this->assertIdentical($elements_sorted, $test_elements); +	} +}
\ No newline at end of file | 
