8000 [FrameworkBundle] Add new TemplateResponse class by pierredup · Pull Request #21765 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[FrameworkBundle] Add new TemplateResponse class #21765

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

Closed
wants to merge 9 commits into from
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\EventListener;

use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Bundle\FrameworkBundle\Templating\TemplatedResponseInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
* @author Pierre du Plessis <pdples@gmail.com>
*/
class TemplateListener implements EventSubscriberInterface
{
private $templating;

public function __construct(EngineInterface $templating)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having a hard dependency to the templating component is not fine IMO, as we worked very hard to make it possible to use Twig natively without wrapping it in the Templating component.

{
$this->templating = $templating;
}

public static function getSubscribedEvents()
{
return array(
KernelEvents::VIEW => array('onView', 128),
);
}

public function onView(GetResponseForControllerResultEvent $event)
{
$result = $event->getControllerResult();

if (!$result instanceof TemplatedResponseInterface) {
return;
}

$response = $result->getResponse($this->templating);

if (!$response instanceof Response) {
$msg = sprintf('The method %s::getResponse() must return a response (%s given).', get_class($result), is_object($response) ? get_class($response) : gettype($response));

throw new \LogicException($msg);
}

$event->setResponse($response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,10 @@
</service>

<service id="templating.loader" alias="templating.loader.filesystem" />

<service id="templating.listener" class="Symfony\Bundle\FrameworkBundle\EventListener\TemplateListener">
<tag name="kernel.event_subscriber" />
<argument type="service" id="templating" />
</service>
</services>
</container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\Templating;

use Symfony\Component\HttpFoundation\Response;

/**
* @author Pierre du Plessis <pdples@gmail.com>
*/
class TemplatedResponse implements TemplatedResponseInterface
{
private $template;
private $parameters;
private $response;

public function __construct($template, array $parameters = array(), Response $response = null)
{
$this->template = $template;
$this->parameters = $parameters;
$this->response = $response ?: new Response();
}

/**
* {@inheritdoc}
*/
public function getResponse(EngineInterface $templating)
{
return $templating->renderResponse($this->template, $this->parameters, $this->response);
}
}
< 8000 /tbody>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\Templating;

use Symfony\Component\HttpFoundation\Response;

/**
* @author Pierre du Plessis <pdples@gmail.com>
*/
interface TemplatedResponseInterface
{
/**
* @param EngineInterface $templating
*
* @return Response
*/
public function getResponse(EngineInterface $templating);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\Tests\EventListener;

use Symfony\Bundle\FrameworkBundle\EventListener\TemplateListener;
use Symfony\Bundle\FrameworkBundle\Templating\PhpEngine;
use Symfony\Bundle\FrameworkBundle\Templating\TemplatedResponse;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
use Symfony\Bundle\FrameworkBundle\Templating\TemplatedResponseInterface;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Templating\Loader\Loader;
use Symfony\Component\Templating\Storage\StringStorage;
use Symfony\Component\Templating\TemplateNameParser;
use Symfony\Component\Templating\TemplateReferenceInterface;

class TemplateListenerTest extends TestCase
{
public function testTemplateReference()
{
$template = new TemplatedResponse('dummy_template.html.php', array('var' => 'dummy'));

$event = $this->getEvent($template);

$listener = new TemplateListener($this->getPhpEngine());
$listener->onView($event);

$response = $event->getResponse();

$this->assertSame('This is dummy content', $response->getContent());
$this->assertSame(200, $response->getStatusCode());
}

public function testInvalidResponse()
{
$templating = $this->getPhpEngine();

$template = $this->getMockBuilder(TemplatedResponseInterface::class)->getMock();
$template->expects($this->once())
->method('getResponse')
->with($templating)
->will($this->throwException(new \LogicException()));

$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('LogicException');

$event = $this->getEvent($template);

$listener = new TemplateListener($templating);
$listener->onView($event);
}

private function getEvent($template)
{
$request = new Request(array(), array(), array());
$mockKernel = $this->getMockForAbstractClass('Symfony\Component\HttpKernel\Kernel', array('', ''));

return new GetResponseForControllerResultEvent($mockKernel, $request, Kernel::MASTER_REQUEST, $template);
}

private function getPhpEngine()
{
$container = new Container();
$loader = new ProjectTemplateLoader();

$loader->templates['dummy_template.html.php'] = 'This is <?= $var ?> content';

$engine = new PhpEngine(new TemplateNameParser(), $container, $loader);

return $engine;
}
}

class ProjectTemplateLoader extends Loader
{
public $templates = array();

public function setTemplate($name, $content)
{
$template = new TemplateReference($name, 'php');
$this->templates[$template->getLogicalName()] = $content;
}

public function load(TemplateReferenceInterface $template)
{
if (isset($this->templates[$template->getLogicalName()])) {
return new StringStorage($this->templates[$template->getLogicalName()]);
}

return false;
}

public function isFresh(TemplateReferenceInterface $template, $time)
{
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\Tests\Templating;

use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Bundle\FrameworkBundle\Templating\TemplatedResponse;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Component\HttpFoundation\Response;

class TemplatedResponseTest extends TestCase
{
public function testResponse()
{
$templating = $this->getMockBuilder(EngineInterface::class)->getMock();

$templating->expects($this->once())
->method('renderResponse')
->with('dummy_template.html.php', array('var' => 'dummy'))
->will($this->returnValue(new Response()));

$templateResponse = new TemplatedResponse('dummy_template.html.php', array('var' => 'dummy'));

$this->assertInstanceOf(Response::class, $templateResponse->getResponse($templating));
}

public function testSameResponse()
{
$templating = $this->getMockBuilder(EngineInterface::class)->getMock();

$response = new Response();
$templating->expects($this->once())
->method('renderResponse')
->with('dummy_template.html.php', array('var' => 'dummy'))
->will($this->returnValue($response));

$templateResponse = new TemplatedResponse('dummy_template.html.php', array('var' => 'dummy'), $response);

$this->assertSame($response, $templateResponse->getResponse($templating));
}
}
0