This PR was merged into the 1.x branch.
Discussion
----------
fixed regression when registering two extensions with the same class
fixed #2165
Commits
-------
47432f3 fixed regression when registering two extensions having the same class name
... | ... |
@@ -1,5 +1,6 @@ |
1 | 1 |
* 1.27.0 (2016-XX-XX) |
2 | 2 |
|
3 |
+ * fixed regression when registering two extensions having the same class name |
|
3 | 4 |
* deprecated Twig_LoaderInterface::getSource() (implement Twig_SourceContextLoaderInterface instead) |
4 | 5 |
* fixed the filesystem loader with relative paths |
5 | 6 |
* deprecated Twig_Node::getLine() in favor of Twig_Node::getTemplateLine() |
... | ... |
@@ -49,7 +49,7 @@ class Twig_Environment |
49 | 49 |
private $bcWriteCacheFile = false; |
50 | 50 |
private $bcGetCacheFilename = false; |
51 | 51 |
private $lastModifiedExtension = 0; |
52 |
- private $legacyExtensionNames = array(); |
|
52 |
+ private $extensionsByClass = array(); |
|
53 | 53 |
private $runtimeLoaders = array(); |
54 | 54 |
private $runtimes = array(); |
55 | 55 |
private $optionsHash; |
... | ... |
@@ -808,12 +808,16 @@ class Twig_Environment |
808 | 808 |
*/ |
809 | 809 |
public function hasExtension($class) |
810 | 810 |
{ |
811 |
- if (isset($this->legacyExtensionNames[$class])) { |
|
812 |
- $class = $this->legacyExtensionNames[$class]; |
|
813 |
- @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); |
|
811 |
+ $class = ltrim($class, '\\'); |
|
812 |
+ if (isset($this->extensions[$class])) { |
|
813 |
+ if ($class !== get_class($this->extensions[$class])) { |
|
814 |
+ @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); |
|
815 |
+ } |
|
816 |
+ |
|
817 |
+ return true; |
|
814 | 818 |
} |
815 | 819 |
|
816 |
- return isset($this->extensions[ltrim($class, '\\')]); |
|
820 |
+ return isset($this->extensionsByClass[ltrim($class, '\\')]); |
|
817 | 821 |
} |
818 | 822 |
|
819 | 823 |
/** |
... | ... |
@@ -833,18 +837,21 @@ class Twig_Environment |
833 | 837 |
*/ |
834 | 838 |
public function getExtension($class) |
835 | 839 |
{ |
836 |
- if (isset($this->legacyExtensionNames[$class])) { |
|
837 |
- $class = $this->legacyExtensionNames[$class]; |
|
838 |
- @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); |
|
839 |
- } |
|
840 |
- |
|
841 | 840 |
$class = ltrim($class, '\\'); |
842 | 841 |
|
843 |
- if (!isset($this->extensions[$class])) { |
|
842 |
+ if (isset($this->extensions[$class])) { |
|
843 |
+ if ($class !== get_class($this->extensions[$class])) { |
|
844 |
+ @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); |
|
845 |
+ } |
|
846 |
+ |
|
847 |
+ return $this->extensions[$class]; |
|
848 |
+ } |
|
849 |
+ |
|
850 |
+ if (!isset($this->extensionsByClass[$class])) { |
|
844 | 851 |
throw new Twig_Error_Runtime(sprintf('The "%s" extension is not enabled.', $class)); |
845 | 852 |
} |
846 | 853 |
|
847 |
- return $this->extensions[$class]; |
|
854 |
+ return $this->extensionsByClass[$class]; |
|
848 | 855 |
} |
849 | 856 |
|
850 | 857 |
/** |
... | ... |
@@ -878,25 +885,21 @@ class Twig_Environment |
878 | 885 |
*/ |
879 | 886 |
public function addExtension(Twig_ExtensionInterface $extension) |
880 | 887 |
{ |
881 |
- $class = get_class($extension); |
|
882 |
- |
|
883 | 888 |
if ($this->extensionInitialized) { |
884 |
- throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $class)); |
|
889 |
+ throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName())); |
|
885 | 890 |
} |
886 | 891 |
|
887 |
- $m = new ReflectionMethod($extension, 'getName'); |
|
888 |
- $legacyName = 'Twig_Extension' !== $m->getDeclaringClass()->getName() ? $extension->getName() : null; |
|
889 |
- |
|
890 |
- if (isset($this->extensions[$class]) || (null !== $legacyName && isset($this->legacyExtensionNames[$legacyName]))) { |
|
891 |
- unset($this->extensions[$this->legacyExtensionNames[$legacyName]], $this->legacyExtensionNames[$legacyName]); |
|
892 |
- @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); |
|
892 |
+ $class = get_class($extension); |
|
893 |
+ if ($class !== $extension->getName()) { |
|
894 |
+ if (isset($this->extensions[$extension->getName()])) { |
|
895 |
+ unset($this->extensions[$extension->getName()], $this->extensionsByClass[$class]); |
|
896 |
+ @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.', $extension->getName()), E_USER_DEPRECATED); |
|
897 |
+ } |
|
893 | 898 |
} |
894 | 899 |
|
895 | 900 |
$this->lastModifiedExtension = 0; |
896 |
- if ($legacyName !== $class) { |
|
897 |
- $this->legacyExtensionNames[$legacyName] = $class; |
|
898 |
- } |
|
899 |
- $this->extensions[$class] = $extension; |
|
901 |
+ $this->extensionsByClass[$class] = $extension; |
|
902 |
+ $this->extensions[$extension->getName()] = $extension; |
|
900 | 903 |
$this->updateOptionsHash(); |
901 | 904 |
} |
902 | 905 |
|
... | ... |
@@ -913,16 +916,20 @@ class Twig_Environment |
913 | 916 |
{ |
914 | 917 |
@trigger_error(sprintf('The %s method is deprecated since version 1.12 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); |
915 | 918 |
|
916 |
- if (isset($this->legacyExtensionNames[$name])) { |
|
917 |
- $name = $this->legacyExtensionNames[$name]; |
|
918 |
- @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); |
|
919 |
- } |
|
920 |
- |
|
921 | 919 |
if ($this->extensionInitialized) { |
922 | 920 |
throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name)); |
923 | 921 |
} |
924 | 922 |
|
925 |
- unset($this->extensions[ltrim($name, '\\')]); |
|
923 |
+ $class = ltrim($name, '\\'); |
|
924 |
+ if (isset($this->extensions[$class])) { |
|
925 |
+ if ($class !== get_class($this->extensions[$class])) { |
|
926 |
+ @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); |
|
927 |
+ } |
|
928 |
+ |
|
929 |
+ unset($this->extensions[$class]); |
|
930 |
+ } |
|
931 |
+ |
|
932 |
+ unset($this->extensions[$class]); |
|
926 | 933 |
$this->updateOptionsHash(); |
927 | 934 |
} |
928 | 935 |
|
... | ... |
@@ -277,6 +277,27 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase |
277 | 277 |
$twig->loadTemplate($templateName); |
278 | 278 |
} |
279 | 279 |
|
280 |
+ /** |
|
281 |
+ * @group legacy |
|
282 |
+ */ |
|
283 |
+ public function testHasGetExtensionWithDynamicName() |
|
284 |
+ { |
|
285 |
+ $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); |
|
286 |
+ |
|
287 |
+ $ext1 = new Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName('ext1'); |
|
288 |
+ $ext2 = new Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName('ext2'); |
|
289 |
+ $twig->addExtension($ext1); |
|
290 |
+ $twig->addExtension($ext2); |
|
291 |
+ |
|
292 |
+ $this->assertTrue($twig->hasExtension('ext1')); |
|
293 |
+ $this->assertTrue($twig->hasExtension('ext2')); |
|
294 |
+ |
|
295 |
+ $this->assertTrue($twig->hasExtension('Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName')); |
|
296 |
+ |
|
297 |
+ $this->assertSame($ext1, $twig->getExtension('ext1')); |
|
298 |
+ $this->assertSame($ext2, $twig->getExtension('ext2')); |
|
299 |
+ } |
|
300 |
+ |
|
280 | 301 |
public function testHasGetExtensionByClassName() |
281 | 302 |
{ |
282 | 303 |
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); |
... | ... |
@@ -538,6 +559,21 @@ class Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName extends Twig_Exten |
538 | 559 |
} |
539 | 560 |
} |
540 | 561 |
|
562 |
+class Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName extends Twig_Extension |
|
563 |
+{ |
|
564 |
+ private $name; |
|
565 |
+ |
|
566 |
+ public function __construct($name) |
|
567 |
+ { |
|
568 |
+ $this->name = $name; |
|
569 |
+ } |
|
570 |
+ |
|
571 |
+ public function getName() |
|
572 |
+ { |
|
573 |
+ return $this->name; |
|
574 |
+ } |
|
575 |
+} |
|
576 |
+ |
|
541 | 577 |
class Twig_Tests_EnvironmentTest_TokenParser extends Twig_TokenParser |
542 | 578 |
{ |
543 | 579 |
public function parse(Twig_Token $token) |