[Templating] fix logic regarding template references and many phpdocs

This commit is contained in:
Tobias Schultze 2013-09-04 14:01:22 +02:00 committed by Fabien Potencier
parent 164c1cbfec
commit f6c12bd6de
22 changed files with 142 additions and 174 deletions

View File

@ -12,6 +12,7 @@
namespace Symfony\Bridge\Twig\Tests;
use Symfony\Bridge\Twig\TwigEngine;
use Symfony\Component\Templating\TemplateReference;
class TwigEngineTest extends \PHPUnit_Framework_TestCase
{
@ -27,6 +28,7 @@ class TwigEngineTest extends \PHPUnit_Framework_TestCase
$engine = $this->getTwig();
$this->assertFalse($engine->exists('foobar'));
$this->assertFalse($engine->exists(new TemplateReference('foorbar')));
}
public function testExistsWithTemplateWithSyntaxErrors()
@ -34,6 +36,7 @@ class TwigEngineTest extends \PHPUnit_Framework_TestCase
$engine = $this->getTwig();
$this->assertTrue($engine->exists('error'));
$this->assertTrue($engine->exists(new TemplateReference('error')));
}
public function testExists()
@ -41,6 +44,25 @@ class TwigEngineTest extends \PHPUnit_Framework_TestCase
$engine = $this->getTwig();
$this->assertTrue($engine->exists('index'));
$this->assertTrue($engine->exists(new TemplateReference('index')));
}
public function testRender()
{
$engine = $this->getTwig();
$this->assertSame('foo', $engine->render('index'));
$this->assertSame('foo', $engine->render(new TemplateReference('index')));
}
/**
* @expectedException \Twig_Error_Syntax
*/
public function testRenderWithError()
{
$engine = $this->getTwig();
$engine->render(new TemplateReference('error'));
}
protected function getTwig()

View File

@ -14,6 +14,7 @@ namespace Symfony\Bridge\Twig;
use Symfony\Component\Templating\EngineInterface;
use Symfony\Component\Templating\StreamingEngineInterface;
use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\Templating\TemplateReferenceInterface;
/**
* This engine knows how to render Twig templates.
@ -38,15 +39,11 @@ class TwigEngine implements EngineInterface, StreamingEngineInterface
}
/**
* Renders a template.
* {@inheritdoc}
*
* @param mixed $name A template name
* @param array $parameters An array of parameters to pass to the template
* It also supports \Twig_Template as name parameter.
*
* @return string The evaluated template as a string
*
* @throws \InvalidArgumentException if the template does not exist
* @throws \RuntimeException if the template cannot be rendered
* @throws \Twig_Error if something went wrong like a thrown exception while rendering the template
*/
public function render($name, array $parameters = array())
{
@ -54,12 +51,11 @@ class TwigEngine implements EngineInterface, StreamingEngineInterface
}
/**
* Streams a template.
* {@inheritdoc}
*
* @param mixed $name A template name or a TemplateReferenceInterface instance
* @param array $parameters An array of parameters to pass to the template
* It also supports \Twig_Template as name parameter.
*
* @throws \RuntimeException if the template cannot be rendered
* @throws \Twig_Error if something went wrong like a thrown exception while rendering the template
*/
public function stream($name, array $parameters = array())
{
@ -67,11 +63,9 @@ class TwigEngine implements EngineInterface, StreamingEngineInterface
}
/**
* Returns true if the template exists.
* {@inheritdoc}
*
* @param mixed $name A template name
*
* @return Boolean true if the template exists, false otherwise
* It also supports \Twig_Template as name parameter.
*/
public function exists($name)
{
@ -82,11 +76,13 @@ class TwigEngine implements EngineInterface, StreamingEngineInterface
$loader = $this->environment->getLoader();
if ($loader instanceof \Twig_ExistsLoaderInterface) {
return $loader->exists($name);
return $loader->exists((string) $name);
}
try {
$loader->getSource($name);
// cast possible TemplateReferenceInterface to string because the
// EngineInterface supports them but Twig_LoaderInterface does not
$loader->getSource((string) $name);
} catch (\Twig_Error_Loader $e) {
return false;
}
@ -95,11 +91,9 @@ class TwigEngine implements EngineInterface, StreamingEngineInterface
}
/**
* Returns true if this class is able to render the given template.
* {@inheritdoc}
*
* @param string $name A template name
*
* @return Boolean True if this class supports the given resource, false otherwise
* It also supports \Twig_Template as name parameter.
*/
public function supports($name)
{
@ -115,7 +109,8 @@ class TwigEngine implements EngineInterface, StreamingEngineInterface
/**
* Loads the given template.
*
* @param mixed $name A template name or an instance of Twig_Template
* @param string|TemplateReferenceInterface|\Twig_Template $name A template name or an instance of
* TemplateReferenceInterface or \Twig_Template
*
* @return \Twig_TemplateInterface A \Twig_TemplateInterface instance
*
@ -128,7 +123,7 @@ class TwigEngine implements EngineInterface, StreamingEngineInterface
}
try {
return $this->environment->loadTemplate($name);
return $this->environment->loadTemplate((string) $name);
} catch (\Twig_Error_Loader $e) {
throw new \InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
}

View File

@ -30,14 +30,14 @@
"symfony/stopwatch": "~2.2"
},
"suggest": {
"symfony/form": "",
"symfony/http-kernel": "",
"symfony/routing": "",
"symfony/templating": "",
"symfony/translation": "",
"symfony/yaml": "",
"symfony/security": "",
"symfony/stopwatch": ""
"symfony/form": "For using the FormExtension",
"symfony/http-kernel": "For using the HttpKernelExtension",
"symfony/routing": "For using the RoutingExtension",
"symfony/templating": "For using the TwigEngine",
"symfony/translation": "For using the TranslationExtension",
"symfony/yaml": "For using the YamlExtension",
"symfony/security": "For using the SecurityExtension",
"symfony/stopwatch": "For using the StopwatchExtension"
},
"autoload": {
"psr-0": { "Symfony\\Bridge\\Twig\\": "" }

View File

@ -40,50 +40,42 @@ class DelegatingEngine extends BaseDelegatingEngine implements EngineInterface
/**
* {@inheritdoc}
*/
public function supports($name)
public function getEngine($name)
{
foreach ($this->engines as $i => $engine) {
if (is_string($engine)) {
$engine = $this->engines[$i] = $this->container->get($engine);
}
$this->resolveEngines();
if ($engine->supports($name)) {
return true;
}
}
return false;
return parent::getEngine($name);
}
/**
* {@inheritdoc}
*/
public function getEngine($name)
public function renderResponse($view, array $parameters = array(), Response $response = null)
{
foreach ($this->engines as $i => $engine) {
if (is_string($engine)) {
$engine = $this->engines[$i] = $this->container->get($engine);
}
$engine = $this->getEngine($view);
if ($engine->supports($name)) {
return $engine;
}
if ($engine instanceof EngineInterface) {
return $engine->renderResponse($view, $parameters, $response);
}
throw new \RuntimeException(sprintf('No engine is able to work with the template "%s".', $name));
if (null === $response) {
$response = new Response();
}
$response->setContent($engine->render($view, $parameters));
return $response;
}
/**
* Renders a view and returns a Response.
*
* @param string $view The view name
* @param array $parameters An array of parameters to pass to the view
* @param Response $response A Response instance
*
* @return Response A Response instance
* Resolved engine ids to their real engine instances from the container.
*/
public function renderResponse($view, array $parameters = array(), Response $response = null)
private function resolveEngines()
{
return $this->getEngine($view)->renderResponse($view, $parameters, $response);
foreach ($this->engines as $i => $engine) {
if (is_string($engine)) {
$this->engines[$i] = $this->container->get($engine);
}
}
}
}

View File

@ -29,6 +29,8 @@ interface EngineInterface extends BaseEngineInterface
* @param Response $response A Response instance
*
* @return Response A Response instance
*
* @throws \RuntimeException if the template cannot be rendered
*/
public function renderResponse($view, array $parameters = array(), Response $response = null);
}

View File

@ -36,11 +36,7 @@ class FilesystemLoader implements LoaderInterface
}
/**
* Loads a template.
*
* @param TemplateReferenceInterface $template A template
*
* @return FileStorage|Boolean false if the template cannot be loaded, a Storage instance otherwise
* {@inheritdoc}
*/
public function load(TemplateReferenceInterface $template)
{
@ -54,12 +50,7 @@ class FilesystemLoader implements LoaderInterface
}
/**
* Returns true if the template is still fresh.
*
* @param TemplateReferenceInterface $template The template name as an array
* @param integer $time The last modification time of the cached template (timestamp)
*
* @return Boolean
* {@inheritdoc}
*/
public function isFresh(TemplateReferenceInterface $template, $time)
{

View File

@ -66,7 +66,7 @@ class TemplateLocator implements FileLocatorInterface
public function locate($template, $currentPath = null, $first = true)
{
if (!$template instanceof TemplateReferenceInterface) {
throw new \InvalidArgumentException("The template must be an instance of TemplateReferenceInterface.");
throw new \InvalidArgumentException('The template must be an instance of TemplateReferenceInterface.');
}
$key = $this->getCacheKey($template);

View File

@ -46,7 +46,7 @@ class PhpEngine extends BasePhpEngine implements EngineInterface
}
/**
* @throws \InvalidArgumentException When the helper is not defined
* {@inheritdoc}
*/
public function get($name)
{
@ -71,13 +71,7 @@ class PhpEngine extends BasePhpEngine implements EngineInterface
}
/**
* Renders a view and returns a Response.
*
* @param string $view The view name
* @param array $parameters An array of parameters to pass to the view
* @param Response $response A Response instance
*
* @return Response A Response instance
* {@inheritdoc}
*/
public function renderResponse($view, array $parameters = array(), Response $response = null)
{

View File

@ -24,9 +24,13 @@ class TemplateFilenameParser implements TemplateNameParserInterface
/**
* {@inheritdoc}
*/
public function parse($file)
public function parse($name)
{
$parts = explode('/', strtr($file, '\\', '/'));
if ($name instanceof TemplateReferenceInterface) {
return $name;
}
$parts = explode('/', strtr($name, '\\', '/'));
$elements = explode('.', array_pop($parts));
if (3 > count($elements)) {

View File

@ -11,8 +11,6 @@
namespace Symfony\Bundle\FrameworkBundle\Templating;
use Symfony\Bundle\FrameworkBundle\Templating\PhpEngine;
use Symfony\Bundle\FrameworkBundle\Templating\GlobalVariables;
use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\Templating\Loader\LoaderInterface;

View File

@ -58,7 +58,7 @@ class DelegatingEngineTest extends \PHPUnit_Framework_TestCase
$delegatingEngine->getEngine('template.php', array('foo' => 'bar'));
}
public function testRenderResponse()
public function testRenderResponseWithFrameworkEngine()
{
$response = $this->getMock('Symfony\Component\HttpFoundation\Response');
$engine = $this->getFrameworkEngineMock('template.php', true);
@ -73,6 +73,15 @@ class DelegatingEngineTest extends \PHPUnit_Framework_TestCase
$this->assertSame($response, $delegatingEngine->renderResponse('template.php', array('foo' => 'bar')));
}
public function testRenderResponseWithTemplatingEngine()
{
$engine = $this->getEngineMock('template.php', true);
$container = $this->getContainerMock(array('engine' => $engine));
$delegatingEngine = new DelegatingEngine($container, array('engine'));
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $delegatingEngine->renderResponse('template.php', array('foo' => 'bar')));
}
private function getEngineMock($template, $supports)
{
$engine = $this->getMock('Symfony\Component\Templating\EngineInterface');

View File

@ -11,13 +11,13 @@
namespace Symfony\Bundle\TwigBundle\Loader;
use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\Templating\TemplateReferenceInterface;
/**
* FilesystemLoader extends the default Twig filesystem loader
* to work with the Symfony2 paths.
* to work with the Symfony2 paths and template references.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
@ -38,21 +38,22 @@ class FilesystemLoader extends \Twig_Loader_Filesystem
$this->locator = $locator;
$this->parser = $parser;
$this->cache = array();
}
/**
* {@inheritdoc}
*
* The name parameter might also be a TemplateReferenceInterface.
*/
public function exists($template)
public function exists($name)
{
if (parent::exists($template)) {
if (parent::exists((string) $name)) {
return true;
}
// same logic as findTemplate below for the fallback
try {
$this->cache[(string) $template] = $this->locator->locate($this->parser->parse($template));
$this->cache[(string) $name] = $this->locator->locate($this->parser->parse($name));
} catch (\Exception $e) {
return false;
}
@ -84,7 +85,7 @@ class FilesystemLoader extends \Twig_Loader_Filesystem
$file = null;
$previous = null;
try {
$file = parent::findTemplate($template);
$file = parent::findTemplate($logicalName);
} catch (\Twig_Error_Loader $e) {
$previous = $e;

View File

@ -11,11 +11,9 @@
namespace Symfony\Bundle\TwigBundle\Tests\Loader;
use Symfony\Bundle\TwigBundle\Tests\TestCase;
use Symfony\Bundle\TwigBundle\Loader\FilesystemLoader;
use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Bundle\TwigBundle\Loader\FilesystemLoader;
use Symfony\Bundle\TwigBundle\Tests\TestCase;
class FilesystemLoaderTest extends TestCase
{

View File

@ -62,16 +62,7 @@ class TwigEngine extends BaseEngine implements EngineInterface
}
/**
* Renders a template.
*
* @param mixed $name A template name
* @param array $parameters An array of parameters to pass to the template
*
* @return string The evaluated template as a string
*
* @throws \InvalidArgumentException if the template does not exist
* @throws \RuntimeException if the template cannot be rendered
* @throws \Twig_Error
* {@inheritdoc}
*/
public function render($name, array $parameters = array())
{
@ -91,13 +82,9 @@ class TwigEngine extends BaseEngine implements EngineInterface
}
/**
* Renders a view and returns a Response.
* {@inheritdoc}
*
* @param string $view The view name
* @param array $parameters An array of parameters to pass to the view
* @param Response $response A Response instance
*
* @return Response A Response instance
* @throws \Twig_Error if something went wrong like a thrown exception while rendering the template
*/
public function renderResponse($view, array $parameters = array(), Response $response = null)
{

View File

@ -106,7 +106,7 @@ class DelegatingEngine implements EngineInterface, StreamingEngineInterface
/**
* Get an engine able to render the given template.
*
* @param mixed $name A template name or a TemplateReferenceInterface instance
* @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
*
* @return EngineInterface The engine
*

View File

@ -23,7 +23,7 @@ namespace Symfony\Component\Templating;
* TemplateReferenceInterface, a TemplateNameParserInterface should be used to
* convert the name to a TemplateReferenceInterface instance.
*
* Each template loader use the logical template name to look for
* Each template loader uses the logical template name to look for
* the template.
*
* @author Fabien Potencier <fabien@symfony.com>
@ -35,8 +35,8 @@ interface EngineInterface
/**
* Renders a template.
*
* @param mixed $name A template name or a TemplateReferenceInterface instance
* @param array $parameters An array of parameters to pass to the template
* @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
* @param array $parameters An array of parameters to pass to the template
*
* @return string The evaluated template as a string
*
@ -49,10 +49,12 @@ interface EngineInterface
/**
* Returns true if the template exists.
*
* @param mixed $name A template name or a TemplateReferenceInterface instance
* @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
*
* @return Boolean true if the template exists, false otherwise
*
* @throws \RuntimeException if the engine cannot handle the template name
*
* @api
*/
public function exists($name);
@ -60,7 +62,7 @@ interface EngineInterface
/**
* Returns true if this class is able to render the given template.
*
* @param mixed $name A template name or a TemplateReferenceInterface instance
* @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
*
* @return Boolean true if this class supports the given template, false otherwise
*

View File

@ -71,15 +71,9 @@ class PhpEngine implements EngineInterface, \ArrayAccess
}
/**
* Renders a template.
*
* @param mixed $name A template name or a TemplateReferenceInterface instance
* @param array $parameters An array of parameters to pass to the template
*
* @return string The evaluated template as a string
* {@inheritdoc}
*
* @throws \InvalidArgumentException if the template does not exist
* @throws \RuntimeException if the template cannot be rendered
*
* @api
*/
@ -112,11 +106,7 @@ class PhpEngine implements EngineInterface, \ArrayAccess
}
/**
* Returns true if the template exists.
*
* @param mixed $name A template name or a TemplateReferenceInterface instance
*
* @return Boolean true if the template exists, false otherwise
* {@inheritdoc}
*
* @api
*/
@ -132,11 +122,7 @@ class PhpEngine implements EngineInterface, \ArrayAccess
}
/**
* Returns true if this class is able to render the given template.
*
* @param mixed $name A template name or a TemplateReferenceInterface instance
*
* @return Boolean true if this class supports the given resource, false otherwise
* {@inheritdoc}
*
* @api
*/
@ -567,7 +553,7 @@ class PhpEngine implements EngineInterface, \ArrayAccess
/**
* Loads the given template.
*
* @param mixed $name A template name or a TemplateReferenceInterface instance
* @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
*
* @return Storage A Storage instance
*

View File

@ -23,8 +23,8 @@ interface StreamingEngineInterface
*
* The implementation should output the content directly to the client.
*
* @param mixed $name A template name or a TemplateReferenceInterface instance
* @param array $parameters An array of parameters to pass to the template
* @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
* @param array $parameters An array of parameters to pass to the template
*
* @throws \RuntimeException if the template cannot be rendered
* @throws \LogicException if the template cannot be streamed

View File

@ -27,11 +27,7 @@ use Symfony\Component\Templating\TemplateReference;
class TemplateNameParser implements TemplateNameParserInterface
{
/**
* Parses a template to an array of parameters.
*
* @param string $name A template name
*
* @return TemplateReferenceInterface A template
* {@inheritdoc}
*
* @api
*/

View File

@ -24,7 +24,7 @@ interface TemplateNameParserInterface
/**
* Convert a template name to a TemplateReferenceInterface instance.
*
* @param string $name A template name
* @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance
*
* @return TemplateReferenceInterface A template
*

View File

@ -30,20 +30,16 @@ class TemplateReference implements TemplateReferenceInterface
);
}
/**
* {@inheritdoc}
*/
public function __toString()
{
return $this->getLogicalName();
}
/**
* Sets a template parameter.
*
* @param string $name The parameter name
* @param string $value The parameter value
*
* @return TemplateReferenceInterface The TemplateReferenceInterface instance
*
* @throws \InvalidArgumentException if the parameter is not defined
* {@inheritdoc}
*
* @api
*/
@ -59,13 +55,7 @@ class TemplateReference implements TemplateReferenceInterface
}
/**
* Gets a template parameter.
*
* @param string $name The parameter name
*
* @return string The parameter value
*
* @throws \InvalidArgumentException if the parameter is not defined
* {@inheritdoc}
*
* @api
*/
@ -79,9 +69,7 @@ class TemplateReference implements TemplateReferenceInterface
}
/**
* Gets the template parameters.
*
* @return array An array of parameters
* {@inheritdoc}
*
* @api
*/
@ -91,11 +79,7 @@ class TemplateReference implements TemplateReferenceInterface
}
/**
* Returns the path to the template.
*
* By default, it just returns the template name.
*
* @return string A path to the template or a resource
* {@inheritdoc}
*
* @api
*/
@ -105,11 +89,7 @@ class TemplateReference implements TemplateReferenceInterface
}
/**
* Returns the "logical" template name.
*
* The template name acts as a unique identifier for the template.
*
* @return string The template name
* {@inheritdoc}
*
* @api
*/

View File

@ -37,7 +37,7 @@ interface TemplateReferenceInterface
*
* @return TemplateReferenceInterface The TemplateReferenceInterface instance
*
* @throws \InvalidArgumentException if the parameter is not defined
* @throws \InvalidArgumentException if the parameter name is not supported
*
* @api
*/
@ -50,7 +50,7 @@ interface TemplateReferenceInterface
*
* @return string The parameter value
*
* @throws \InvalidArgumentException if the parameter is not defined
* @throws \InvalidArgumentException if the parameter name is not supported
*
* @api
*/
@ -77,4 +77,15 @@ interface TemplateReferenceInterface
* @api
*/
public function getLogicalName();
/**
* Returns the string representation as shortcut for getLogicalName().
*
* Alias of getLogicalName().
*
* @return string The template name
*
* @api
*/
public function __toString();
}