From 2ae647dc3c6ca56faab1349d7b3181b6aba0269f Mon Sep 17 00:00:00 2001 From: Nur Alam Date: Mon, 27 Feb 2023 01:08:51 +0600 Subject: [PATCH] all previous beta nav generator approched removed, added new approch --- config/navbar.php | 15 +- phpunit.xml | 29 ++ src/Attributes/AppendTo.php | 13 - src/Attributes/AppendableNavLinks.php | 11 - src/Attributes/Nav.php | 13 - src/Attributes/NavLinks.php | 16 - src/Attributes/ParentNav.php | 13 - src/Children.php | 38 ++ src/Console/NavCacheClearCommand.php | 38 -- src/Contracts/NavPrepare.php | 28 -- src/Contracts/PermissionsResolver.php | 10 - src/Contracts/Presenter.php | 12 +- src/Contracts/WithNavbar.php | 11 - src/Enums/Constant.php | 9 - src/FilesFinderService.php | 73 ---- src/Html/NavBuilder.php | 55 +++ src/Nav.php | 86 ++++ src/NavBuilder.php | 115 ------ src/NavPrepare.php | 221 ---------- src/NavService.php | 549 ------------------------- src/Navbar.php | 213 ---------- src/NavbarServiceProvider.php | 8 - src/Presenter/NavBarPresenter.php | 172 ++++---- src/Services/NavGenerateAttributes.php | 507 ----------------------- src/Traits/Navbar.php | 41 -- src/helpers.php | 22 - tests/Feature/NavItemsGenerateTest.php | 122 ++++++ tests/TestCase.php | 24 ++ 28 files changed, 446 insertions(+), 2018 deletions(-) create mode 100644 phpunit.xml delete mode 100644 src/Attributes/AppendTo.php delete mode 100644 src/Attributes/AppendableNavLinks.php delete mode 100644 src/Attributes/Nav.php delete mode 100644 src/Attributes/NavLinks.php delete mode 100644 src/Attributes/ParentNav.php create mode 100644 src/Children.php delete mode 100644 src/Console/NavCacheClearCommand.php delete mode 100644 src/Contracts/NavPrepare.php delete mode 100644 src/Contracts/PermissionsResolver.php delete mode 100644 src/Contracts/WithNavbar.php delete mode 100644 src/Enums/Constant.php delete mode 100644 src/FilesFinderService.php create mode 100644 src/Html/NavBuilder.php create mode 100644 src/Nav.php delete mode 100644 src/NavBuilder.php delete mode 100644 src/NavPrepare.php delete mode 100644 src/NavService.php delete mode 100644 src/Navbar.php delete mode 100644 src/Services/NavGenerateAttributes.php delete mode 100644 src/Traits/Navbar.php delete mode 100644 src/helpers.php create mode 100644 tests/Feature/NavItemsGenerateTest.php create mode 100644 tests/TestCase.php diff --git a/config/navbar.php b/config/navbar.php index 0880ad2..aa89322 100644 --- a/config/navbar.php +++ b/config/navbar.php @@ -3,11 +3,6 @@ use RadiateCode\LaravelNavbar\Presenter\NavBarPresenter; return [ - /** - * Controllers path to generate navs - */ - 'controllers-path' => app_path('Http/Controllers'), - /** * Presenter for navbar style * @@ -18,10 +13,8 @@ /** * Cache the render navbar */ - 'cache-enable' => true, - - /** - * Cache living duration - */ - 'cache-time' => now()->addDay(), + 'cache' => [ + 'enable' => true, + 'ttl' => now()->addDay() // cache duration + ], ]; \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..ea6323d --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,29 @@ + + + + + src/ + + + + + ./tests/Unit + + + ./tests/Feature + + + \ No newline at end of file diff --git a/src/Attributes/AppendTo.php b/src/Attributes/AppendTo.php deleted file mode 100644 index 5f90843..0000000 --- a/src/Attributes/AppendTo.php +++ /dev/null @@ -1,13 +0,0 @@ -nav = new Nav(); + } + + public function add(string $title, string $url, array $attributes = [], ?callable $configure = null): Children + { + $this->nav->add($title, $url, $attributes, $configure); + + return $this; + } + + public function addIf($condition, string $title, string $url, array $attributes = [], ?callable $configure = null): Children + { + $condition = is_callable($condition) ? $condition() : $condition; + + if ($condition) { + $this->add($title, $url, $attributes, $configure); + } + + return $this; + } + + public function render() + { + return $this->nav->render(); + } +} diff --git a/src/Console/NavCacheClearCommand.php b/src/Console/NavCacheClearCommand.php deleted file mode 100644 index c0b5c2e..0000000 --- a/src/Console/NavCacheClearCommand.php +++ /dev/null @@ -1,38 +0,0 @@ -info('laravel-navbar caches are cleared successfully'); - } -} \ No newline at end of file diff --git a/src/Contracts/NavPrepare.php b/src/Contracts/NavPrepare.php deleted file mode 100644 index e5004a9..0000000 --- a/src/Contracts/NavPrepare.php +++ /dev/null @@ -1,28 +0,0 @@ -findFiles($item, $ext)); - } elseif (is_file($item)) { - $files[] = $item; - } - } - - return $files; - } - - public function findClasses($path): array - { - $globePattern = strtolower(PHP_OS) == 'windows' ? '\*' : '/*'; // php_uname('s') also shows os name - - $files = $this->findFiles($path, $globePattern); - - $basePath = base_path(); - - $classList = []; - - foreach ($files as $file) { - if (is_file($file)) { - //$fileName = pathinfo($file, PATHINFO_FILENAME); - - $class = str_replace([$basePath . '/', '.php'], '', $file); - - if(strtolower(PHP_OS) != 'windows' ){ - $class = str_replace('/', '\\', $class); - } - - $classList[] = ucfirst($class); - } - } - - return $classList; - } -} diff --git a/src/Html/NavBuilder.php b/src/Html/NavBuilder.php new file mode 100644 index 0000000..acadd5b --- /dev/null +++ b/src/Html/NavBuilder.php @@ -0,0 +1,55 @@ +navItems = $navItems; + } + + public static function make(array $navItems): NavBuilder + { + return new self($navItems); + } + + public function navbar(): string + { + $enable = config('navbar.cache.enable'); + + if ($enable) { + return $this->cacheNavbar(); + } + + return $this->getPresenter()->navbar(); + } + + protected function cacheNavbar(bool $reset = false) + { + $ttl = config('navbar.cache.ttl'); + + $key = 'navbar-' . auth()->id(); + + if ($reset) { + Cache::forget($key); + } + + return Cache::remember($key, $ttl, function () { + return $this->getPresenter()->navbar(); + }); + } + + protected function getPresenter(): Presenter + { + $presenter = config('navbar.menu-presenter'); + + return new $presenter($this->navItems); + } +} diff --git a/src/Nav.php b/src/Nav.php new file mode 100644 index 0000000..2b4fab1 --- /dev/null +++ b/src/Nav.php @@ -0,0 +1,86 @@ +render(); + + // if no nav-items then why bother to create header in first place + if (empty($navItems['nav-items'])) { + return $this; + } + + $this->navWithHeader[Str::slug($name)] = array_merge([ + 'title' => $name, + 'attributes' => $attributes, + 'type' => 'header' + ], $navItems); + + return $this; + } + + public function add(string $title, string $url, ?array $attributes = null, ?callable $configure = null): Nav + { + $childrenItems = []; + + if ($configure) { + $children = new Children(); + + $configure($children); + + $childrenItems = $children->render(); + } + + // if no children then why bother to create the nav + if (array_key_exists('nav-items', $childrenItems) && empty($childrenItems['nav-items'])) { + return $this; + } + + $this->nav[] = [ + 'title' => $title, + 'url' => $url, + 'attributes' => $attributes, + 'type' => 'menu', + 'children' => $childrenItems + ]; + + return $this; + } + + public function addIf($condition, string $title, string $url, array $attributes = [], ?callable $configure = null): self + { + $condition = is_callable($condition) ? $condition() : $condition; + + if ($condition) { + $this->add($title, $url, $attributes, $configure); + } + + return $this; + } + + public function render() + { + return array_merge($this->navWithHeader, ['nav-items' => $this->nav]); + } +} diff --git a/src/NavBuilder.php b/src/NavBuilder.php deleted file mode 100644 index 8c789f4..0000000 --- a/src/NavBuilder.php +++ /dev/null @@ -1,115 +0,0 @@ -presenter = config('navbar.menu-presenter'); - } - - public static function instance(): NavBuilder - { - return new self(); - } - - /** - * @throws Exception - */ - public function build(): string - { - if (config('navbar.cache-enable') && $this->hasCache()) { - return $this->getCachedHtmlNavs(); - } - - $presenter = $this->getPresenter(); - - $html = $presenter->openNavTag(); - - $html .= $presenter->openNavULTag(); - - foreach ($this->menus as $key => $menu) { - if($menu['type'] == 'header'){ - - $html .= $presenter->header($menu['title']); - - continue; - } - - $html .= $presenter->nav($menu); - } - - $html .= $presenter->closeNavULTag(); - - $html .= $presenter->closeNavTag(); - - $this->cacheHtmlNavs($html); - - return $html; - } - - /** - * @param array $menus - * @param string|null $key // key can contains . to indicate nested - * - * @return $this - */ - public function injectMenus(array $menus, string $key = null): NavBuilder - { - if ($key) { - Arr::set($this->menus, $key, $menus); - - return $this; - } - - $this->menus = array_merge($this->menus, $menus); - - return $this; - } - - public function menus(array $menus): NavBuilder - { - $this->menus = $menus; - - return $this; - } - - protected function getCachedHtmlNavs() - { - return Cache::get(Constant::CACHE_HTML_RENDERED_NAVS); - } - - protected function hasCache(): bool - { - return Cache::has(Constant::CACHE_HTML_RENDERED_NAVS); - } - - protected function cacheHtmlNavs($menus) - { - $ttl = config('navbar.cache-time'); - - $enable = config('navbar.cache-enable'); - - if ($enable) { - Cache::put(Constant::CACHE_HTML_RENDERED_NAVS, $menus, $ttl); - } - } - - private function getPresenter(): NavBarPresenter - { - return new $this->presenter(); - } -} diff --git a/src/NavPrepare.php b/src/NavPrepare.php deleted file mode 100644 index b7a760e..0000000 --- a/src/NavPrepare.php +++ /dev/null @@ -1,221 +0,0 @@ -header = [ - 'name' => Str::slug($name), - 'type' => 'header', - ]; - - return $this; - } - - public function addNav( - string $name, - string $icon = 'fa fa-home' - ): NavPrepare { - $this->menu = [ - 'name' => Str::slug($name), - 'icon' => $icon, - 'type' => 'menu', - ]; - - return $this; - } - - /** - * @param callable|bool $condition - * - * @return $this - */ - public function createIf($condition): NavPrepare - { - if (is_callable($condition)) { - $this->creatable = $condition(); - - return $this; - } - - if (is_bool($condition)) { - $this->creatable = $condition; - - return $this; - } - - - return $this; - } - - /** - * Generate menu link by route controller associate method - * - * @param string $method_name - * @param string|null $title - * @param string|null $icon - * @param array $css_classes - * - * @return $this - */ - public function addNavLink( - string $method_name, - string $title = null, - string $icon = null, - array $css_classes = [] - ): NavPrepare { - $this->links[$method_name] = [ - 'link-title' => $title, - 'link-icon' => $icon ?: 'far fa-circle nav-icon', - 'link-css-class' => $css_classes, - ]; - - return $this; - } - - /** - * @param bool|callable $condition - * @param string $method_name - * @param string|null $title - * @param string|null $icon - * @param array $css_classes - * - * @return $this - */ - public function addNavLinkIf( - $condition, - string $method_name, - string $title = null, - string $icon = null, - array $css_classes = [] - ): NavPrepare { - if (is_bool($condition) && ! $condition) { - return $this; - } - - if (is_callable($condition) && ! $condition()) { - return $this; - } - - $this->addNavLink($method_name, $title, $icon, $css_classes); - - return $this; - } - - /** - * Menus is child of another menu - * - * @param string $name - * @param string $icon - * - * @return $this - */ - public function childOf( - string $name, - string $icon = 'fa fa-circle' - ): NavPrepare { - $this->childOf = [ - 'name' => $name, - 'icon' => $icon, - 'type' => 'menu', - ]; - - return $this; - } - - /** - * Menu append to another menu - * - * @param string $controllerClass - * - * @return $this - */ - public function appendTo(string $controllerClass): NavPrepare - { - $this->appendTo[] = $controllerClass; - - return $this; - } - - public function hasParent(): bool - { - return ! empty($this->childOf); - } - - public function hasHeader(): bool - { - return ! empty($this->header); - } - - public function isAppendable(): bool - { - return ! empty($this->appendTo); - } - - public function isCreatable(): bool - { - return $this->creatable; - } - - public function hasInconsistencyInAppend(): bool - { - return count($this->appendTo) != count($this->links); - } - - public function getAppends(): array - { - return $this->appendTo; - } - - public function getNav(): array - { - return $this->menu; - } - - public function getHeader(): array - { - return $this->header; - } - - public function getParent(): array - { - return $this->childOf; - } - - public function getNavLinks(): array - { - return $this->links; - } - - public function when( - bool $value, - callable $callback, - callable $default = null - ) { - if ($value) { - return $callback($this) ?: $this; - } elseif ($default) { - return $default($this) ?: $this; - } - - return $this; - } -} diff --git a/src/NavService.php b/src/NavService.php deleted file mode 100644 index f4f7f86..0000000 --- a/src/NavService.php +++ /dev/null @@ -1,549 +0,0 @@ -hasCacheNavs()) { - $this->menus = $this->getCacheNavs(); - - return $this; - } - - $routes = Route::getRoutes(); - - $this->menus = $this->navItemsGenerate($routes); - - $this->cacheNavs(); - - return $this; - } - - protected function navItemsGenerate($routes) - { - $menus = []; - - $childrenTobeInjectInParent = []; - - $navLinksTobeInject = []; - - foreach ($routes as $route) { - $actionName = $route->getActionName(); - - $actionExtract = explode('@', $actionName); - - $currentController = $actionExtract[0]; - - if ($currentController == 'Closure') { - continue; - } - - $currentControllerInstance = app('\\' . $currentController); - - if (!$currentControllerInstance instanceof WithNavbar) { - continue; - } - - $currentControllerInstance->navigation(); // run the navigation - - $currentControllerInstance->navbarInstantiateException(); - - $this->currentControllerMethod = $actionExtract[1]; // $route->getActionMethod() - - $this->currentNavInstance = $currentControllerInstance->getNavbarInstance(); - - if (!$this->currentNavInstance->isCreatable()) { - continue; - } - - if ($this->currentNavInstance->hasHeader()) { - $this->prepareHeader($menus); - } - - $this->currentNavLinks = $this->currentNavInstance->getNavLinks(); - - /** - * Nav link keys are generated by controller action method, - * so check current controller action method is a nav link - */ - if (!in_array($this->currentControllerMethod, array_keys($this->currentNavLinks))) { - continue; - } - - /** - * ------------------------------------------------------- - * Current menu is appendable to another menu - * ------------------------------------------------------- - */ - if ($this->currentNavInstance->isAppendable()) { - $this->prepareOrAppendLinks($menus, $navLinksTobeInject, $route); - - continue; - } - - $currentMenu = $this->currentNavInstance->getNav(); - - /** - * ------------------------------------------------------ - * Current menu is a children of another menu - * ------------------------------------------------------ - */ - if ($this->currentNavInstance->hasParent()) { - $this->prepareChildrenNav($menus, $childrenTobeInjectInParent, $currentMenu, $route); - } - - /** - * ---------------------------------------------------- - * Current menu is a base menu - * ----------------------------------------------------- - */ - else { - - $currentMenuName = $currentMenu['name']; - - if (Arr::get($menus, $currentMenuName . '.nav-links')) { - $this->arr_push($menus, $currentMenuName . '.nav-links', $this->prepareNavLink($route)); - } else { - $preparedMenu = $this->prepareNav($currentMenu, $this->prepareNavLink($route)); - - $menus[$currentMenuName] = $preparedMenu[$currentMenuName]; - } - - if (array_key_exists($currentMenuName, $childrenTobeInjectInParent)) { - $menus[$currentMenuName]['children'] = $childrenTobeInjectInParent[$currentMenuName]['children']; - } - } - - $this->emptyTheTail(); - } - - // check is there any nav-links waiting to be inject in the menus - $this->linksToBeAppend($navLinksTobeInject, $menus); - - return $menus; - } - - protected function getCacheNavs() - { - return Cache::get(Constant::CACHE_NAVS); - } - - protected function hasCacheNavs(): bool - { - return Cache::has(Constant::CACHE_NAVS); - } - - protected function cacheNavs() - { - $ttl = config('navbar.cache-time'); - - $enable = config('navbar.cache-enable'); - - if ($enable && !$this->hasCacheNavs()) { - Cache::put(Constant::CACHE_NAVS, $this->menus, $ttl); - } - } - - /** - * @throws Exception - */ - public function toHtml(): string - { - return NavBuilder::instance()->menus($this->toArray())->build(); - } - - public function toArray(): array - { - return $this->menus; - } - - protected function prepareHeader(&$menus) - { - $header = $this->currentNavInstance->getHeader(); - - if (!Arr::get($menus, $header['name'])) { - $menus[$header['name']] = [ - 'title' => ucwords(str_replace('-', ' ', $header['name'])), - 'type' => $header['type'] - ]; - } - } - - /** - * @param $menus - * @param $childrenTobeInjectInParent - * @param $currentMenu - * @param $route - * - * @return bool - */ - protected function prepareChildrenNav(&$menus, &$childrenTobeInjectInParent, $currentMenu, $route): bool - { - $parent = $this->currentNavInstance->getParent(); - - /** - * If parent menu is not a controller class then prepare the parent menu from the given string - * [Note: This non-class parent menu only works as root level menu, it will not append as child] - */ - if (!class_exists('\\' . $parent['name'])) { - $parentMenuName = Str::slug($parent['name']); - - if (!Arr::get($menus, $parentMenuName)) { - $menus[$parentMenuName] = [ - 'icon' => $parent['icon'], - 'title' => ucwords(str_replace('-', ' ', $parentMenuName)), - 'type' => $parent['type'], - 'nav-links' => [] - ]; - } - } - - /** - * If the parent menu is a controller then get the menu info from the controller - */ - - else { - $parentControllerInstance = app('\\' . $parent['name']); - - if (!$parentControllerInstance instanceof WithNavbar) { - return false; - } - - $parentControllerInstance->navigation(); // run the navigation - - $parentControllerInstance->navbarInstantiateException(); - - $parentMenuInstance = $parentControllerInstance->getNavbarInstance(); - - $parentMenuName = $parentMenuInstance->getNav()['name']; - } - - $currentMenuName = $currentMenu['name']; - - // find is the parent menu already live in the $menus - $exist = $this->keyExists($menus, $parentMenuName); - - // if parent menu is not exist temporarily store it to $childrenTobeInjectInParent - // so that when parent menu appear we can inject the children menu - if (!$exist) { - $navLinks = $this->prepareNavLink($route); - - $preparedMenu = $this->prepareNav($currentMenu, $navLinks); - - // check is there any children need to be injected in this current menu - if (array_key_exists($currentMenuName, $childrenTobeInjectInParent)) { - $preparedMenu[$currentMenuName]['children'] = $childrenTobeInjectInParent[$currentMenuName]['children']; - } - - // parent menu save to $childrenTobeInjectInParent - // so that when the parent menu will appear we can injects it's children - $navLinksOfChildren = $parentMenuName . '.children.' . $currentMenuName . '.nav-links'; - - if (Arr::get($childrenTobeInjectInParent, $navLinksOfChildren)) { - $this->arr_push($childrenTobeInjectInParent, $navLinksOfChildren, $navLinks); - } else { - $childrenTobeInjectInParent[$parentMenuName]['children'][$currentMenuName] = $preparedMenu[$currentMenuName]; - } - - return true; - } - - /** - * if parent menu is exist then add children menus - */ - - // get the position of the parent menu - $livingTails = $this->tail(); - - // add children key to the position of the parent menu - $children = $livingTails . ".children"; - - // prepare the current menu array - $navLinks = $this->prepareNavLink($route); - - $preparedMenu = $this->prepareNav($currentMenu, $navLinks); - - // check is there any children need to be injected in this current menu - if (array_key_exists($currentMenuName, $childrenTobeInjectInParent)) { - $preparedMenu[$currentMenuName]['children'] = $childrenTobeInjectInParent[$currentMenuName]['children']; - } - - $childrenMenu = $children . '.' . $currentMenuName; - - $navLinksOfChildren = $childrenMenu . '.nav-links'; - - if (Arr::get($menus, $childrenMenu)) { // if children menu exist - // then add only a nav link to the nav-links of that children menu - $this->arr_push($menus, $navLinksOfChildren, $navLinks); - } else { // if children not exist then add whole prepared menu as children - Arr::set($menus, $childrenMenu, $preparedMenu[$currentMenuName]); - } - - return true; - } - - /** - * Links append to existing nav-links - * Or prepare links to be append later - * - * @throws Exception - */ - protected function prepareOrAppendLinks(&$menus, &$navLinksTobeInject, $route) - { - if ($this->currentNavInstance->hasInconsistencyInAppend()) { - throw new Exception( - 'Inconsistency occurred between links and append to!' - ); - } - - $appendControllerInstance = $this->makeAppendControllerInstance(); - - if (!$appendControllerInstance instanceof WithNavbar) { - return null; - } - - $appendControllerInstance->navigation(); // run the navigation - - $appendControllerInstance->navbarInstantiateException(); - - $appendMenuInstance = $appendControllerInstance->getNavbarInstance(); - - $appendMenu = $appendMenuInstance->getNav(); - - $appendMenuName = $appendMenu['name']; - - // find is the append menu already live in the $menus - $exist = $this->keyExists($menus, $appendMenuName); - - /** - * If append to menu exist in the menus then push it to the correct menu links - * If not found then temporary store it for later use - */ - if ($exist) { - // get the position of the append menu - $livingTails = $this->tail(); - - // add nav-links key to the position of the append menu - $navLinks = $livingTails . ".nav-links"; - - // prepare the appended link - $navLink = $this->prepareNavLink($route); - - // add the nav-link to the menu - $this->arr_push($menus, $navLinks, $navLink); - } else { - $navLink = $this->prepareNavLink($route); - - // store the nav link so that it can be inject latter when it's menu appear - $navLinksTobeInject[$appendMenuName]['nav-links'][] = $navLink; - } - - $this->emptyTheTail(); - } - - /** - * Append links to existing nav-links - * - * @param $navLinksTobeInject - * @param $menus - */ - protected function linksToBeAppend(&$navLinksTobeInject, &$menus) - { - foreach ($navLinksTobeInject as $key => $item) { - $exist = $this->keyExists($menus, $key); - - if ($exist) { - // get the position of the parent menu - $livingTails = $this->tail() . '.nav-links'; - - $links = Arr::get($menus, $livingTails); - - $combinedLinks = array_merge($links, $item['nav-links']); - - Arr::set($menus, $livingTails, $combinedLinks); - } - - unset($navLinksTobeInject[$key]); - } - } - - /** - * @param $menu - * @param $navLinks - * - * @return array - */ - protected function prepareNav($menu, $navLinks): array - { - $menuPreparation = []; - - $menuName = $menu['name']; - - $menuPreparation[$menuName]['icon'] = $menu['icon']; - - $menuPreparation[$menuName]['title'] = ucwords( - str_replace('-', ' ', $menuName) - ); - - $menuPreparation[$menuName]['type'] = $menu['type']; - - $menuPreparation[$menuName]['nav-links'][] = $navLinks; - - return $menuPreparation; - } - - /** - * @param $route - * - * @return array - */ - protected function prepareNavLink($route): array - { - $title = $this->currentNavLinks[$this->currentControllerMethod]['link-title']; - - return [ - 'link-title' => $title ?: ucwords(str_replace('.', ' ', $route->getName())), - 'link-url' => url($route->uri()), - 'link-icon' => $this->currentNavLinks[$this->currentControllerMethod]['link-icon'], - 'link-css-class' => $this->currentNavLinks[$this->currentControllerMethod]['link-css-class'], - ]; - } - - /** - * @return string - */ - protected function tail(): string - { - return implode('.', array_reverse($this->tail)); - } - - protected function emptyTheTail() - { - $this->tail = []; - } - - /** - * @return Application|mixed - */ - protected function makeAppendControllerInstance() - { - $appendMenus = $this->currentNavInstance->getAppends(); - - $position = array_search( - $this->currentControllerMethod, - array_keys($this->currentNavLinks) - ); - - $appendTo = $appendMenus[$position]; - - return app('\\' . $appendTo); - } - - /** - * @param array $arr - * @param $keySearch - * - * @return bool - */ - private function keyExists(array $arr, $keySearch): bool - { - // is in base array? - if (array_key_exists($keySearch, $arr)) { - $this->tail[] = $keySearch; - - return true; - } - - // check arrays contained in this array - foreach ($arr as $key => $element) { - if (is_array($element)) { - if (array_key_exists('children', $element)) { - if ($this->keyExists($element['children'], $keySearch)) { - $this->tail[] = 'children'; - - $this->tail[] = $key; - - return true; - } - } - } - } - - return false; - } - - /** - * @param $array - * @param $key - * @param $value - * - * @return array|mixed - */ - private function arr_push(&$array, $key, $value) - { - if (is_null($key)) { - return $array = $value; - } - - $keys = explode('.', $key); - - foreach ($keys as $i => $key) { - if (count($keys) === 1) { - break; - } - - unset($keys[$i]); - - // If the key doesn't exist at this depth, we will just create an empty array - // to hold the next value, allowing us to create the arrays to hold final - // values at the correct depth. Then we'll keep digging into the array. - if (!isset($array[$key]) || !is_array($array[$key])) { - $array[$key] = []; - } - - $array = &$array[$key]; - } - - $array[array_shift($keys)][] = $value; - - return $array; - } -} diff --git a/src/Navbar.php b/src/Navbar.php deleted file mode 100644 index b0071e0..0000000 --- a/src/Navbar.php +++ /dev/null @@ -1,213 +0,0 @@ -nav = $nav; - - $this->tail = $this->nav; - - $this->tempMenu[$nav] = [ - 'icon' => $icon, - 'title' => $title, - 'type' => 'menu', - ]; - - return $this; - } - - /** - * @param string|array $url - * @param string|null $title - * @param string|null $icon - * @param array $css_classes - * - * @return $this - */ - public function link( - $url, - string $title = null, - string $icon = null, - array $css_classes = [] - ): Navbar { - if ( ! $this->isCreatable) { - return $this; - } - - $injectTo = $this->tail.'.nav-links'; - - $values = Arr::get($this->tempMenu, $injectTo); - - $url = $this->resolveUrl($url); - - $links = [ - 'link-title' => $title ?: $this->resolveLinkTitle($url), - 'link-url' => $url, - 'link-icon' => $icon ?: 'far fa-circle nav-icon', - 'link-css-class' => $css_classes, - ]; - - if ($values == null) { - Arr::set($this->tempMenu, $injectTo, [$links]); - } else { - array_push($values, $links); - - Arr::set($this->tempMenu, $injectTo, $values); - } - - return $this; - } - - public function linkIf( - $condition, - $url, - string $title = null, - string $icon = null, - array $css_classes = [] - ): Navbar { - if (is_bool($condition) && ! $condition) { - return $this; - } - - if (is_callable($condition) && ! $condition()) { - return $this; - } - - $this->link($url, $title, $icon, $css_classes); - - return $this; - } - - public function children(string $title, string $icon = 'fa fa-home'): Navbar - { - if ( ! $this->isCreatable) { - return $this; - } - - $nav = Str::slug($title); - - $this->tail = $this->tail.'.children.'.$nav; - - Arr::set( - $this->tempMenu, - $this->tail, - [ - 'title' => $title, - 'icon' => $icon, - 'type' => 'menu', - ] - ); - - return $this; - } - - public function make(): bool - { - $this->pushNav($this->nav, $this->tempMenu[$this->nav]) - ->emptyCycle(); - - return true; - } - - public function makeIf($condition): bool - { - if (is_bool($condition) && ! $condition) { - return false; - } - - if (is_callable($condition) && ! $condition()) { - return false; - } - - $this->make(); - - return true; - } - - private function pushNav(string $name, array $value): Navbar - { - $this->navs[$name] = $value; - - return $this; - } - - private function emptyCycle() - { - $this->tempMenu = []; - - $this->nav = null; - - $this->tail = null; - } - - private function resolveUrl($url) - { - if (is_array($url)) { - $resolveUrl = $url[0].'@' - .$url[1]; // 0 index is controller, 1 index is it's method - - return URL::action($resolveUrl); - } elseif (is_string($url) && Str::contains($url, '@')) { - return URL::action($url); - } - - return $url; - } - - private function resolveLinkTitle(string $url): string - { - $name = app('router')->getRoutes()->match( - app('request')->create($url, 'GET') - )->getName(); - - return ucwords(str_replace('.', ' ', $name)); - } - - /** - * @throws Exception - */ - public function toHtml(): string - { - return NavBuilder::instance()->menus($this->toArray())->build(); - } - - public function toArray(): array - { - return $this->navs; - } -} diff --git a/src/NavbarServiceProvider.php b/src/NavbarServiceProvider.php index 02f8607..6b95820 100644 --- a/src/NavbarServiceProvider.php +++ b/src/NavbarServiceProvider.php @@ -14,14 +14,6 @@ public function register() public function boot() { - if ($this->app->runningInConsole()) { - $this->commands( - [ - NavCacheClearCommand::class - ] - ); - } - $this->publishes([ __DIR__.'/../config/navbar.php' => config_path('navbar.php'), ], 'navbar-config'); diff --git a/src/Presenter/NavBarPresenter.php b/src/Presenter/NavBarPresenter.php index 1947609..f9b5980 100644 --- a/src/Presenter/NavBarPresenter.php +++ b/src/Presenter/NavBarPresenter.php @@ -4,131 +4,133 @@ namespace RadiateCode\LaravelNavbar\Presenter; +use Illuminate\Support\Facades\Cache; use RadiateCode\LaravelNavbar\Contracts\Presenter; class NavBarPresenter implements Presenter { - public function openNavTag(string $class = null, array $attributes = []): string + protected array $navItems = []; + + public function __construct(array $navItems) { - return PHP_EOL . '' . PHP_EOL; + return PHP_EOL . '' . PHP_EOL; } - public function openNavULTag(string $class = null, array $attributes = []): string + /** + * Navigation Items + * + * @param string $navItems + * @return string + */ + protected function ulTag(string $navItems) { - return PHP_EOL - . '' . PHP_EOL; + return ''; } /** - * Add header or section - * - * @param string $title - * @param string|null $class - * @param array $attributes + * Tree Nav * + * @param array $navItem * @return string */ - public function header(string $title, string $class = null, array $attributes = []): string + protected function treeNav(array $navItem) { - return PHP_EOL . '' . PHP_EOL; + $treeNav = ''; + + $treeNav = PHP_EOL . '' . PHP_EOL; + + return $treeNav; } - public function nav($menu): string + /** + * Nav item + * + * @param array $navItem + * @return string + */ + protected function navItem(array $navItem) { - return $this->navbarTreeGenerate($menu); + return PHP_EOL . '' . PHP_EOL; } - protected function navbarTreeGenerate($menu): string + /** + * Make nav items, it can be called recursively to generate deep level nav items + * + * [ex: Parent Nav -> Children Navs -> Children Navs -> Children Navs] + * + * @param array $items + * @return string + */ + protected function navItems(array $items) { - /** - * Tree navbar with nav links and children navs - */ - if (array_key_exists('children', $menu) && $menu['children']) { - return PHP_EOL . '' . PHP_EOL; - } + $nav = ''; - /** - * Tree navbar with nav links - */ - if (count($menu['nav-links']) > 1){ - return '' . PHP_EOL; + foreach ($items as $item) { + $nav .= $this->isTreeNav($item) + ? $this->treeNav($item) + : $this->navItem($item); } - /** - * Single nav link [no-tree] - */ - return '' . PHP_EOL; - + return $nav; } - protected function navLink($links): string + public function navbar(): string { - $linkHtml = ''; + $nav = ''; - if (count($links) == 0){ - return $linkHtml; - } + foreach ($this->navItems as $key => $item) { + if ($key != 'nav-items' && $item['type'] == 'header') { + $nav .= $this->headerTag($item['title']); - foreach ($links as $link) { - $navItemCssClasses = implode(' ',array_merge($link['link-css-class'],['nav_items'])); + $nav .= $this->navItems($item['nav-items']); + } - $linkHtml .= "
  • " - ."" - ."" . $link['link-title'] - ."" - ."
  • " . PHP_EOL; + if ($key == 'nav-items') { + $nav .= $this->navItems($item); + } } - return $linkHtml; + return $this->navTag($this->ulTag($nav)); } - protected function children($menu): string + protected function isTreeNav(array $nav) { - $children = ''; - - if (array_key_exists('children', $menu) && $menu['children']) { - foreach ($menu['children'] as $key => $item) { - $children .= $this->navbarTreeGenerate($item); - } - } - - return $children; + return $nav['url'] == '#' && !empty($nav['children']['nav-items']); } } diff --git a/src/Services/NavGenerateAttributes.php b/src/Services/NavGenerateAttributes.php deleted file mode 100644 index 16d96cd..0000000 --- a/src/Services/NavGenerateAttributes.php +++ /dev/null @@ -1,507 +0,0 @@ -hasCacheNavs()) { - // $this->menus = $this->getCacheNavs(); - - // return $this; - // } - - $path = config('navbar.controllers-path'); - - $controllers = FilesFinderService::make()->findClasses($path); - - $this->menus = $this->navItemsGenerate($controllers); - - //$this->cacheNavs(); - - return $this; - } - - protected function navItemsGenerate($controllers) - { - $menus = []; - - $childrenTobeInjectInParent = []; - - $navLinksToBeAppend = []; - - foreach ($controllers as $controller) { - - $reflectionClass = new ReflectionClass($controller); - - $attributes = $reflectionClass->getAttributes(); - - $nav = []; - - $navName = ""; - - $hasParent = false; - - if (count($attributes) > 0) { // check is there any class level nav attributes - foreach ($attributes as $attribute) { - /** - * ------------------------------------- - * Nav links append to anothe nav - * ------------------------------------- - */ - if ($attribute->getName() == AppendableNavLinks::class) { - $this->prepareOrAppendNavLinks($menus, $navLinksToBeAppend, $reflectionClass); - - continue; - } - - $attributeInstance = $attribute->newInstance(); // make instance of the attribute - - /** - * ------------------------------------- - * Prepare nav - * ------------------------------------- - */ - if ($attribute->getName() == Nav::class) { - $serial = $attributeInstance->serial; - - $header = $attributeInstance->header; - - $navName = Str::slug($attributeInstance->name); - - $navIcon = $attributeInstance->icon; - - $navLinks = $this->prepareNavLinks($reflectionClass); - - // if (empty($navLinks)) { // if no nav links then no need to prepare a nav - // continue; - // } - - // $this->prepareHeader($menus, $header); - - $nav = $this->prepareNav($navName, $navIcon, $navLinks); - - // check is there any children need to be injected in this current nav - if (array_key_exists($navName, $childrenTobeInjectInParent)) { - $nav['children'] = $childrenTobeInjectInParent[$navName]; - } - - continue; - } - - /** - * Children nav - */ - if ($attribute->getName() == ParentNav::class && !empty($nav)) { - $hasParent = true; // flag to indicate whether the prepare nav is base nav or a child nav - - /** - * If parent menu is not a controller class then prepare the parent nav from the given string - * [Note: This non-class parent menu only works as root level menu, it will not append as child] - */ - if (!class_exists('\\' . $attributeInstance->name)) { - $parentNavName = Str::slug($attributeInstance->name); - - if (Arr::get($menus, $parentNavName)) { - continue; - } - - // add nav - $menus[$parentNavName] = [ - 'icon' => $attributeInstance->icon, - 'title' => ucwords(str_replace('-', ' ', $parentNavName)), - 'type' => 'menu', - 'nav-links' => [] - ]; - - continue; - } - - /** - * Parent nav is a controller class - */ - $parentNavClass = new ReflectionClass($attributeInstance->name); - - $attributes = $parentNavClass->getAttributes(); - - $attributeInstance = $attributes[0]->newInstance(); - - if ($attributes[0]->getName() != Nav::class) { - continue; - } - - $parentNavName = Str::slug($attributeInstance->name); - - // find is the parent nav already live in the $menus - $exist = $this->keyExists($menus, $parentNavName); - - if ($exist) { // inject the prepared nav to parent as children nav - $livingTails = $this->tail(); - - // add children key to the position of the parent menu - $children = $livingTails . ".children." . $navName; - - // add children nav - Arr::set($menus, $children, $nav); - - continue; - } - - // prepared nav need to be wait for the parent - $childrenTobeInjectInParent[$parentNavName][$navName] = $nav; - } - } - } - - /** - * -------------------------- - * Base nav - * -------------------------- - */ - if (!$hasParent && !empty($nav)) { - $menus[$navName] = $nav; - } - - $this->emptyTheTail(); - } - - $this->linksToBeAppend($navLinksToBeAppend,$menus); - - return $menus; - } - - public function cache() - { - $this->isCache = true; - - return $this; - } - - protected function getCacheNavs() - { - return Cache::get(Constant::CACHE_NAVS); - } - - protected function hasCacheNavs(): bool - { - return Cache::has(Constant::CACHE_NAVS); - } - - protected function cacheNavs() - { - $ttl = config('navbar.cache-time'); - - $enable = config('navbar.cache-enable'); - - if ($enable && !$this->hasCacheNavs()) { - Cache::put(Constant::CACHE_NAVS, $this->menus, $ttl); - } - } - - /** - * @throws Exception - */ - public function toHtml(): string - { - return NavBuilder::instance()->menus($this->toArray())->build(); - } - - public function toArray(): array - { - return $this->menus; - } - - /** - * Append links to existing nav-links - * - * @param $navLinksToBeAppend - * @param $menus - */ - protected function linksToBeAppend(&$navLinksToBeAppend, &$menus) - { - foreach ($navLinksToBeAppend as $key => $item) { - $exist = $this->keyExists($menus, $key); - - if ($exist) { - // get the position of the parent menu - $livingTails = $this->tail() . '.nav-links'; - - $links = Arr::get($menus, $livingTails); - - $combinedLinks = array_merge($links, $item); - - Arr::set($menus, $livingTails, $combinedLinks); - } - - unset($navLinksToBeAppend[$key]); - } - } - - protected function prepareOrAppendNavLinks(&$menus, &$navLinksToBeAppend, $reflectionClass): void - { - $methods = $reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC); - - foreach ($methods as $method) { // get the methods of the reflected class - $attributes = $method->getAttributes(); // get the attributes of the method - - $link = []; - - foreach ($attributes as $attribute) { - /** - * ---------------------------------- - * Preparing appendanble nav-links - * ---------------------------------- - */ - if ($attribute->getName() == NavLinks::class) { - $attributeInstance = $attribute->newInstance(); - - if (!$attributeInstance->condition) { // if condition is false then skip the nav links preparetion - continue; - } - - $method_name = $method->getName(); - $title = $attributeInstance->title; - $icon = $attributeInstance->icon; - - $link = [ - 'link-title' => $title, - 'link-url' => action($reflectionClass->getName() . '@' . $method_name), - 'link-icon' => $icon ?: 'far fa-circle nav-icon', - 'link-css-class' => [], - ]; - } - - /** - * ------------------------------------ - * Prepared nav-links append to another nav - * ------------------------------------ - */ - if ($attribute->getName() == AppendTo::class && !empty($link)) { - $appendToInstance = $attribute->newInstance(); - - // if appendanble nav is non-controller-class - if (!class_exists('\\' . $appendToInstance->name)) { - $appendableNavName = Str::slug($appendToInstance->name); - - if (Arr::get($menus, $appendableNavName)) { - $menus[$appendableNavName]['nav-links'][] = $link; - - continue; - } - - // when appendanble nav is not exist in $menus - $navLinksToBeAppend[$appendableNavName][] = $link; - - continue; - } - - // if appendanble nav is a controller class - $appendableNavClass = new ReflectionClass($appendToInstance->name); - - $attributes = $appendableNavClass->getAttributes(); - - if (count($attributes) == 0) { - continue; - } - - if ($attributes[0]->getName() != Nav::class) { - continue; - } - - $attributeInstance = $attributes[0]->newInstance(); - - $appendableNavName = Str::slug($attributeInstance->name); - - // find is the appendable nav already exist in the $menus - $exist = $this->keyExists($menus, $appendableNavName); - - if ($exist) { // append the nav links - $appendPositionKey = $this->tail() . ".nav-links"; - - // append the nav-link to the menu - $this->arr_push($menus, $appendPositionKey, $link); - - continue; - } - - // nav links need to be wait to append - $navLinksToBeAppend[$appendableNavName][] = $link; - } - } - } - } - - protected function prepareHeader(&$menus, $header) - { - $header = Str::slug($header); - - if (!Arr::get($menus, $header)) { - $menus[$header] = [ - 'title' => ucwords(str_replace('-', ' ', $header)), - 'type' => 'header' - ]; - } - } - - /** - * @param $navLinks - * - * @return array - */ - protected function prepareNav(string $navName, string $navIcon, array $navLinks): array - { - return [ - 'icon' => $navIcon, - 'title' => ucwords(str_replace('-', ' ', $navName)), - 'type' => 'menu', - 'nav-links' => $navLinks - ]; - } - - /** - * @param $route - * - * @return array - */ - protected function prepareNavLinks($reflectionClass): array - { - $methods = $reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC); - - $links = []; - - foreach ($methods as $method) { // get the methods of the reflected class - $attributes = $method->getAttributes(NavLinks::class); // get the attributes of the method - - foreach ($attributes as $attribute) { - $attributeInstance = $attribute->newInstance(); // make instance of the method attribute - - if (!$attributeInstance->condition) { // if condition is false then skip the nav links preparetion - continue; - } - - $method_name = $method->getName(); - $title = $attributeInstance->title; - $icon = $attributeInstance->icon; - - $links[] = [ - 'link-title' => $title, - 'link-url' => action($reflectionClass->getName() . '@' . $method_name), - 'link-icon' => $icon ?: 'far fa-circle nav-icon', - 'link-css-class' => [], - ]; - } - } - - return $links; - } - - /** - * Track the nav key depth - * - * @return string - */ - protected function tail(): string - { - return implode('.', array_reverse($this->tail)); - } - - protected function emptyTheTail() - { - $this->tail = []; - } - - /** - * @param array $arr - * @param $keySearch - * - * @return bool - */ - private function keyExists(array $arr, $keySearch): bool - { - // is in base array? - if (array_key_exists($keySearch, $arr)) { - $this->tail[] = $keySearch; - - return true; - } - - // check arrays contained in this array - foreach ($arr as $key => $element) { - if (is_array($element)) { - if (array_key_exists('children', $element)) { - if ($this->keyExists($element['children'], $keySearch)) { - $this->tail[] = 'children'; - - $this->tail[] = $key; - - return true; - } - } - } - } - - return false; - } - - private function arr_push(&$array, $key, $value) - { - if (is_null($key)) { - return $array = $value; - } - - $keys = explode('.', $key); - - foreach ($keys as $i => $key) { - if (count($keys) === 1) { - break; - } - - unset($keys[$i]); - - // If the key doesn't exist at this depth, we will just create an empty array - // to hold the next value, allowing us to create the arrays to hold final - // values at the correct depth. Then we'll keep digging into the array. - if (!isset($array[$key]) || !is_array($array[$key])) { - $array[$key] = []; - } - - $array = &$array[$key]; - } - - $array[array_shift($keys)][] = $value; - - return $array; - } -} diff --git a/src/Traits/Navbar.php b/src/Traits/Navbar.php deleted file mode 100644 index df097df..0000000 --- a/src/Traits/Navbar.php +++ /dev/null @@ -1,41 +0,0 @@ -nav = new NavPrepare(); - } - - /** - * @throws Exception - */ - public function navbarInstantiateException() - { - if (empty($this->nav)) { - throw new Exception( - 'No navigation instantiated for this controller [' - .class_basename($this).']' - ); - } - } - - public function getNavbarInstance(): NavPrepare - { - return $this->nav; - } - - abstract public function navigation(): void; -} diff --git a/src/helpers.php b/src/helpers.php deleted file mode 100644 index aaf7715..0000000 --- a/src/helpers.php +++ /dev/null @@ -1,22 +0,0 @@ -resolve(); - } - - if (is_array($access) && is_countable($access)){ // if access param is array - foreach ($access as $value){ - return in_array($value, $permissions); - } - } - - return in_array($access, $permissions); - } -} \ No newline at end of file diff --git a/tests/Feature/NavItemsGenerateTest.php b/tests/Feature/NavItemsGenerateTest.php new file mode 100644 index 0000000..7cb3dd8 --- /dev/null +++ b/tests/Feature/NavItemsGenerateTest.php @@ -0,0 +1,122 @@ +header('Adminland', function (Nav $nav) { + $nav + ->addIf(true, 'Roles', 'http://hrp.test/role-list', ['icon' => 'fa fa-user-tag']) + ->addIf(true, 'User', 'http://hrp.test/system-user-list', ['icon' => 'fa fa-users']); + }) + ->header('Settings', function (Nav $nav) { + $nav + ->add('Organisation', '#', ['icon' => 'fa fa-wrench'], function (Children $children) { + $children + ->add('Profile', 'http://hrp.test/view-organisation-profile', ['icon' => 'fa fa-address-card']) + ->add('Offices', 'http://hrp.test/office-list', ['icon' => 'fa fa-landmark']) + ->add('Project', 'http://hrp.test/project-list', ['icon' => 'fa fa-project-diagram']) + ->add('Departments', 'http://hrp.test/department-list', ['icon' => 'fa fa-building']) + ->add('Designations', 'http://hrp.test/designation-list', ['icon' => 'fa fa-user-tag']); + }) + ->add('Rules', '#', ['icon' => 'fa fa-wrench'], function (Children $children) { + $children + ->add('Bonus Rule', '#', ['icon' => 'fa fa-money-bill-wave'], function (Children $children) { + $children + ->addIf(true, 'List', 'http://hrp.test/bonus-rule-list', ['icon' => 'fa fa-list']) + ->addIf(true, 'Create', 'http://hrp.test/create-bonus-rule', ['icon' => 'fa fa-plus-circle']);; + }) + ->add('Pay Grade', '#', ['icon' => 'fa fa-money-check-alt'], function (Children $children) { + $children + ->addIf(true, 'List', 'http://hrp.test/monthly-pay-grade-list', ['icon' => 'fa fa-list']) + ->addIf(false, 'Create', 'http://hrp.test/create-monthly-pay-grade', ['icon' => 'fa fa-plus-circle']); + }); + }); + }) + ->header('Employee Management', function (Nav $nav) { + $nav + ->add('Employee', '#', ['icon' => 'fa fa-user'], function (Children $children) { + $children + ->addIf(true, 'List', 'http://hrp.test/employee-list', ['icon' => 'fa fa-list']) + ->addIf(true, 'Create', 'http://hrp.test/create-employee', ['icon' => 'fa fa-plus-circle']); + }) + ->add('Transfer', '#', ['icon' => 'fa fa-money-check-alt'], function (Children $children) { + $children + ->addIf(true, 'List', 'http://hrp.test/transfer-list', ['icon' => 'fa fa-list']) + ->addIf(true, 'Create', 'http://hrp.test/create-transfer', ['icon' => 'fa fa-plus-circle']); + }); + }) + ->header('Salary Management', function (Nav $nav) { + $nav + ->add('Salary', '#', ['icon' => 'fa fa-money-bill-wave'], function (Children $children) { + $children + ->addIf(true, 'List', 'http://hrp.test/salary-list', ['icon' => 'fa fa-list']) + ->addIf(true, 'Create', 'http://hrp.test/create-salary', ['icon' => 'fa fa-plus-circle']); + }) + ->add('Salary Adjustment', '#', ['icon' => 'fa fa-money-bill-wave'], function (Children $children) { + $children + ->addIf(true, 'List', 'http://hrp.test/salary-adjustment-list', ['icon' => 'fa fa-list']) + ->addIf(true, 'Create', 'http://hrp.test/create-salary-adjustment', ['icon' => 'fa fa-plus-circle']); + }) + ->add('Bonus', '#', ['icon' => 'fa fa-money-bill-wave'], function (Children $children) { + $children + ->addIf(true, 'List', 'http://hrp.test/bonus-list', ['icon' => 'fa fa-list']) + ->addIf(true, 'Create', 'http://hrp.test/create-bonus', ['icon' => 'fa fa-plus-circle']);; + }) + ->add('Advance', '#', ['icon' => 'fa fa-money-bill-wave'], function (Children $children) { + $children + ->addIf(true, 'List', 'http://hrp.test/advance-list', ['icon' => 'fa fa-list']) + ->addIf(true, 'Create', 'http://hrp.test/create-advance', ['icon' => 'fa fa-plus-circle']);; + }) + ->add('General Deduction', '#', ['icon' => 'fa fa-money-bill-wave'], function (Children $children) { + $children + ->addIf(true, 'List', 'http://hrp.test/general-deduction-list', ['icon' => 'fa fa-list']) + ->addIf(true, 'Create', 'http://hrp.test/create-general-deduction', ['icon' => 'fa fa-plus-circle']);; + }) + ->add('Remuneration', '#', ['icon' => 'fas fa-money-bills'], function (Children $children) { + $children + ->addIf(true, 'Cash Paygrade', 'http://hrp.test/remuneration-cash-payment-list', ['icon' => 'fa fa-list']) + ->addIf(true, 'Cash Remuneration', 'http://hrp.test/cash-remuneration-list', ['icon' => 'fa fa-list']) + ->addIf(true, 'Bank Remuneration', 'http://hrp.test/bank-remuneration-list', ['icon' => 'fa fa-list']); + }) + ->add('Incentive', '#', ['icon' => 'fas fa-money-bills'], function (Children $children) { + $children + ->addIf(true, 'List', 'http://hrp.test/incentive-list', ['icon' => 'fa fa-list']) + ->addIf(true, 'Create', 'http://hrp.test/create-incentive', ['icon' => 'fa fa-plus-circle']);; + }); + }) + ->header('Reports', function (Nav $nav) { + $nav + ->add('Statement', '#', ['icon' => 'fa fa-circle'], function (Children $children) { + $children + ->add('Financial Year', 'http://hrp.test/financial-year-salary-statement', ['icon' => 'fa fa-money-check']) + ->add('Salary Statment', 'http://hrp.test/employee-salary-statement', ['icon' => 'fa fa-money-check']) + ->add('Bonus Statment', 'http://hrp.test/employee-bonus-statement', ['icon' => 'fa fa-money-check']); + }) + ->add('Salary Sheet', 'http://hrp.test/generate-salary-sheet', ['icon' => 'fa fa-money-check']) + ->add('Bonus Sheet', 'http://hrp.test/generate-bonus-sheet', ['icon' => 'fa fa-money-check']) + ->add('Remuneration Sheet', '#', ['icon' => 'fa fa-money-check'], function (Children $children) { + $children + ->add('Cash Sheet', 'http://hrp.test/generate-cash-remuneration-sheet', ['icon' => 'fa fa-circle']) + ->add('Bank Sheet', 'http://hrp.test/generate-bank-remuneration-sheet', ['icon' => 'fa fa-circle']); + }); + }) + ->render(); + + //dd($nav); + + $this->assertIsArray($nav); + $this->assertEmpty($nav['nav-items'],'All nav items generated with header section'); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..6487a8a --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,24 @@ +