Skip to content

Commit

Permalink
fixed regression when registering two extensions with the same class
Browse files Browse the repository at this point in the history
  • Loading branch information
fabpot committed Oct 22, 2016
1 parent d6e6074 commit 714ee45
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 16 deletions.
34 changes: 18 additions & 16 deletions lib/Twig/Environment.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class Twig_Environment
private $bcWriteCacheFile = false;
private $bcGetCacheFilename = false;
private $lastModifiedExtension = 0;
private $legacyExtensionNames = array();
private $legacyExtensions = array();
private $runtimeLoaders = array();
private $runtimes = array();
private $optionsHash;
Expand Down Expand Up @@ -816,9 +816,10 @@ public function initRuntime()
*/
public function hasExtension($class)
{
if (isset($this->legacyExtensionNames[$class])) {
$class = $this->legacyExtensionNames[$class];
if (isset($this->legacyExtensions[$class])) {
@trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED);

return true;
}

return isset($this->extensions[ltrim($class, '\\')]);
Expand All @@ -841,9 +842,10 @@ public function addRuntimeLoader(Twig_RuntimeLoaderInterface $loader)
*/
public function getExtension($class)
{
if (isset($this->legacyExtensionNames[$class])) {
$class = $this->legacyExtensionNames[$class];
if (isset($this->legacyExtensions[$class])) {
@trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED);

return $this->legacyExtensions[$class];
}

$class = ltrim($class, '\\');
Expand Down Expand Up @@ -887,23 +889,22 @@ public function getRuntime($class)
public function addExtension(Twig_ExtensionInterface $extension)
{
$class = get_class($extension);
$legacyName = $class !== $extension->getName() ? $extension->getName() : null;

if ($this->extensionInitialized) {
throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $class));
throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', null !== $legacyName ? $legacyName : $class));
}

$m = new ReflectionMethod($extension, 'getName');
$legacyName = 'Twig_Extension' !== $m->getDeclaringClass()->getName() ? $extension->getName() : null;
if (null !== $legacyName) {
if (isset($this->legacyExtensions[$legacyName])) {
unset($this->extensions[$class], $this->legacyExtensions[$legacyName]);
@trigger_error(sprintf('The possibility to register the same extension twice ("%s") is deprecated since version 1.23 and will be removed in Twig 2.0. Use proper PHP inheritance instead.', $legacyName), E_USER_DEPRECATED);
}

if (isset($this->extensions[$class]) || (null !== $legacyName && isset($this->legacyExtensionNames[$legacyName]))) {
unset($this->extensions[$this->legacyExtensionNames[$legacyName]], $this->legacyExtensionNames[$legacyName]);
@trigger_error(sprintf('The possibility to register the same extension twice ("%s") is deprecated since version 1.23 and will be removed in Twig 2.0. Use proper PHP inheritance instead.', $class), E_USER_DEPRECATED);
$this->legacyExtensions[$legacyName] = $extension;
}

$this->lastModifiedExtension = 0;
if ($legacyName !== $class) {
$this->legacyExtensionNames[$legacyName] = $class;
}
$this->extensions[$class] = $extension;
$this->updateOptionsHash();
}
Expand All @@ -921,9 +922,10 @@ public function removeExtension($name)
{
@trigger_error(sprintf('The %s method is deprecated since version 1.12 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);

if (isset($this->legacyExtensionNames[$name])) {
$name = $this->legacyExtensionNames[$name];
if (isset($this->legacyExtensions[$name])) {
@trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $name), E_USER_DEPRECATED);

unset($this->extensions[$name], $this->legacyExtensions[$name]);
}

if ($this->extensionInitialized) {
Expand Down
36 changes: 36 additions & 0 deletions test/Twig/Tests/EnvironmentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,27 @@ public function testAutoReloadOutdatedCacheHit()
$twig->loadTemplate($templateName);
}

/**
* @group legacy
*/
public function testHasGetExtensionWithDynamicName()
{
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());

$ext1 = new Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName('ext1');
$ext2 = new Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName('ext2');
$twig->addExtension($ext1);
$twig->addExtension($ext2);

$this->assertTrue($twig->hasExtension('ext1'));
$this->assertTrue($twig->hasExtension('ext2'));

$this->assertTrue($twig->hasExtension('Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName'));

$this->assertSame($ext1, $twig->getExtension('ext1'));
$this->assertSame($ext2, $twig->getExtension('ext2'));
}

public function testHasGetExtensionByClassName()
{
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
Expand Down Expand Up @@ -538,6 +559,21 @@ public function getName()
}
}

class Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName extends Twig_Extension
{
public $name;

public function __construct($name)
{
$this->name = $name;
}

public function getName()
{
return $this->name;
}
}

class Twig_Tests_EnvironmentTest_TokenParser extends Twig_TokenParser
{
public function parse(Twig_Token $token)
Expand Down

0 comments on commit 714ee45

Please sign in to comment.