.*)$#', $template, $matches)) {
+ $namespace = $matches['namespace'];
+ $template = $matches['template'];
+ }
+
+ $this->lastLookupFailure = false;
+
+ if ($this->isLfiProtectionOn() && preg_match('#\.\.[\\\/]#', $template)) {
+ throw new Exception\DomainException(
+ 'Requested scripts may not include parent directory traversal ("../", "..\\" notation)'
+ );
+ }
+
+ if (!count($this->paths)) {
+ $this->lastLookupFailure = static::FAILURE_NO_PATHS;
+ return false;
+ }
+
+ // Ensure we have the expected file extension
+ $defaultSuffix = $this->getDefaultSuffix();
+ if (pathinfo($template, PATHINFO_EXTENSION) == '') {
+ $template .= '.' . $defaultSuffix;
+ }
+
+ $path = false;
+ if ($namespace !== self::DEFAULT_NAMESPACE) {
+ $path = $this->getPathFromNamespace($template, $namespace);
+ }
+
+ $path = $path ?: $this->getPathFromNamespace($template, self::DEFAULT_NAMESPACE);
+
+ if ($path) {
+ return $path;
+ }
+
+ $this->lastLookupFailure = static::FAILURE_NOT_FOUND;
+ return false;
+ }
+
+ /**
+ * Fetch a template path from a given namespace.
+ *
+ * @param string $template
+ * @param string $namespace
+ * @return false|string String path on success; false on failure
+ */
+ private function getPathFromNamespace($template, $namespace)
+ {
+ if (! array_key_exists($namespace, $this->paths)) {
+ return false;
+ }
+
+ foreach ($this->paths[$namespace] as $path) {
+ $file = new SplFileInfo($path . $template);
+ if ($file->isReadable()) {
+ // Found! Return it.
+ if (($filePath = $file->getRealPath()) === false && substr($path, 0, 7) === 'phar://') {
+ // Do not try to expand phar paths (realpath + phars == fail)
+ $filePath = $path . $template;
+ if (! file_exists($filePath)) {
+ break;
+ }
+ }
+
+ if ($this->useStreamWrapper()) {
+ // If using a stream wrapper, prepend the spec to the path
+ $filePath = 'zend.view://' . $filePath;
+ }
+ return $filePath;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/test/Template/PlatesTest.php b/test/Template/PlatesTest.php
index 6501634d..3a7e320a 100644
--- a/test/Template/PlatesTest.php
+++ b/test/Template/PlatesTest.php
@@ -160,4 +160,18 @@ public function testCanRenderWithParameterObjects($params, $search)
$content = str_replace('=$this->e($name)?>', $search, $content);
$this->assertEquals($content, $result);
}
+
+ /**
+ * @group namespacing
+ */
+ public function testProperlyResolvesNamespacedTemplate()
+ {
+ $template = new PlatesTemplate();
+ $template->addPath(__DIR__ . '/TestAsset/test', 'test');
+
+ $expected = file_get_contents(__DIR__ . '/TestAsset/test/test.php');
+ $test = $template->render('test::test');
+
+ $this->assertSame($expected, $test);
+ }
}
diff --git a/test/Template/TestAsset/test/test.html b/test/Template/TestAsset/test/test.html
new file mode 100644
index 00000000..cb427324
--- /dev/null
+++ b/test/Template/TestAsset/test/test.html
@@ -0,0 +1,3 @@
+Twig Test Namespace
+
+This template is from the test namespace.
diff --git a/test/Template/TestAsset/test/test.js b/test/Template/TestAsset/test/test.js
new file mode 100644
index 00000000..577eedc7
--- /dev/null
+++ b/test/Template/TestAsset/test/test.js
@@ -0,0 +1,3 @@
+{
+ "test": "twig"
+}
diff --git a/test/Template/TestAsset/test/test.php b/test/Template/TestAsset/test/test.php
new file mode 100644
index 00000000..c485b6a5
--- /dev/null
+++ b/test/Template/TestAsset/test/test.php
@@ -0,0 +1,3 @@
+Plates Test Namespace
+
+This template is from the test namespace.
diff --git a/test/Template/TestAsset/test/test.phtml b/test/Template/TestAsset/test/test.phtml
new file mode 100644
index 00000000..10290aee
--- /dev/null
+++ b/test/Template/TestAsset/test/test.phtml
@@ -0,0 +1,3 @@
+zend-view Test Namespace
+
+This template is from the test namespace.
diff --git a/test/Template/TwigTest.php b/test/Template/TwigTest.php
index 998fcb36..4c306a42 100644
--- a/test/Template/TwigTest.php
+++ b/test/Template/TwigTest.php
@@ -143,4 +143,32 @@ public function testCanRenderWithParameterObjects($params, $search)
$content = str_replace('{{ name }}', $search, $content);
$this->assertEquals($content, $result);
}
+
+ /**
+ * @group namespacing
+ */
+ public function testProperlyResolvesNamespacedTemplate()
+ {
+ $template = new TwigTemplate();
+ $template->addPath(__DIR__ . '/TestAsset/test', 'test');
+
+ $expected = file_get_contents(__DIR__ . '/TestAsset/test/test.html');
+ $test = $template->render('test::test');
+
+ $this->assertSame($expected, $test);
+ }
+
+ /**
+ * @group namespacing
+ */
+ public function testResolvesNamespacedTemplateWithSuffix()
+ {
+ $template = new TwigTemplate();
+ $template->addPath(__DIR__ . '/TestAsset/test', 'test');
+
+ $expected = file_get_contents(__DIR__ . '/TestAsset/test/test.js');
+ $test = $template->render('test::test.js');
+
+ $this->assertSame($expected, $test);
+ }
}
diff --git a/test/Template/ZendViewTest.php b/test/Template/ZendViewTest.php
index 95498af5..a5db0999 100644
--- a/test/Template/ZendViewTest.php
+++ b/test/Template/ZendViewTest.php
@@ -224,4 +224,18 @@ public function testCanPassViewModelForLayoutParameterWhenRendering()
$this->assertContains($content, $result);
$this->assertContains('ALTERNATE LAYOUT PAGE', $result);
}
+
+ /**
+ * @group namespacing
+ */
+ public function testProperlyResolvesNamespacedTemplate()
+ {
+ $template = new ZendView();
+ $template->addPath(__DIR__ . '/TestAsset/test', 'test');
+
+ $expected = file_get_contents(__DIR__ . '/TestAsset/test/test.phtml');
+ $test = $template->render('test::test');
+
+ $this->assertSame($expected, $test);
+ }
}