Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve menu filters (last stage) #1274

Merged
merged 2 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 26 additions & 45 deletions src/Menu/ActiveChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,73 +2,54 @@

namespace JeroenNoten\LaravelAdminLte\Menu;

use Illuminate\Contracts\Routing\UrlGenerator;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class ActiveChecker
{
/**
* The request instance.
*
* @var Request
*/
private $request;

/**
* The url generator instance.
*
* @var UrlGenerator
*/
private $url;

/**
* Map between menu item properties and their respective test method.
* A map between menu item properties and their respective test methods.
*
* @var array
*/
private $tests;
protected $tests;

/**
* Constructor.
*
* @param UrlGenerator $url
*/
public function __construct(UrlGenerator $url)
public function __construct()
{
$this->request = $url->getRequest();
$this->url = $url;

// Fill the map with tests. These tests will check if a menu item is
// active or not.
// Fill the map with tests. These tests will check whether a menu item
// is active. Since the menu is traversed with a depth-first technique,
// for submenu elements with nested submenus, checking for the
// dynamically compiled 'active' property first will give us more
// performance.

$this->tests = [
'submenu' => [$this, 'containsActive'],
'active' => [$this, 'isExplicitActive'],
'submenu' => [$this, 'containsActive'],
'href' => [$this, 'checkPattern'],
'url' => [$this, 'checkPattern'],
];
}

/**
* Checks if a menu item is currently active. Active items will be
* highlighted.
* Checks if a menu item is currently active. An active item will be
* highlighted in the menu.
*
* @param mixed $item The menu item to check
* @return bool
*/
public function isActive($item)
{
// Return true if any of the verification tests is met.
// Return true if any of the verification tests is met. Otherwise,
// return false.

foreach ($this->tests as $prop => $testFunc) {
if (isset($item[$prop]) && $testFunc($item[$prop])) {
foreach ($this->tests as $prop => $testMethod) {
if (isset($item[$prop]) && $testMethod($item[$prop])) {
return true;
}
}

// Otherwise, returns false.

return false;
}

Expand All @@ -90,7 +71,8 @@ protected function containsActive($items)
}

/**
* Checks if an item is active by explicit definition of 'active' state.
* Checks if an item is active by explicit definition of the 'active'
* property.
*
* @param bool|array $activeDef
* @return bool
Expand All @@ -116,7 +98,7 @@ protected function isExplicitActive($activeDef)
}

/**
* Checks if an url pattern matches the requested url.
* Checks if an url pattern matches with the requested url.
*
* @param string $pattern
* @return bool
Expand All @@ -128,19 +110,18 @@ protected function checkPattern($pattern)
if (Str::startsWith($pattern, 'regex:')) {
$regex = Str::substr($pattern, 6);

return (bool) preg_match($regex, $this->request->path());
return (bool) preg_match($regex, request()->path());
}

// If pattern is not a regex, check if the requested url matches the
// absolute path to the given pattern. When the pattern uses query
// parameters, compare with the full url request.
// If pattern is not a regex, check if the requested url matches with
// the absolute path to the given pattern. When the pattern uses query
// parameters, compare with the full requested url.

$pattern = preg_replace('@^https?://@', '*', $this->url->to($pattern));
$request = $this->request->url();
$pattern = preg_replace('@^https?://@', '*', url($pattern));

if (isset(parse_url($pattern)['query'])) {
$request = $this->request->fullUrl();
}
$request = isset(parse_url($pattern)['query'])
? request()->fullUrl()
: request()->url();

return Str::is(trim($pattern), trim($request));
}
Expand Down
5 changes: 3 additions & 2 deletions src/Menu/Filters/ActiveFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ public function __construct(ActiveChecker $activeChecker)
}

/**
* Transforms a menu item. Adds the active attribute when suitable.
* Transforms a menu item. Check if an item is active based on the current
* requested URL and compile it's active property.
*
* @param array $item A menu item
* @return array The transformed menu item
* @return array
*/
public function transform($item)
{
Expand Down
67 changes: 31 additions & 36 deletions src/Menu/Filters/HrefFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,15 @@

namespace JeroenNoten\LaravelAdminLte\Menu\Filters;

use Illuminate\Contracts\Routing\UrlGenerator;
use JeroenNoten\LaravelAdminLte\Helpers\MenuItemHelper;

class HrefFilter implements FilterInterface
{
/**
* The url generator instance.
*
* @var UrlGenerator
*/
protected $urlGenerator;

/**
* Constructor.
*
* @param UrlGenerator $urlGenerator
*/
public function __construct(UrlGenerator $urlGenerator)
{
$this->urlGenerator = $urlGenerator;
}

/**
* Transforms a menu item. Make the href attribute when situable.
* Transforms a menu item. Compile the href HTML attribute when situable.
*
* @param array $item A menu item
* @return array The transformed menu item
* @return array
*/
public function transform($item)
{
Expand All @@ -40,34 +22,47 @@ public function transform($item)
}

/**
* Make the href attribute for a menu item.
* Make and return the href HTML attribute for a menu item.
*
* @param array $item A menu item
* @return string The href attribute
* @return string
*/
protected function makeHref($item)
{
// If url attribute is available, use it to make the href.
// If url attribute is available, use it to make the href property.
// Otherwise, check if route attribute is available.

if (isset($item['url'])) {
return $this->urlGenerator->to($item['url']);
if (! empty($item['url'])) {
return url($item['url']);
} elseif (! empty($item['route'])) {
return $this->makeHrefFromRouteAttr($item['route']);
}

// When url is not available, check for route attribute.
// When url and route are not available, return a default value.

if (isset($item['route'])) {
if (is_array($item['route'])) {
$route = $item['route'][0];
$params = is_array($item['route'][1]) ? $item['route'][1] : [];
return '#';
}

return $this->urlGenerator->route($route, $params);
}
/**
* Make and return the href HTML attribute fom the route attribute of a
* menu item.
*
* @param mixed $routeAttr The route attribute of a menu item
* @return string
*/
protected function makeHrefFromRouteAttr($routeAttr)
{
$routeName = $routeParams = null;

return $this->urlGenerator->route($item['route']);
}
// Check type of the route attribute.

// When no url or route, return a default value.
if (is_array($routeAttr)) {
$routeName = $routeAttr[0] ?? null;
$routeParams = is_array($routeAttr[1]) ? $routeAttr[1] : null;
} elseif (is_string($routeAttr)) {
$routeName = $routeAttr;
}

return '#';
return $routeName ? route($routeName, $routeParams) : '#';
}
}
Loading