dirk
11/23/2011 - 8:58 AM

Admin navigation management in Lithium PHP framework

Admin navigation management in Lithium PHP framework

<?php
/**
 * Test case for Set class
 * 
 * @author   Fahad Ibnay Heylaal <contact@fahad19.com>
 * @license  http://www.opensource.org/licenses/mit-license.php The MIT License
 */
namespace core\tests\cases\util;

use core\util\Set;

class SetTest extends \lithium\test\Unit {
	
	public function setUp() {
		
	}
	
	public function testOrder() {
		$data = array(
			'group1' => array(
				'key1' => array('foo' => 'bar', 'weight' => 5),
				'key2' => array('hello' => 'world', 'weight' => 1),
			),
			'group2' => array(
				'key1' => array('foo' => 'bar', 'weight' => 1),
				'key2' => array('hello' => 'world', 'weight' => 2),
			),
			'group3' => array('apple', 'orange', 'blackberry'),
		);
		$expected = array(
			'group1' => array(
				'key2' => array('hello' => 'world', 'weight' => 1),
				'key1' => array('foo' => 'bar', 'weight' => 5),
			),
			'group2' => array(
				'key1' => array('foo' => 'bar', 'weight' => 1),
				'key2' => array('hello' => 'world', 'weight' => 2),
			),
			'group3' => array('apple', 'orange', 'blackberry'),
		);
		$this->assertEqual(Set::order($data, 'weight'), $expected);
	}
	
	public function testFindPath() {
		$data = array(
			'group1' => array(
				'white' => 'board',
				'black' => 'pen',
				'yellow' => 'highlighter',
			),
		);
		$result = Set::findPath($data, 'pen');
		$expected = 'group1.black';
		$this->assertEqual($result, $expected);
	}
	
}

?>
<?php
/**
 * Extended Set class
 * 
 * @author   Fahad Ibnay Heylaal <contact@fahad19.com>
 * @license  http://www.opensource.org/licenses/mit-license.php The MIT License
 */
namespace core\util;

class Set extends \lithium\util\Set {
	
	/**
	 * Orders nested array based on array key.
	 * 
	 * @param array $data
	 * @param string $key
	 * @return array
	 */
	public static function order($data, $key = 'weight') {
		$output = array();
		
		if (!$data) {
			return $output;
		}
		
		$flat = static::flatten($data);
		$flatWeight = array();
		foreach ($flat AS $k => $v) {
			if (strstr($k, $key)) {
				$flatWeight[$k] = $v;
			}
		}
		asort($flatWeight);
		
		foreach ($flatWeight AS $path => $weight) {
			$pathE = explode('.', $path);
			$depth = count($pathE);
			unset($pathE[$depth - 1]);
			$currentPath = implode('.', $pathE);
			$output = self::insert($output, $currentPath, self::find($data, $currentPath));
		}
		$output = self::merge($output, self::diff($data, $output));
		return $output;
	}
	
	/**
	 * Checks if a particular path is set in an array, and returns the value
	 *
	 * @param mixed $data Data to check on.
	 * @param mixed $path A dot-delimited string.
	 * @return mixed value if path is found, `false` otherwise.
	 */
	public static function find($data, $path = null) {
		if (!$path) {
			return $data;
		}
		$path = is_array($path) ? $path : explode('.', $path);

		foreach ($path as $i => $key) {
			if (is_numeric($key) && intval($key) > 0 || $key === '0') {
				$key = intval($key);
			}
			if ($i === count($path) - 1) {
				if (is_array($data) && isset($data[$key])) {
					return $data[$key];
				}
			} else {
				if (!is_array($data) || !isset($data[$key])) {
					return false;
				}
				$data =& $data[$key];
			}
		}
	}
	
	/**
	 * Searches for a value in the array and returns dot separated path.
	 *
	 * @param mixed $data Data to check on.
	 * @param mixed $value Value to search for.
	 * @param string $key Limit search by key.
	 * @return mixed Dot separated path if value is found, `false` otherwise.
	 */
	public static function findPath($data, $value, $key = null) {
		$flatData = static::flatten($data);
		foreach ($flatData AS $k => $v) {
			if (!$key && $v == $value) {
				return $k;
			} elseif ($key && $key == $k && $value == $v) {
				return $k;
			}
		}
		return false;
	}
	
}

?>
<?php
/**
 * Test case for Navigation class
 * 
 * @author   Fahad Ibnay Heylaal <contact@fahad19.com>
 * @license  http://www.opensource.org/licenses/mit-license.php The MIT License
 */
namespace core\tests\cases\storage;

use lithium\util\Set;
use core\storage\Navigation;

class NavigationTest extends \lithium\test\Unit {
	
	public function setUp() {
		Navigation::clearData();
	}
	
	public function testAdd() {
		$usersNav = array(
			'title' => 'Users',
			'link' => '#',
		);
		Navigation::add('users', $usersNav);
		$expected = array('users' => $usersNav);
		$this->assertEqual($expected, Navigation::getData());
		
		$menusNav = array(
			'title' => 'Menus',
			'link' => '#',
		);
		Navigation::add('menus', $menusNav);
		$expected = array('users' => $usersNav, 'menus' => $menusNav);
		$this->assertEqual($expected, Navigation::getData());
		
		Navigation::add('users.children.create', array('title' => 'Create'));
		$expected = array('users' => array_merge($usersNav, array('children' => array('create' => array('title' => 'Create')))), 'menus' => $menusNav);
		$this->assertEqual($expected, Navigation::getData());
	}
	
	public function testRemove() {
		Navigation::add('users', array('title' => 'Users'));
		Navigation::remove('users');
		$this->assertEqual(array(), Navigation::getData());
	}
	
}

?>
<?php
/**
 * Navigation class for storing admin panel menu.
 * 
 * @author   Fahad Ibnay Heylaal <contact@fahad19.com>
 * @license  http://www.opensource.org/licenses/mit-license.php The MIT License
 */
namespace core\storage;

use core\util\Set;

/**
 * Navigation
 * 
 * Class for managing admin panel navigation.
 */
class Navigation extends \lithium\core\StaticObject {
	/**
	 * Stores admin navigation information like:
	 *
	 * $_data = array(
	 *	'contents' => array( // unique top level alias
	 *		'title' => 'Link Title',
	 * 		'link' => '#', // string or an array
	 * 		'weight' => 0, // for ordering
	 * 		'access' => array('*'), // roles
	 * 		'children' => array(
	 * 			'list' => array(
	 * 				'title' => 'List',
	 * 				'link' => '#',
	 * 				'weight' => 5,
	 * 			),
	 * 		),
	 *	),
	 * );
	 *
	 * @var array
	 */
	protected static $_data = array();
	
	/**
	 * Add items to navigation
	 * 
	 * @param string $path Dot separated path in the array. See \lithium\util\Set::insert().
	 * @param array $options Information to be inserted in the given path.
	 * @return void
	 */
	public static function add($path, $options) {
		if (!strstr($path, '.')) {
			static::$_data[$path] = $options;
		} else {
			static::$_data = Set::insert(static::$_data, $path, $options);
		}
	}
	
	/**
	 * Removes given path from navigation.
	 * 
	 * @param string $path Dot separated path in the array. See \lithium\util\Set::insert().
	 * @return void
	 */ 
	public static function remove($path) {
		static::$_data = Set::remove(static::$_data, $path);
	}
	
	/**
	 * Returns navigation information
	 * 
	 * @return array
	 */
	public static function getData() {
		return Set::order(static::$_data);
	}
	
	/**
	 * Deletes all navigation information, mainly for test cases.
	 * 
	 * @return void
	 */ 
	public static function clearData() {
		static::$_data = array();
	}
	
}

?>