Skip to content
This repository was archived by the owner on Sep 16, 2021. It is now read-only.

Commit 85a7911

Browse files
authored
Use RequestStack in voters (#305)
* Update UriPrefixVoter.php * refactor voters to use request stack instead of letting knp menu inject the request
1 parent df79259 commit 85a7911

7 files changed

+247
-77
lines changed

src/Resources/config/voters.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
<services>
88

99
<service id="cmf_menu.current_item_voter.uri_prefix" class="Symfony\Cmf\Bundle\MenuBundle\Voter\UriPrefixVoter">
10-
<tag name="knp_menu.voter" request="true"/>
10+
<argument type="service" id="request_stack"/>
11+
<tag name="knp_menu.voter"/>
1112
</service>
1213

1314
<service id="cmf_menu.current_item_voter.content_identity" class="Symfony\Cmf\Bundle\MenuBundle\Voter\RequestContentIdentityVoter">
1415
<argument>%cmf_menu.content_key%</argument>
15-
16-
<tag name="knp_menu.voter" request="true"/>
16+
<argument type="service" id="request_stack"/>
17+
<tag name="knp_menu.voter"/>
1718
</service>
1819

1920
</services>

src/Voter/RequestContentIdentityVoter.php

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Knp\Menu\ItemInterface;
1515
use Knp\Menu\Matcher\Voter\VoterInterface;
1616
use Symfony\Component\HttpFoundation\Request;
17+
use Symfony\Component\HttpFoundation\RequestStack;
1718

1819
/**
1920
* This voter compares whether a key in the request is identical to the content
@@ -31,6 +32,11 @@ class RequestContentIdentityVoter implements VoterInterface
3132
*/
3233
private $requestKey;
3334

35+
/**
36+
* @var RequestStack|null
37+
*/
38+
private $requestStack;
39+
3440
/**
3541
* @var Request|null
3642
*/
@@ -40,32 +46,55 @@ class RequestContentIdentityVoter implements VoterInterface
4046
* @param string $requestKey The key to look up the content in the request
4147
* attributes
4248
*/
43-
public function __construct($requestKey)
49+
public function __construct($requestKey, RequestStack $requestStack = null)
4450
{
4551
$this->requestKey = $requestKey;
52+
$this->requestStack = $requestStack;
4653
}
4754

55+
/**
56+
* @deprecated since version 2.2. Pass a RequestStack to the constructor instead.
57+
*/
4858
public function setRequest(Request $request = null)
4959
{
60+
@trigger_error(
61+
sprintf(
62+
'The %s() method is deprecated since version 2.2.
63+
Pass a Symfony\Component\HttpFoundation\RequestStack
64+
in the constructor instead.',
65+
__METHOD__),
66+
E_USER_DEPRECATED
67+
);
68+
5069
$this->request = $request;
5170
}
5271

5372
/**
5473
* {@inheritdoc}
5574
*/
56-
public function matchItem(ItemInterface $item = null)
75+
public function matchItem(ItemInterface $item)
5776
{
58-
if (!$this->request) {
77+
$request = $this->getRequest();
78+
if (!$request) {
5979
return;
6080
}
6181

6282
$content = $item->getExtra('content');
6383

6484
if (null !== $content
65-
&& $this->request->attributes->has($this->requestKey)
66-
&& $this->request->attributes->get($this->requestKey) === $content
85+
&& $request->attributes->has($this->requestKey)
86+
&& $request->attributes->get($this->requestKey) === $content
6787
) {
6888
return true;
6989
}
7090
}
91+
92+
private function getRequest()
93+
{
94+
if ($this->requestStack) {
95+
return $this->requestStack->getMasterRequest();
96+
}
97+
98+
return $this->request;
99+
}
71100
}

src/Voter/RequestParentContentIdentityVoter.php

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Knp\Menu\ItemInterface;
1515
use Knp\Menu\Matcher\Voter\VoterInterface;
1616
use Symfony\Component\HttpFoundation\Request;
17+
use Symfony\Component\HttpFoundation\RequestStack;
1718

1819
/**
1920
* A variant of the RequestContentIdentityVoter that checks if the request
@@ -37,46 +38,75 @@ class RequestParentContentIdentityVoter implements VoterInterface
3738
*/
3839
private $childClass;
3940

41+
/**
42+
* @var RequestStack|null
43+
*/
44+
private $requestStack;
45+
4046
/**
4147
* @var Request|null
4248
*/
4349
private $request;
4450

4551
/**
46-
* @param string $requestKey The key to look up the content in the request
47-
* attributes
48-
* @param string $childClass Fully qualified class name of the model class
49-
* the content in the request must have to
50-
* attempt calling getParentDocument on it
52+
* @param string $requestKey The key to look up the content in the request
53+
* attributes
54+
* @param string $childClass Fully qualified class name of the model class
55+
* the content in the request must have to
56+
* attempt calling getParentDocument on it
57+
* @param RequestStack|null $requestStack
5158
*/
52-
public function __construct($requestKey, $childClass)
59+
public function __construct($requestKey, $childClass, RequestStack $requestStack = null)
5360
{
5461
$this->requestKey = $requestKey;
5562
$this->childClass = $childClass;
63+
$this->requestStack = $requestStack;
5664
}
5765

66+
/**
67+
* @deprecated since version 2.2. Pass a RequestStack to the constructor instead.
68+
*/
5869
public function setRequest(Request $request = null)
5970
{
71+
@trigger_error(
72+
sprintf(
73+
'The %s() method is deprecated since version 2.2.
74+
Pass a Symfony\Component\HttpFoundation\RequestStack
75+
in the constructor instead.',
76+
__METHOD__),
77+
E_USER_DEPRECATED
78+
);
79+
6080
$this->request = $request;
6181
}
6282

6383
/**
6484
* {@inheritdoc}
6585
*/
66-
public function matchItem(ItemInterface $item = null)
86+
public function matchItem(ItemInterface $item)
6787
{
68-
if (!$this->request) {
88+
$request = $this->getRequest();
89+
if (!$request) {
6990
return;
7091
}
7192

7293
$content = $item->getExtra('content');
7394

7495
if (null !== $content
75-
&& $this->request->attributes->has($this->requestKey)
76-
&& $this->request->attributes->get($this->requestKey) instanceof $this->childClass
77-
&& $this->request->attributes->get($this->requestKey)->getParentDocument() === $content
96+
&& $request->attributes->has($this->requestKey)
97+
&& $request->attributes->get($this->requestKey) instanceof $this->childClass
98+
&& $request->attributes->get($this->requestKey)->getParentDocument() === $content
7899
) {
79100
return true;
80101
}
81102
}
103+
104+
private function getRequest()
105+
{
106+
if ($this->requestStack) {
107+
return $this->requestStack->getMasterRequest();
108+
}
109+
110+
return $this->request;
111+
}
82112
}

src/Voter/UriPrefixVoter.php

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Knp\Menu\ItemInterface;
1515
use Knp\Menu\Matcher\Voter\VoterInterface;
1616
use Symfony\Component\HttpFoundation\Request;
17+
use Symfony\Component\HttpFoundation\RequestStack;
1718
use Symfony\Component\Routing\Route;
1819

1920
/**
@@ -31,12 +32,36 @@
3132
class UriPrefixVoter implements VoterInterface
3233
{
3334
/**
35+
* @var RequestStack|null
36+
*/
37+
private $requestStack;
38+
39+
/**
40+
* @deprecated Use the request stack instead
41+
*
3442
* @var Request|null
3543
*/
3644
private $request;
3745

46+
public function __construct(RequestStack $requestStack = null)
47+
{
48+
$this->requestStack = $requestStack;
49+
}
50+
51+
/**
52+
* @deprecated since version 2.2. Pass a RequestStack to the constructor instead.
53+
*/
3854
public function setRequest(Request $request = null)
3955
{
56+
@trigger_error(
57+
sprintf(
58+
'The %s() method is deprecated since version 2.2.
59+
Pass a Symfony\Component\HttpFoundation\RequestStack
60+
in the constructor instead.',
61+
__METHOD__),
62+
E_USER_DEPRECATED
63+
);
64+
4065
$this->request = $request;
4166
}
4267

@@ -45,18 +70,28 @@ public function setRequest(Request $request = null)
4570
*/
4671
public function matchItem(ItemInterface $item)
4772
{
48-
if (!$this->request) {
73+
$request = $this->getRequest();
74+
if (!$request) {
4975
return;
5076
}
5177

5278
$content = $item->getExtra('content');
5379

5480
if ($content instanceof Route && $content->hasOption('currentUriPrefix')) {
5581
$currentUriPrefix = $content->getOption('currentUriPrefix');
56-
$currentUriPrefix = str_replace('{_locale}', $this->request->getLocale(), $currentUriPrefix);
57-
if (0 === strncmp($this->request->getPathInfo(), $currentUriPrefix, strlen($currentUriPrefix))) {
82+
$currentUriPrefix = str_replace('{_locale}', $request->getLocale(), $currentUriPrefix);
83+
if (0 === strncmp($request->getPathInfo(), $currentUriPrefix, strlen($currentUriPrefix))) {
5884
return true;
5985
}
6086
}
6187
}
88+
89+
private function getRequest()
90+
{
91+
if ($this->requestStack) {
92+
return $this->requestStack->getMasterRequest();
93+
}
94+
95+
return $this->request;
96+
}
6297
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony CMF package.
5+
*
6+
* (c) 2011-2017 Symfony CMF
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Cmf\Bundle\MenuBundle\Tests\Unit\Voter;
13+
14+
use Symfony\Cmf\Bundle\MenuBundle\Voter\RequestContentIdentityVoter;
15+
use Symfony\Component\HttpFoundation\Request;
16+
17+
/**
18+
* @legacy
19+
*/
20+
class LegacyRequestContentIdentityVoterTest extends RequestContentIdentityVoterTestCase
21+
{
22+
protected function buildVoter(Request $request)
23+
{
24+
$voter = new RequestContentIdentityVoter('_content');
25+
$voter->setRequest($request);
26+
27+
return $voter;
28+
}
29+
30+
public function testSkipsWhenNoRequestIsAvailable()
31+
{
32+
$this->voter->setRequest(null);
33+
34+
$this->assertNull($this->voter->matchItem($this->createItem()));
35+
}
36+
}

tests/Unit/Voter/RequestContentIdentityVoterTest.php

Lines changed: 9 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -12,69 +12,23 @@
1212
namespace Symfony\Cmf\Bundle\MenuBundle\Tests\Unit\Voter;
1313

1414
use Symfony\Cmf\Bundle\MenuBundle\Voter\RequestContentIdentityVoter;
15+
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\HttpFoundation\RequestStack;
1517

16-
class RequestContentIdentityVoterTest extends \PHPUnit_Framework_TestCase
18+
class RequestContentIdentityVoterTest extends RequestContentIdentityVoterTestCase
1719
{
18-
private $voter;
19-
20-
private $request;
21-
22-
protected function setUp()
20+
protected function buildVoter(Request $request)
2321
{
24-
$this->request = $this->prophesize('Symfony\Component\HttpFoundation\Request');
25-
26-
$this->voter = new RequestContentIdentityVoter('_content');
27-
$this->voter->setRequest($this->request->reveal());
28-
}
22+
$requestStack = new RequestStack();
23+
$requestStack->push($request);
2924

30-
public function testSkipsWhenNoContentIsAvailable()
31-
{
32-
$this->assertNull($this->voter->matchItem($this->createItem()));
25+
return new RequestContentIdentityVoter('_content', $requestStack);
3326
}
3427

3528
public function testSkipsWhenNoRequestIsAvailable()
3629
{
37-
$this->voter->setRequest(null);
38-
39-
$this->assertNull($this->voter->matchItem($this->createItem()));
40-
}
41-
42-
public function testSkipsWhenNoContentAttributeWasDefined()
43-
{
44-
$attributes = $this->prophesize('Symfony\Component\HttpFoundation\ParameterBag');
45-
$attributes->has('_content')->willReturn(false);
46-
$this->request->attributes = $attributes;
47-
48-
$this->assertNull($this->voter->matchItem($this->createItem(new \stdClass())));
49-
}
50-
51-
public function testMatchesWhenContentIsEqualToCurrentContent()
52-
{
53-
$content = new \stdClass();
54-
55-
$attributes = $this->prophesize('Symfony\Component\HttpFoundation\ParameterBag');
56-
$attributes->has('_content')->willReturn(true);
57-
$attributes->get('_content')->willReturn($content);
58-
$this->request->attributes = $attributes;
59-
60-
$this->assertTrue($this->voter->matchItem($this->createItem($content)));
61-
}
62-
63-
public function testSkipsWhenContentIsNotEqual()
64-
{
65-
$attributes = $this->prophesize('Symfony\Component\HttpFoundation\ParameterBag');
66-
$attributes->has('_content')->willReturn(true);
67-
$attributes->get('_content')->willReturn(new \stdClass());
68-
$this->request->attributes = $attributes;
69-
70-
$this->assertNull($this->voter->matchItem($this->createItem(new \stdClass())));
71-
}
72-
73-
private function createItem($content = null)
74-
{
75-
$item = $this->prophesize('Knp\Menu\ItemInterface');
76-
$item->getExtra('content')->willReturn($content);
30+
$voter = new RequestContentIdentityVoter('_content', new RequestStack());
7731

78-
return $item->reveal();
32+
$this->assertNull($voter->matchItem($this->createItem()));
7933
}
8034
}

0 commit comments

Comments
 (0)