<?php
/**
* Nav
*
* @package Croogo.Croogo.Lib
* @since 1.4
* @author Rachman Chavik <rchavik@xintesa.com>
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
* @link http://www.croogo.org
*/
namespace Croogo\Core;
use Cake\Log\Log;
use Cake\Utility\Hash;
use Cake\Utility\Inflector;
use UnexpectedValueException;
class Nav
{
/**
* Current active menu
*
* @see CroogoNav::activeMenu()
*/
protected static $_activeMenu = 'sidebar';
/**
* _items
*
* @var array
*/
protected static $_items = ['sidebar' => []];
/**
* _defaults
*
* @var array
*/
protected static $_defaults = [
'icon' => '',
'title' => false,
'url' => '#',
'weight' => 9999,
'before' => false,
'after' => false,
'access' => [],
'children' => [],
'htmlAttributes' => [],
];
/**
* Getter/setter for activeMenu
*/
public static function activeMenu($menu = null)
{
if ($menu === null) {
$activeMenu = self::$_activeMenu;
} else {
$activeMenu = $menu;
}
if (!array_key_exists($activeMenu, self::$_items)) {
self::$_items[$activeMenu] = [];
}
self::$_activeMenu = $activeMenu;
return $activeMenu;
}
public static function menus()
{
return array_keys(self::$_items);
}
/**
* _setupOptions
*
* @param array $options
* @return void
*/
protected static function _setupOptions(&$options)
{
$options = self::_merge(self::$_defaults, $options);
foreach ($options['children'] as &$child) {
self::_setupOptions($child);
}
}
/**
* Add a menu item
*
* @param string $menu dot separated path in the array.
* @param array $path menu options array
* @return void
*/
public static function add($menu, $path, $options = [])
{
// Juggle argument for backward compatibility
if (is_array($path)) {
$options = $path;
$path = $menu;
$menu = self::activeMenu();
} else {
self::activeMenu($menu);
}
$pathE = explode('.', $path);
$pathE = array_splice($pathE, 0, count($pathE) - 2);
$parent = join('.', $pathE);
if (!empty($parent) && !Hash::check(self::$_items[$menu], $parent)) {
$title = Inflector::humanize(end($pathE));
$o = ['title' => $title];
self::_setupOptions($o);
self::add($parent, $o);
}
self::_setupOptions($options);
$current = Hash::extract(self::$_items[$menu], $path);
if (!empty($current)) {
self::_replace(self::$_items[$menu], $path, $options);
} else {
self::$_items[$menu] = Hash::insert(self::$_items[$menu], $path, $options);
}
}
/**
* Replace a menu element
*
* @param array $target pointer to start of array
* @param string $path path to search for in dot separated format
* @param array $options data to replace with
* @return void
*/
protected static function _replace(&$target, $path, $options)
{
$pathE = explode('.', $path);
$path = array_shift($pathE);
$fragment = join('.', $pathE);
if (!empty($pathE)) {
self::_replace($target[$path], $fragment, $options);
} else {
$target[$path] = self::_merge($target[$path], $options);
}
}
/**
* Merge $firstArray with $secondArray
*
* Similar to Hash::merge, except duplicates are removed
* @param array $firstArray
* @param array $secondArray
* @return array
*/
protected static function _merge($firstArray, $secondArray)
{
if ($firstArray == $secondArray) {
return $secondArray;
}
$merged = Hash::merge($firstArray, $secondArray);
foreach ($merged as $key => $val) {
if (is_array($val) && is_int(key($val))) {
$merged[$key] = array_unique($val);
}
}
return $merged;
}
/**
* Remove a menu item
*
* @param string $path dot separated path in the array.
* @return void
*/
public static function remove($path)
{
self::$_items = Hash::remove(self::$_items, $path);
}
/**
* Clear all menus
*
* @return void
*/
public static function clear($menu = 'sidebar')
{
if ($menu) {
if (array_key_exists($menu, self::$_items)) {
self::$_items[$menu] = [];
} else {
throw new UnexpectedValueException('Invalid menu: ' . $menu);
}
} else {
self::$_items = [];
}
}
/**
* Sets or returns menu data in array
*
* @param $items array if empty, the current menu is returned.
* @return array
* @throws UnexpectedValueException
*/
public static function items($menu = 'sidebar', $items = null)
{
if (!is_string($menu)) {
throw new UnexpectedValueException('Menu id is not a string');
}
if (!empty($items)) {
self::$_items[$menu] = $items;
}
if (!array_key_exists($menu, self::$_items)) {
Log::error('Invalid menu: ' . $menu);
return [];
}
return self::$_items[$menu];
}
/**
* Check menu existence by path
* @param string $menu Menu name
* @param string $path Path for Hash::extract()
* @return bool
*/
public static function check($menu, $path)
{
if (!isset(static::$_items[$menu])) {
return false;
}
return Hash::check(self::$_items[$menu], $path);
}
/**
* Gets default settings for menu items
* @return array
*/
public static function getDefaults()
{
return self::$_defaults;
}
}