Browse Source

Merge pull request #6233 from HavokInspiration/3.0-prefix-elements

Autoswitch elements to prefix path.

When a controller runs in a prefixed route/namespace it will automatically append
that prefix to the view paths used to locate view files.
Mark Story 11 years ago
parent
commit
c3602bb7a4

+ 34 - 13
src/View/View.php

@@ -964,17 +964,7 @@ class View
         }
         list($plugin, $name) = $this->pluginSplit($name);
 
-        $layoutPaths = ['Layout' . DS . $subDir];
-        if (!empty($this->request->params['prefix'])) {
-            $prefixPath = array_map(
-                'Cake\Utility\Inflector::camelize',
-                explode('/', $this->request->params['prefix'])
-            );
-            array_unshift(
-                $layoutPaths,
-                implode('/', $prefixPath) . DS . $layoutPaths[0]
-            );
-        }
+        $layoutPaths = $this->_getSubPaths('Layout' . DS . $subDir);
 
         foreach ($this->_paths($plugin) as $path) {
             foreach ($layoutPaths as $layoutPath) {
@@ -1000,15 +990,46 @@ class View
         list($plugin, $name) = $this->pluginSplit($name);
 
         $paths = $this->_paths($plugin);
+        $elementPaths = $this->_getSubPaths('Element');
+
         foreach ($paths as $path) {
-            if (file_exists($path . 'Element' . DS . $name . $this->_ext)) {
-                return $path . 'Element' . DS . $name . $this->_ext;
+            foreach ($elementPaths as $elementPath) {
+                if (file_exists($path . $elementPath . DS . $name . $this->_ext)) {
+                    return $path . $elementPath . DS . $name . $this->_ext;
+                }
             }
         }
         return false;
     }
 
     /**
+     * Find all sub templates path, based on $basePath
+     * If a prefix is defined in the current request, this method will prepend
+     * the prefixed template path to the $basePath.
+     * This is essentially used to find prefixed template paths for elements
+     * and layouts.
+     *
+     * @param string $basePath Base path on which to get the prefixed one.
+     * @return array Array with all the templates paths.
+     */
+    protected function _getSubPaths($basePath)
+    {
+        $paths = [$basePath];
+        if (!empty($this->request->params['prefix'])) {
+            $prefixPath = array_map(
+                'Cake\Utility\Inflector::camelize',
+                explode('/', $this->request->params['prefix'])
+            );
+            array_unshift(
+                $paths,
+                implode('/', $prefixPath) . DS . $basePath
+            );
+        }
+
+        return $paths;
+    }
+
+    /**
      * Return all possible paths to find view files in order
      *
      * @param string|null $plugin Optional plugin name to scan for view files.

+ 14 - 0
tests/TestCase/View/Helper/FlashHelperTest.php

@@ -169,4 +169,18 @@ class FlashHelperTest extends TestCase
         $expected = 'flash element from TestTheme';
         $this->assertContains($expected, $result);
     }
+
+    /**
+     * test that when View prefix is set, flash element from that prefix
+     * is used if available.
+     *
+     * @return void
+     */
+    public function testFlashWithPrefix()
+    {
+        $this->View->request->params['prefix'] = 'Admin';
+        $result = $this->Flash->render('flash');
+        $expected = 'flash element from Admin prefix folder';
+        $this->assertContains($expected, $result);
+    }
 }

+ 61 - 0
tests/TestCase/View/ViewTest.php

@@ -817,6 +817,29 @@ class ViewTest extends TestCase
     }
 
     /**
+     * Test element method with a prefix
+     *
+     * @return void
+     */
+    public function testPrefixElement()
+    {
+        $this->View->request->params['prefix'] = 'Admin';
+        $result = $this->View->element('prefix_element');
+        $this->assertEquals('this is a prefixed test element', $result);
+
+        $result = $this->View->element('TestPlugin.plugin_element');
+        $this->assertEquals('this is the plugin prefixed element using params[plugin]', $result);
+
+        $this->View->plugin = 'TestPlugin';
+        $result = $this->View->element('test_plugin_element');
+        $this->assertEquals('this is the test set using View::$plugin plugin prefixed element', $result);
+
+        $this->View->request->params['prefix'] = 'FooPrefix/BarPrefix';
+        $result = $this->View->element('prefix_element');
+        $this->assertEquals('this is a nested prefixed test element', $result);
+    }
+
+    /**
      * Test elementInexistent method
      *
      * @expectedException \Cake\View\Exception\MissingElementException
@@ -1715,6 +1738,26 @@ TEXT;
     }
 
     /**
+     * Test extend() in an element and a view.
+     *
+     * @return void
+     */
+    public function testExtendPrefixElement()
+    {
+        $this->View->request->params['prefix'] = 'Admin';
+        $this->View->layout = false;
+        $content = $this->View->render('extend_element');
+        $expected = <<<TEXT
+Parent View.
+View content.
+Parent Element.
+Prefix Element content.
+
+TEXT;
+        $this->assertEquals($expected, $content);
+    }
+
+    /**
      * Extending an element which doesn't exist should throw a missing view exception
      *
      * @return void
@@ -1750,6 +1793,24 @@ TEXT;
     }
 
     /**
+     * Test extend() preceeded by an element()
+     *
+     * @return void
+     */
+    public function testExtendWithPrefixElementBeforeExtend()
+    {
+        $this->View->request->params['prefix'] = 'Admin';
+        $this->View->layout = false;
+        $result = $this->View->render('extend_with_element');
+        $expected = <<<TEXT
+Parent View.
+this is the test prefix elementThe view
+
+TEXT;
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
      * Test memory leaks that existed in _paths at one point.
      *
      * @return void

+ 1 - 0
tests/test_app/Plugin/TestPlugin/src/Template/Admin/Element/plugin_element.ctp

@@ -0,0 +1 @@
+this is the plugin prefixed element using params[plugin]

+ 1 - 0
tests/test_app/Plugin/TestPlugin/src/Template/Admin/Element/test_plugin_element.ctp

@@ -0,0 +1 @@
+this is the test set using View::$plugin plugin prefixed element

+ 1 - 1
tests/test_app/Plugin/TestPlugin/src/Template/Element/Flash/plugin_element.ctp

@@ -1 +1 @@
-<?= 'this is the plugin element'; ?>
+this is the plugin element

+ 1 - 1
tests/test_app/Plugin/TestPlugin/src/Template/Element/plugin_element.ctp

@@ -1 +1 @@
-<?= 'this is the plugin element using params[plugin]'; ?>
+this is the plugin element using params[plugin]

+ 1 - 1
tests/test_app/Plugin/TestPlugin/src/Template/Element/test_plugin_element.ctp

@@ -1 +1 @@
-<?= 'this is the test set using View::$plugin plugin element'; ?>
+this is the test set using View::$plugin plugin element

+ 1 - 0
tests/test_app/TestApp/Template/Admin/Element/Flash/default.ctp

@@ -0,0 +1 @@
+flash element from Admin prefix folder

+ 2 - 0
tests/test_app/TestApp/Template/Admin/Element/extended_element.ctp

@@ -0,0 +1,2 @@
+<?php $this->extend('parent_element'); ?>
+Prefix Element content.

+ 1 - 0
tests/test_app/TestApp/Template/Admin/Element/prefix_element.ctp

@@ -0,0 +1 @@
+this is a prefixed test element

+ 1 - 0
tests/test_app/TestApp/Template/Admin/Element/test_element.ctp

@@ -0,0 +1 @@
+this is the test prefix element

+ 1 - 1
tests/test_app/TestApp/Template/Element/test_element.ctp

@@ -1 +1 @@
-<?= 'this is the test element'; ?>
+this is the test element

+ 1 - 0
tests/test_app/TestApp/Template/FooPrefix/BarPrefix/Element/prefix_element.ctp

@@ -0,0 +1 @@
+this is a nested prefixed test element