4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\HttpKernel\Tests\DataCollector;
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\HttpFoundation\ParameterBag;
16 use Symfony\Component\HttpFoundation\RedirectResponse;
17 use Symfony\Component\HttpFoundation\Session\Session;
18 use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
19 use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
20 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
21 use Symfony\Component\HttpKernel\HttpKernel;
22 use Symfony\Component\HttpKernel\HttpKernelInterface;
23 use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector;
24 use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
25 use Symfony\Component\HttpFoundation\Request;
26 use Symfony\Component\HttpFoundation\Response;
27 use Symfony\Component\HttpFoundation\Cookie;
28 use Symfony\Component\EventDispatcher\EventDispatcher;
30 class RequestDataCollectorTest extends TestCase
32 public function testCollect()
34 $c = new RequestDataCollector();
36 $c->collect($request = $this->createRequest(), $this->createResponse());
39 $attributes = $c->getRequestAttributes();
41 $this->assertSame('request', $c->getName());
42 $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestHeaders());
43 $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestServer());
44 $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestCookies());
45 $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $attributes);
46 $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestRequest());
47 $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestQuery());
48 $this->assertInstanceOf(ParameterBag::class, $c->getResponseCookies());
49 $this->assertSame('html', $c->getFormat());
50 $this->assertEquals('foobar', $c->getRoute());
51 $this->assertEquals(array('name' => 'foo'), $c->getRouteParams());
52 $this->assertSame(array(), $c->getSessionAttributes());
53 $this->assertSame('en', $c->getLocale());
54 $this->assertContains(__FILE__, $attributes->get('resource'));
55 $this->assertSame('stdClass', $attributes->get('object')->getType());
57 $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getResponseHeaders());
58 $this->assertSame('OK', $c->getStatusText());
59 $this->assertSame(200, $c->getStatusCode());
60 $this->assertSame('application/json', $c->getContentType());
63 public function testCollectWithoutRouteParams()
65 $request = $this->createRequest(array());
67 $c = new RequestDataCollector();
68 $c->collect($request, $this->createResponse());
71 $this->assertEquals(array(), $c->getRouteParams());
75 * @dataProvider provideControllerCallables
77 public function testControllerInspection($name, $callable, $expected)
79 $c = new RequestDataCollector();
80 $request = $this->createRequest();
81 $response = $this->createResponse();
82 $this->injectController($c, $callable, $request);
83 $c->collect($request, $response);
86 $this->assertSame($expected, $c->getController()->getValue(true), sprintf('Testing: %s', $name));
89 public function provideControllerCallables()
91 // make sure we always match the line number
92 $r1 = new \ReflectionMethod($this, 'testControllerInspection');
93 $r2 = new \ReflectionMethod($this, 'staticControllerMethod');
94 $r3 = new \ReflectionClass($this);
96 // test name, callable, expected
100 array($this, 'testControllerInspection'),
102 'class' => __NAMESPACE__.'\RequestDataCollectorTest',
103 'method' => 'testControllerInspection',
105 'line' => $r1->getStartLine(),
111 function () { return 'foo'; },
113 'class' => __NAMESPACE__.'\{closure}',
116 'line' => __LINE__ - 5,
121 'Static callback as string',
122 __NAMESPACE__.'\RequestDataCollectorTest::staticControllerMethod',
124 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest',
125 'method' => 'staticControllerMethod',
127 'line' => $r2->getStartLine(),
132 'Static callable with instance',
133 array($this, 'staticControllerMethod'),
135 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest',
136 'method' => 'staticControllerMethod',
138 'line' => $r2->getStartLine(),
143 'Static callable with class name',
144 array('Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'staticControllerMethod'),
146 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest',
147 'method' => 'staticControllerMethod',
149 'line' => $r2->getStartLine(),
154 'Callable with instance depending on __call()',
155 array($this, 'magicMethod'),
157 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest',
158 'method' => 'magicMethod',
165 'Callable with class name depending on __callStatic()',
166 array('Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'magicMethod'),
168 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest',
169 'method' => 'magicMethod',
176 'Invokable controller',
179 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest',
182 'line' => $r3->getStartLine(),
188 public function testItIgnoresInvalidCallables()
190 $request = $this->createRequestWithSession();
191 $response = new RedirectResponse('/');
193 $c = new RequestDataCollector();
194 $c->collect($request, $response);
196 $this->assertSame('n/a', $c->getController());
199 public function testItAddsRedirectedAttributesWhenRequestContainsSpecificCookie()
201 $request = $this->createRequest();
202 $request->cookies->add(array(
203 'sf_redirect' => '{}',
206 $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock();
208 $c = new RequestDataCollector();
209 $c->onKernelResponse(new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $this->createResponse()));
211 $this->assertTrue($request->attributes->get('_redirected'));
214 public function testItSetsARedirectCookieIfTheResponseIsARedirection()
216 $c = new RequestDataCollector();
218 $response = $this->createResponse();
219 $response->setStatusCode(302);
220 $response->headers->set('Location', '/somewhere-else');
222 $c->collect($request = $this->createRequest(), $response);
225 $cookie = $this->getCookieByName($response, 'sf_redirect');
227 $this->assertNotEmpty($cookie->getValue());
230 public function testItCollectsTheRedirectionAndClearTheCookie()
232 $c = new RequestDataCollector();
234 $request = $this->createRequest();
235 $request->attributes->set('_redirected', true);
236 $request->cookies->add(array(
237 'sf_redirect' => '{"method": "POST"}',
240 $c->collect($request, $response = $this->createResponse());
243 $this->assertEquals('POST', $c->getRedirect()['method']);
245 $cookie = $this->getCookieByName($response, 'sf_redirect');
246 $this->assertNull($cookie->getValue());
249 protected function createRequest($routeParams = array('name' => 'foo'))
251 $request = Request::create('http://test.com/foo?bar=baz');
252 $request->attributes->set('foo', 'bar');
253 $request->attributes->set('_route', 'foobar');
254 $request->attributes->set('_route_params', $routeParams);
255 $request->attributes->set('resource', fopen(__FILE__, 'r'));
256 $request->attributes->set('object', new \stdClass());
261 private function createRequestWithSession()
263 $request = $this->createRequest();
264 $request->attributes->set('_controller', 'Foo::bar');
265 $request->setSession(new Session(new MockArraySessionStorage()));
266 $request->getSession()->start();
271 protected function createResponse()
273 $response = new Response();
274 $response->setStatusCode(200);
275 $response->headers->set('Content-Type', 'application/json');
276 $response->headers->set('X-Foo-Bar', null);
277 $response->headers->setCookie(new Cookie('foo', 'bar', 1, '/foo', 'localhost', true, true));
278 $response->headers->setCookie(new Cookie('bar', 'foo', new \DateTime('@946684800')));
279 $response->headers->setCookie(new Cookie('bazz', 'foo', '2000-12-12'));
285 * Inject the given controller callable into the data collector.
287 protected function injectController($collector, $controller, $request)
289 $resolver = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface')->getMock();
290 $httpKernel = new HttpKernel(new EventDispatcher(), $resolver, null, $this->getMockBuilder(ArgumentResolverInterface::class)->getMock());
291 $event = new FilterControllerEvent($httpKernel, $controller, $request, HttpKernelInterface::MASTER_REQUEST);
292 $collector->onKernelController($event);
296 * Dummy method used as controller callable.
298 public static function staticControllerMethod()
300 throw new \LogicException('Unexpected method call');
304 * Magic method to allow non existing methods to be called and delegated.
306 public function __call($method, $args)
308 throw new \LogicException('Unexpected method call');
312 * Magic method to allow non existing methods to be called and delegated.
314 public static function __callStatic($method, $args)
316 throw new \LogicException('Unexpected method call');
319 public function __invoke()
321 throw new \LogicException('Unexpected method call');
324 private function getCookieByName(Response $response, $name)
326 foreach ($response->headers->getCookies() as $cookie) {
327 if ($cookie->getName() == $name) {
332 throw new \InvalidArgumentException(sprintf('Cookie named "%s" is not in response', $name));