Skip to content

Commit

Permalink
add ability to match request for node activation (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
dmaicher authored Aug 29, 2024
1 parent d813fdb commit ab7a0c9
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 4 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ class MainMenuTreeBuilder implements MenuTreeBuilderInterface
->child('stream')
->setRoute('social_media_stream')
->setRequiredPermissions(['ROLE_SOCIAL_STREAM'])
->setAdditionalActiveRequestMatcher(static function (Request $request): bool {
// additionally will mark node as active if the request path starts with '/foo_bar'
return str_starts_with($request->getPathInfo(), '/foo_bar');
})
->end()
->child('update_status')
->setRoute('social_media_update_status')
Expand Down
26 changes: 26 additions & 0 deletions src/Node/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace DAMA\MenuBundle\Node;

use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\HttpFoundation\Request;

class Node
{
Expand Down Expand Up @@ -46,6 +47,11 @@ class Node
*/
protected $additionalActiveRoutes = [];

/**
* @var callable(Request): bool|null
*/
protected $additionalActiveRequestMatcher;

/**
* @var array<string|Expression|mixed>
*/
Expand Down Expand Up @@ -456,4 +462,24 @@ public static function resetCounter(): void
{
self::$counter = 0;
}

/**
* @return callable(Request): bool|null
*/
public function getAdditionalActiveRequestMatcher(): ?callable
{
return $this->additionalActiveRequestMatcher;
}

/**
* @param callable(Request): bool|null $additionalActiveRequestMatcher
*
* @return $this
*/
public function setAdditionalActiveRequestMatcher(?callable $additionalActiveRequestMatcher): self
{
$this->additionalActiveRequestMatcher = $additionalActiveRequestMatcher;

return $this;
}
}
13 changes: 9 additions & 4 deletions src/NodeVisitor/NodeActivator.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@
*/
final class NodeActivator implements NodeVisitorInterface
{
/**
* @var RequestStack
*/
private $requestStack;
private RequestStack $requestStack;

public function __construct(RequestStack $requestStack)
{
Expand All @@ -28,6 +25,14 @@ public function visit(Node $node): void

if (in_array($request->get('_route'), $node->getAllActiveRoutes())) {
$node->setActive(true);

return;
}

if (($callable = $node->getAdditionalActiveRequestMatcher())
&& $callable($request)
) {
$node->setActive(true);
}
}
}
4 changes: 4 additions & 0 deletions tests/Functional/FunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public function testRenderMenuWithUserFoo(): void

$this->assertCount(2, $crawler->filter('a[href="/test_2"]'));
$this->assertCount(0, $crawler->filter('a[href="/test_1"]'));

$crawler = $client->request('GET', '/test_3');
$this->assertSame(200, $client->getResponse()->getStatusCode());
$this->assertCount(2, $crawler->filter('li.menu-item-active > a[href="/test_2"]'));
}

public function testRenderMenuWithUserBar(): void
Expand Down
4 changes: 4 additions & 0 deletions tests/Functional/TestMenuTreeBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use DAMA\MenuBundle\MenuTree\MenuTreeBuilderInterface;
use DAMA\MenuBundle\Node\Node;
use Symfony\Component\HttpFoundation\Request;

class TestMenuTreeBuilder implements MenuTreeBuilderInterface
{
Expand All @@ -29,6 +30,9 @@ public function build(Node $root): void
->end()
->child('bar-sub-2')
->setRoute('test_2')
->setAdditionalActiveRequestMatcher(static function (Request $request): bool {
return str_starts_with($request->getPathInfo(), '/test_');
})
->end()
->end()
;
Expand Down
6 changes: 6 additions & 0 deletions tests/Functional/routing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ test_2:
controller: 'Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction'
defaults:
template: test_menu.html.twig

test_3:
path: /test_3
controller: 'Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction'
defaults:
template: test_menu.html.twig

0 comments on commit ab7a0c9

Please sign in to comment.