From bf8ab3612e992e8ef3bdea551829cda7780720b5 Mon Sep 17 00:00:00 2001 From: Klaas Poortinga Date: Sun, 1 Mar 2020 08:10:37 +0100 Subject: [PATCH] Modify menu structure to objects (#4929) * Modify menu structure to objects --- modules/backend/classes/MainMenuItem.php | 125 ++++++++++++++++++ modules/backend/classes/NavigationManager.php | 99 +++++++++----- modules/backend/classes/SideMenuItem.php | 117 ++++++++++++++++ 3 files changed, 309 insertions(+), 32 deletions(-) create mode 100644 modules/backend/classes/MainMenuItem.php create mode 100644 modules/backend/classes/SideMenuItem.php diff --git a/modules/backend/classes/MainMenuItem.php b/modules/backend/classes/MainMenuItem.php new file mode 100644 index 000000000..07f42cb62 --- /dev/null +++ b/modules/backend/classes/MainMenuItem.php @@ -0,0 +1,125 @@ +permissions[$permission] = $definition; + } + + /** + * @param SideMenuItem $sideMenu + */ + public function addSideMenuItem(SideMenuItem $sideMenu) + { + $this->sideMenu[$sideMenu->code] = $sideMenu; + } + + /** + * @param string $code + * @return SideMenuItem + * @throws SystemException + */ + public function getSideMenuItem(string $code): SideMenuItem + { + if (!array_key_exists($code, $this->sideMenu)) { + throw new SystemException('No sidenavigation item available with code ' . $code); + } + + return $this->sideMenu[$code]; + } + + /** + * @param string $code + */ + public function removeSideMenuItem(string $code) + { + unset($this->sideMenu[$code]); + } + + /** + * @param array $data + * @return static + */ + public static function createFromArray(array $data) + { + $instance = new static(); + $instance->code = $data['code']; + $instance->owner = $data['owner']; + $instance->label = $data['label']; + $instance->url = $data['url']; + $instance->icon = $data['icon'] ?? null; + $instance->iconSvg = $data['iconSvg'] ?? null; + $instance->counter = $data['counter'] ?? null; + $instance->counterLabel = $data['counterLabel'] ?? null; + $instance->permissions = $data['permissions'] ?? $instance->permissions; + $instance->order = $data['order'] ?? $instance->order; + return $instance; + } +} diff --git a/modules/backend/classes/NavigationManager.php b/modules/backend/classes/NavigationManager.php index 59003f7f0..8985f3e09 100644 --- a/modules/backend/classes/NavigationManager.php +++ b/modules/backend/classes/NavigationManager.php @@ -24,7 +24,7 @@ class NavigationManager protected $callbacks = []; /** - * @var array List of registered items. + * @var MainMenuItem[] List of registered items. */ protected $items; @@ -61,7 +61,7 @@ class NavigationManager ]; /** - * @var System\Classes\PluginManager + * @var PluginManager */ protected $pluginManager; @@ -76,6 +76,7 @@ class NavigationManager /** * Loads the menu items from modules and plugins * @return void + * @throws SystemException */ protected function loadItems() { @@ -118,7 +119,7 @@ class NavigationManager /* * Sort menu items */ - uasort($this->items, function ($a, $b) { + uasort($this->items, static function ($a, $b) { return $a->order - $b->order; }); @@ -147,7 +148,7 @@ class NavigationManager /* * Sort side menu items */ - uasort($item->sideMenu, function ($a, $b) { + uasort($item->sideMenu, static function ($a, $b) { return $a->order - $b->order; }); @@ -202,6 +203,7 @@ class NavigationManager * - counterLabel - an optional string value to describe the numeric reference in counter. * @param string $owner Specifies the menu items owner plugin or module in the format Author.Plugin. * @param array $definitions An array of the menu item definitions. + * @throws SystemException */ public function registerMenuItems($owner, array $definitions) { @@ -222,9 +224,9 @@ class NavigationManager $errorMessage = 'Invalid menu item detected in ' . $owner . '. Contact the plugin author to fix (' . $validator->errors()->first() . ')'; if (Config::get('app.debug', false)) { throw new SystemException($errorMessage); - } else { - Log::error($errorMessage); } + + Log::error($errorMessage); } $this->addMainMenuItems($owner, $definitions); @@ -246,7 +248,7 @@ class NavigationManager * Dynamically add a single main menu item * @param string $owner * @param string $code - * @param array $definitions + * @param array $definition */ public function addMainMenuItem($owner, $code, array $definition) { @@ -256,20 +258,39 @@ class NavigationManager $definition = array_merge((array) $this->items[$itemKey], $definition); } - $item = (object) array_merge(self::$mainItemDefaults, array_merge($definition, [ + $item = array_merge($definition, [ 'code' => $code, 'owner' => $owner - ])); + ]); - $this->items[$itemKey] = $item; + $this->items[$itemKey] = MainMenuItem::createFromArray($item); - if ($item->sideMenu) { - $this->addSideMenuItems($owner, $code, $item->sideMenu); + if (array_key_exists('sideMenu', $item)) { + $this->addSideMenuItems($owner, $code, $item['sideMenu']); } } + /** + * @param string $owner + * @param string $code + * @return MainMenuItem + * @throws SystemException + */ + public function getMainMenuItem(string $owner, string $code): MainMenuItem + { + $itemKey = $this->makeItemKey($owner, $code); + + if (!array_key_exists($itemKey, $this->items)) { + throw new SystemException('No main menu item found with key ' . $itemKey); + } + + return $this->items[$itemKey]; + } + /** * Removes a single main menu item + * @param $owner + * @param $code */ public function removeMainMenuItem($owner, $code) { @@ -295,9 +316,10 @@ class NavigationManager * @param string $owner * @param string $code * @param string $sideCode - * @param array $definitions + * @param array $definition + * @return bool */ - public function addSideMenuItem($owner, $code, $sideCode, array $definition) + public function addSideMenuItem($owner, $code, $sideCode, array $definition): bool { $itemKey = $this->makeItemKey($owner, $code); @@ -316,15 +338,20 @@ class NavigationManager $definition = array_merge((array) $mainItem->sideMenu[$sideCode], $definition); } - $item = (object) array_merge(self::$sideItemDefaults, $definition); + $item = SideMenuItem::createFromArray($definition); - $this->items[$itemKey]->sideMenu[$sideCode] = $item; + $this->items[$itemKey]->addSideMenuItem($item); + return true; } /** * Removes a single main menu item + * @param string $owner + * @param string $code + * @param string $sideCode + * @return bool */ - public function removeSideMenuItem($owner, $code, $sideCode) + public function removeSideMenuItem($owner, $code, $sideCode): bool { $itemKey = $this->makeItemKey($owner, $code); if (!isset($this->items[$itemKey])) { @@ -332,12 +359,14 @@ class NavigationManager } $mainItem = $this->items[$itemKey]; - unset($mainItem->sideMenu[$sideCode]); + $mainItem->removeSideMenuItem($sideCode); + return true; } /** * Returns a list of the main menu items. * @return array + * @throws SystemException */ public function listMainMenuItems() { @@ -372,8 +401,12 @@ class NavigationManager /** * Returns a list of side menu items for the currently active main menu item. * The currently active main menu item is set with the setContext methods. + * @param null $owner + * @param null $code + * @return SideMenuItem[] + * @throws SystemException */ - public function listSideMenuItems($owner = null, $code = null) + public function listSideMenuItems($owner = null, $code = null): array { $activeItem = null; @@ -467,17 +500,18 @@ class NavigationManager /** * Determines if a main menu item is active. - * @param mixed $item Specifies the item object. + * @param MainMenuItem $item Specifies the item object. * @return boolean Returns true if the menu item is active. */ - public function isMainMenuItemActive($item) + public function isMainMenuItemActive($item): bool { - return $this->contextOwner == $item->owner && $this->contextMainMenuItemCode == $item->code; + return $this->contextOwner === $item->owner && $this->contextMainMenuItemCode === $item->code; } /** * Returns the currently active main menu item - * @param mixed $item Returns the item object or null. + * @return null|MainMenuItem $item Returns the item object or null. + * @throws SystemException */ public function getActiveMainMenuItem() { @@ -492,17 +526,17 @@ class NavigationManager /** * Determines if a side menu item is active. - * @param mixed $item Specifies the item object. + * @param SideMenuItem $item Specifies the item object. * @return boolean Returns true if the side item is active. */ - public function isSideMenuItemActive($item) + public function isSideMenuItemActive($item): bool { if ($this->contextSideMenuItemCode === true) { $this->contextSideMenuItemCode = null; return true; } - return $this->contextOwner == $item->owner && $this->contextSideMenuItemCode == $item->code; + return $this->contextOwner === $item->owner && $this->contextSideMenuItemCode === $item->code; } /** @@ -534,17 +568,17 @@ class NavigationManager /** * Removes menu items from an array if the supplied user lacks permission. - * @param User $user A user object - * @param array $items A collection of menu items + * @param \Backend\Models\User $user A user object + * @param MainMenuItem[]|SideMenuItem[] $items A collection of menu items * @return array The filtered menu items */ - protected function filterItemPermissions($user, array $items) + protected function filterItemPermissions($user, array $items): array { if (!$user) { return $items; } - $items = array_filter($items, function ($item) use ($user) { + $items = array_filter($items, static function ($item) use ($user) { if (!$item->permissions || !count($item->permissions)) { return true; } @@ -557,10 +591,11 @@ class NavigationManager /** * Internal method to make a unique key for an item. - * @param object $item + * @param string $owner + * @param string $code * @return string */ - protected function makeItemKey($owner, $code) + protected function makeItemKey($owner, $code): string { return strtoupper($owner).'.'.strtoupper($code); } diff --git a/modules/backend/classes/SideMenuItem.php b/modules/backend/classes/SideMenuItem.php new file mode 100644 index 000000000..0fb82f870 --- /dev/null +++ b/modules/backend/classes/SideMenuItem.php @@ -0,0 +1,117 @@ +attributes[$attribute] = $value; + } + + public function removeAttribute($attribute) + { + unset($this->attributes[$attribute]); + } + + /** + * @param string $permission + * @param array $definition + */ + public function addPermission(string $permission, array $definition) + { + $this->permissions[$permission] = $definition; + } + + /** + * @param string $permission + * @return void + */ + public function removePermission(string $permission) + { + unset($this->permissions[$permission]); + } + + /** + * @param array $data + * @return static + */ + public static function createFromArray(array $data): self + { + $instance = new static(); + $instance->code = $data['code']; + $instance->owner = $data['owner']; + $instance->label = $data['label']; + $instance->url = $data['url']; + $instance->icon = $data['icon'] ?? null; + $instance->iconSvg = $data['iconSvg'] ?? null; + $instance->counter = $data['counter'] ?? null; + $instance->counterLabel = $data['counterLabel'] ?? null; + $instance->attributes = $data['attributes'] ?? $instance->attributes; + $instance->permissions = $data['permissions'] ?? $instance->permissions; + $instance->order = $data['order'] ?? $instance->order; + return $instance; + } +}