made using Twig_SourceContextLoaderInterface required

This commit is contained in:
Fabien Potencier
2016-10-21 16:09:46 -07:00
parent 8c337082bb
commit 21ecba8c44
17 changed files with 164 additions and 41 deletions
+1
View File
@@ -1,5 +1,6 @@
* 1.27.0 (2016-XX-XX)
* deprecated Twig_LoaderInterface::getSource() (implement Twig_SourceContextLoaderInterface instead)
* fixed the filesystem loader with relative paths
* deprecated Twig_Node::getLine() in favor of Twig_Node::getTemplateLine()
* deprecated Twig_Template::getSource() in favor of Twig_Template::getSourceContext()
+7
View File
@@ -271,6 +271,8 @@ All loaders implement the ``Twig_LoaderInterface``::
* @param string $name string The name of the template to load
*
* @return string The template source code
*
* @deprecated since 1.27 (to be removed in 2.0), implement Twig_SourceContextLoaderInterface
*/
function getSource($name);
@@ -295,6 +297,11 @@ All loaders implement the ``Twig_LoaderInterface``::
The ``isFresh()`` method must return ``true`` if the current cached template
is still fresh, given the last modification time, or ``false`` otherwise.
.. note::
As of Twig 1.27, you should also implement
``Twig_SourceContextLoaderInterface`` to avoid deprecation notices.
.. tip::
As of Twig 1.11.0, you can also implement ``Twig_ExistsLoaderInterface``
+5
View File
@@ -137,6 +137,7 @@ Interfaces
* ``Twig_NodeInterface`` (use ``Twig_Node`` instead)
* ``Twig_ParserInterface`` (use ``Twig_Parser`` instead)
* ``Twig_ExistsLoaderInterface`` (merged with ``Twig_LoaderInterface``)
* ``Twig_SourceContextLoaderInterface`` (merged with ``Twig_LoaderInterface``)
* ``Twig_TemplateInterface`` (use ``Twig_Template`` instead, and use
those constants Twig_Template::ANY_CALL, Twig_Template::ARRAY_CALL,
Twig_Template::METHOD_CALL)
@@ -153,6 +154,10 @@ Loaders
* As of Twig 1.x, ``Twig_Loader_String`` is deprecated and will be removed in
2.0. You can render a string via ``Twig_Environment::createTemplate()``.
* As of Twig 1.27, ``Twig_LoaderInterface::getSource()`` is deprecated.
Implement ``Twig_SourceContextLoaderInterface`` instead and use
``getSourceContext()``.
Node Visitors
-------------
+11 -1
View File
@@ -417,7 +417,7 @@ We have created a simple ``templates`` table that hosts two templates:
Now, let's define a loader able to use this database::
class DatabaseTwigLoader implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
class DatabaseTwigLoader implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
{
protected $dbh;
@@ -435,6 +435,16 @@ Now, let's define a loader able to use this database::
return $source;
}
// Twig_SourceContextLoaderInterface as of Twig 1.27
public function getSourceContext($name)
{
if (false === $source = $this->getValue('source', $name)) {
throw new Twig_Error_Loader(sprintf('Template "%s" does not exist.', $name));
}
return new Twig_Source($source, $name);
}
// Twig_ExistsLoaderInterface as of Twig 1.11
public function exists($name)
{
+20 -7
View File
@@ -403,13 +403,7 @@ class Twig_Environment
}
if (!class_exists($cls, false)) {
$loader = $this->getLoader();
if ($loader instanceof Twig_SourceContextLoaderInterface) {
$source = $loader->getSourceContext($name);
} else {
$source = new Twig_Source($loader->getSource($name), $name);
}
$content = $this->compileSource($source);
$content = $this->compileSource($this->getSourceContext($name));
if ($this->bcWriteCacheFile) {
$this->writeCacheFile($key, $content);
@@ -735,6 +729,10 @@ class Twig_Environment
*/
public function setLoader(Twig_LoaderInterface $loader)
{
if (!$loader instanceof Twig_SourceContextLoaderInterface && 0 !== strpos(get_class($loader), 'Mock_Twig_LoaderInterface')) {
@trigger_error(sprintf('Twig loader "%s" should implement Twig_SourceContextLoaderInterface since version 1.27.', get_class($loader)), E_USER_DEPRECATED);
}
$this->loader = $loader;
}
@@ -752,6 +750,21 @@ class Twig_Environment
return $this->loader;
}
/**
* Gets the source context for the given template name.
*
* @return Twig_Source
*/
public function getSourceContext($name)
{
$loader = $this->getLoader();
if (!$loader instanceof Twig_SourceContextLoaderInterface) {
return new Twig_Source($loader->getSource($name), $name);
}
return $loader->getSourceContext($name);
}
/**
* Sets the default template charset.
*
+1 -1
View File
@@ -1490,7 +1490,7 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = a
function twig_source(Twig_Environment $env, $name, $ignoreMissing = false)
{
try {
return $env->getLoader()->getSource($name);
return $env->getSourceContext($name)->getCode();
} catch (Twig_Error_Loader $e) {
if (!$ignoreMissing) {
throw $e;
+16 -1
View File
@@ -21,7 +21,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
{
protected $templates = array();
@@ -51,6 +51,8 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
*/
public function getSource($name)
{
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
$name = (string) $name;
if (!isset($this->templates[$name])) {
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
@@ -59,6 +61,19 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
return $this->templates[$name];
}
/**
* {@inheritdoc}
*/
public function getSourceContext($name)
{
$name = (string) $name;
if (!isset($this->templates[$name])) {
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
}
return new Twig_Source($this->templates[$name], $name);
}
/**
* {@inheritdoc}
*/
+7 -1
View File
@@ -47,6 +47,8 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
*/
public function getSource($name)
{
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
$exceptions = array();
foreach ($this->loaders as $loader) {
if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
@@ -109,7 +111,11 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
}
try {
$loader->getSource($name);
if ($loader instanceof Twig_SourceContextLoaderInterface) {
$loader->getSourceContext($name);
} else {
$loader->getSource($name);
}
return $this->hasSourceCache[$name] = true;
} catch (Twig_Error_Loader $e) {
+2
View File
@@ -138,6 +138,8 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
*/
public function getSource($name)
{
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
return file_get_contents($this->findTemplate($name));
}
+11 -1
View File
@@ -27,16 +27,26 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
{
/**
* {@inheritdoc}
*/
public function getSource($name)
{
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
return $name;
}
/**
* {@inheritdoc}
*/
public function getSourceContext($name)
{
return new Twig_Source($name, $name);
}
/**
* {@inheritdoc}
*/
+2
View File
@@ -24,6 +24,8 @@ interface Twig_LoaderInterface
* @return string The template source code
*
* @throws Twig_Error_Loader When $name is not found
*
* @deprecated since 1.27 (to be removed in 2.0), implement Twig_SourceContextLoaderInterface
*/
public function getSource($name);
@@ -9,6 +9,13 @@
* file that was distributed with this source code.
*/
/**
* Adds a getSourceContext() method for loaders.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since 1.27 (to be removed in 3.0)
*/
interface Twig_SourceContextLoaderInterface
{
/**
+1 -2
View File
@@ -212,8 +212,7 @@ abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase
foreach (array_keys($templates) as $name) {
echo "Template: $name\n";
$source = $loader->getSource($name);
echo $twig->compile($twig->parse($twig->tokenize($source, $name)));
echo $twig->compile($twig->parse($twig->tokenize($twig->getSourceContext($name), $name)));
}
}
$this->assertEquals($expected, $output, $message.' (in '.$file.')');
+24 -12
View File
@@ -71,9 +71,14 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
public function testGlobals()
{
// to be removed in 2.0
$loader = $this->getMockBuilder('Twig_EnvironmentTestLoaderInterface')->getMock();
//$loader = $this->getMockBuilder(array('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface'))->getMock();
$loader->expects($this->any())->method('getSourceContext')->will($this->returnValue(new Twig_Source('', '')));
// globals can be added after calling getGlobals
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
$twig = new Twig_Environment($loader);
$twig->addGlobal('foo', 'foo');
$twig->getGlobals();
$twig->addGlobal('foo', 'bar');
@@ -81,7 +86,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
$this->assertEquals('bar', $globals['foo']);
// globals can be modified after a template has been loaded
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
$twig = new Twig_Environment($loader);
$twig->addGlobal('foo', 'foo');
$twig->getGlobals();
$twig->loadTemplate('index');
@@ -90,7 +95,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
$this->assertEquals('bar', $globals['foo']);
// globals can be modified after extensions init
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
$twig = new Twig_Environment($loader);
$twig->addGlobal('foo', 'foo');
$twig->getGlobals();
$twig->getFunctions();
@@ -99,7 +104,8 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
$this->assertEquals('bar', $globals['foo']);
// globals can be modified after extensions and a template has been loaded
$twig = new Twig_Environment($loader = new Twig_Loader_Array(array('index' => '{{foo}}')));
$arrayLoader = new Twig_Loader_Array(array('index' => '{{foo}}'));
$twig = new Twig_Environment($arrayLoader);
$twig->addGlobal('foo', 'foo');
$twig->getGlobals();
$twig->getFunctions();
@@ -108,7 +114,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
$globals = $twig->getGlobals();
$this->assertEquals('bar', $globals['foo']);
$twig = new Twig_Environment($loader);
$twig = new Twig_Environment($arrayLoader);
$twig->getGlobals();
$twig->addGlobal('foo', 'bar');
$template = $twig->loadTemplate('index');
@@ -116,7 +122,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
/* to be uncomment in Twig 2.0
// globals cannot be added after a template has been loaded
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
$twig = new Twig_Environment($loader);
$twig->addGlobal('foo', 'foo');
$twig->getGlobals();
$twig->loadTemplate('index');
@@ -128,7 +134,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
}
// globals cannot be added after extensions init
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
$twig = new Twig_Environment($loader);
$twig->addGlobal('foo', 'foo');
$twig->getGlobals();
$twig->getFunctions();
@@ -140,7 +146,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
}
// globals cannot be added after extensions and a template has been loaded
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
$twig = new Twig_Environment($loader);
$twig->addGlobal('foo', 'foo');
$twig->getGlobals();
$twig->getFunctions();
@@ -153,7 +159,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
}
// test adding globals after a template has been loaded without call to getGlobals
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
$twig = new Twig_Environment($loader);
$twig->loadTemplate('index');
try {
$twig->addGlobal('bar', 'bar');
@@ -445,11 +451,13 @@ EOF
protected function getMockLoader($templateName, $templateContent)
{
$loader = $this->getMockBuilder('Twig_LoaderInterface')->getMock();
// to be removed in 2.0
$loader = $this->getMockBuilder('Twig_EnvironmentTestLoaderInterface')->getMock();
//$loader = $this->getMockBuilder(array('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface'))->getMock();
$loader->expects($this->any())
->method('getSource')
->method('getSourceContext')
->with($templateName)
->will($this->returnValue($templateContent));
->will($this->returnValue(new Twig_Source($templateContent, $templateName)));
$loader->expects($this->any())
->method('getCacheKey')
->with($templateName)
@@ -597,3 +605,7 @@ class Twig_Tests_EnvironmentTest_Runtime
return $name;
}
}
interface Twig_EnvironmentTestLoaderInterface extends Twig_LoaderInterface, Twig_SourceContextLoaderInterface
{
}
+16 -2
View File
@@ -11,6 +11,9 @@
class Twig_Tests_Loader_ArrayTest extends PHPUnit_Framework_TestCase
{
/**
* @group legacy
*/
public function testGetSource()
{
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
@@ -19,6 +22,7 @@ class Twig_Tests_Loader_ArrayTest extends PHPUnit_Framework_TestCase
}
/**
* @group legacy
* @expectedException Twig_Error_Loader
*/
public function testGetSourceWhenTemplateDoesNotExist()
@@ -28,6 +32,16 @@ class Twig_Tests_Loader_ArrayTest extends PHPUnit_Framework_TestCase
$loader->getSource('foo');
}
/**
* @expectedException Twig_Error_Loader
*/
public function testGetSourceContextWhenTemplateDoesNotExist()
{
$loader = new Twig_Loader_Array(array());
$loader->getSourceContext('foo');
}
public function testGetCacheKey()
{
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
@@ -50,7 +64,7 @@ class Twig_Tests_Loader_ArrayTest extends PHPUnit_Framework_TestCase
$loader = new Twig_Loader_Array(array());
$loader->setTemplate('foo', 'bar');
$this->assertEquals('bar', $loader->getSource('foo'));
$this->assertEquals('bar', $loader->getSourceContext('foo')->getCode());
}
public function testIsFresh()
@@ -75,7 +89,7 @@ class Twig_Tests_Loader_ArrayTest extends PHPUnit_Framework_TestCase
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
$loader->getCacheKey($name);
$loader->getSource($name);
$loader->getSourceContext($name);
$loader->isFresh($name, time());
$loader->setTemplate($name, 'foobar');
}
+26 -6
View File
@@ -11,6 +11,9 @@
class Twig_Tests_Loader_ChainTest extends PHPUnit_Framework_TestCase
{
/**
* @group legacy
*/
public function testGetSource()
{
$loader = new Twig_Loader_Chain(array(
@@ -35,7 +38,7 @@ class Twig_Tests_Loader_ChainTest extends PHPUnit_Framework_TestCase
$this->assertSame('', $loader->getSourceContext('foo')->getPath());
$this->assertEquals('errors/index.html', $loader->getSourceContext('errors/index.html')->getName());
$this->assertNull($loader->getSourceContext('errors/index.html')->getPath());
$this->assertSame('', $loader->getSourceContext('errors/index.html')->getPath());
$this->assertEquals('baz', $loader->getSourceContext('errors/index.html')->getCode());
$this->assertEquals('errors/base.html', $loader->getSourceContext('errors/base.html')->getName());
@@ -46,6 +49,17 @@ class Twig_Tests_Loader_ChainTest extends PHPUnit_Framework_TestCase
/**
* @expectedException Twig_Error_Loader
*/
public function testGetSourceContextWhenTemplateDoesNotExist()
{
$loader = new Twig_Loader_Chain(array());
$loader->getSourceContext('foo');
}
/**
* @group legacy
* @expectedException Twig_Error_Loader
*/
public function testGetSourceWhenTemplateDoesNotExist()
{
$loader = new Twig_Loader_Chain(array());
@@ -79,17 +93,19 @@ class Twig_Tests_Loader_ChainTest extends PHPUnit_Framework_TestCase
$loader = new Twig_Loader_Chain();
$loader->addLoader(new Twig_Loader_Array(array('foo' => 'bar')));
$this->assertEquals('bar', $loader->getSource('foo'));
$this->assertEquals('bar', $loader->getSourceContext('foo')->getCode());
}
public function testExists()
{
$loader1 = $this->getMockBuilder('Twig_Loader_Array')->setMethods(array('exists', 'getSource'))->disableOriginalConstructor()->getMock();
$loader1 = $this->getMockBuilder('Twig_Loader_Array')->setMethods(array('exists', 'getSourceContext'))->disableOriginalConstructor()->getMock();
$loader1->expects($this->once())->method('exists')->will($this->returnValue(false));
$loader1->expects($this->never())->method('getSource');
$loader1->expects($this->never())->method('getSourceContext');
$loader2 = $this->getMockBuilder('Twig_LoaderInterface')->getMock();
$loader2->expects($this->once())->method('getSource')->will($this->returnValue('content'));
// can be removed in 2.0
$loader2 = $this->getMockBuilder('Twig_ChainTestLoaderInterface')->getMock();
//$loader2 = $this->getMockBuilder(array('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface'))->getMock();
$loader2->expects($this->once())->method('getSourceContext')->will($this->returnValue(new Twig_Source('content', 'index')));
$loader = new Twig_Loader_Chain();
$loader->addLoader($loader1);
@@ -98,3 +114,7 @@ class Twig_Tests_Loader_ChainTest extends PHPUnit_Framework_TestCase
$this->assertTrue($loader->exists('foo'));
}
}
interface Twig_ChainTestLoaderInterface extends Twig_LoaderInterface, Twig_SourceContextLoaderInterface
{
}
+7 -7
View File
@@ -88,9 +88,9 @@ class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
// do not use realpath here as it would make the test unuseful
$this->assertEquals($cacheKey, str_replace('\\', '/', $loader->getCacheKey('@named/named_absolute.html')));
$this->assertEquals("path (final)\n", $loader->getSource('index.html'));
$this->assertEquals("path (final)\n", $loader->getSource('@__main__/index.html'));
$this->assertEquals("named path (final)\n", $loader->getSource('@named/index.html'));
$this->assertEquals("path (final)\n", $loader->getSourceContext('index.html')->getCode());
$this->assertEquals("path (final)\n", $loader->getSourceContext('@__main__/index.html')->getCode());
$this->assertEquals("named path (final)\n", $loader->getSourceContext('@named/index.html')->getCode());
}
public function getBasePaths()
@@ -147,7 +147,7 @@ class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
$loader->addPath($basePath.'/named', 'named');
try {
$loader->getSource('@named/nowhere.html');
$loader->getSourceContext('@named/nowhere.html');
} catch (Exception $e) {
$this->assertInstanceof('Twig_Error_Loader', $e);
$this->assertContains('Unable to find template "@named/nowhere.html"', $e->getMessage());
@@ -162,11 +162,11 @@ class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
$loader->addPath($basePath.'/named', 'named');
// prime the cache for index.html in the named namespace
$namedSource = $loader->getSource('@named/index.html');
$namedSource = $loader->getSourceContext('@named/index.html')->getCode();
$this->assertEquals("named path\n", $namedSource);
// get index.html from the main namespace
$this->assertEquals("path\n", $loader->getSource('index.html'));
$this->assertEquals("path\n", $loader->getSourceContext('index.html')->getCode());
}
public function testLoadTemplateAndRenderBlockWithCache()
@@ -221,6 +221,6 @@ class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
// $f = new Phar('phar-test.phar');
// $f->addFromString('hello.twig', 'hello from phar');
$loader->addPath('phar://'.dirname(__FILE__).'/Fixtures/phar/phar-sample.phar');
$this->assertSame('hello from phar', $loader->getSource('hello.twig'));
$this->assertSame('hello from phar', $loader->getSourceContext('hello.twig')->getCode());
}
}