Browse Source

Start to integrate ViewBuilder.

Replace the various calls to getView() with viewBuilder(). This new
method should replace getView() entirely and allow for simpler view
configuration as we don't have to manage concrete view instances as
often.

This updates Controller/ but there is still lots to do elsewhere.
Mark Story 10 years ago
parent
commit
2662b44e5d

+ 1 - 1
src/Controller/Component/AuthComponent.php

@@ -376,7 +376,7 @@ class AuthComponent extends Component
         }
 
         if (!empty($this->_config['ajaxLogin'])) {
-            $controller->getview()->viewPath('Element');
+            $controller->viewBuilder()->viewPath('Element');
             $response = $controller->render(
                 $this->_config['ajaxLogin'],
                 $this->RequestHandler->ajaxLayout

+ 6 - 6
src/Controller/Component/RequestHandlerComponent.php

@@ -546,6 +546,7 @@ class RequestHandlerComponent extends Component
         }
         $options += $defaults;
 
+        $builder = $controller->viewBuilder();
         if (array_key_exists($type, $viewClassMap)) {
             $view = $viewClassMap[$type];
         } else {
@@ -555,21 +556,20 @@ class RequestHandlerComponent extends Component
 
         if ($viewClass) {
             $controller->viewClass = $viewClass;
+            $builder->className($viewClass);
         } else {
-            $view = $controller->getView();
-
             if (empty($this->_renderType)) {
-                $view->viewPath($view->viewPath() . DS . $type);
+                $builder->viewPath($builder->viewPath() . DS . $type);
             } else {
-                $view->viewPath(preg_replace(
+                $builder->viewPath(preg_replace(
                     "/([\/\\\\]{$this->_renderType})$/",
                     DS . $type,
-                    $view->viewPath()
+                    $builder->viewPath()
                 ));
             }
 
             $this->_renderType = $type;
-            $view->layoutPath($type);
+            $builder->layoutPath($type);
         }
 
         $response = $this->response;

+ 17 - 27
src/Controller/Controller.php

@@ -187,7 +187,7 @@ class Controller implements EventListenerInterface, EventDispatcherInterface
      * Controller::render() is called.
      *
      * @var \Cake\View\View
-     * @deprecated 3.1.0 Use getView() instead.
+     * @deprecated 3.1.0 Use viewBuilder() instead.
      */
     public $View;
 
@@ -319,10 +319,10 @@ class Controller implements EventListenerInterface, EventDispatcherInterface
     {
         if (in_array($name, ['layout', 'view', 'theme', 'autoLayout', 'viewPath', 'layoutPath'], true)) {
             trigger_error(
-                sprintf('Controller::$%s is deprecated. Use $this->getView()->%s() instead.', $name, $name),
+                sprintf('Controller::$%s is deprecated. Use $this->viewBuilder()->%s() instead.', $name, $name),
                 E_USER_DEPRECATED
             );
-            return $this->getView()->{$name}();
+            return $this->viewBuilder()->{$name}();
         }
 
         list($plugin, $class) = pluginSplit($this->modelClass, true);
@@ -343,10 +343,10 @@ class Controller implements EventListenerInterface, EventDispatcherInterface
     {
         if (in_array($name, ['layout', 'view', 'theme', 'autoLayout', 'viewPath', 'layoutPath'], true)) {
             trigger_error(
-                sprintf('Controller::$%s is deprecated. Use $this->getView()->%s() instead.', $name, $name),
+                sprintf('Controller::$%s is deprecated. Use $this->viewBuilder()->%s() instead.', $name, $name),
                 E_USER_DEPRECATED
             );
-            $this->getView()->{$name}($value);
+            $this->viewBuilder()->{$name}($value);
             return;
         }
 
@@ -554,49 +554,39 @@ class Controller implements EventListenerInterface, EventDispatcherInterface
      */
     public function render($view = null, $layout = null)
     {
-        $this->View = $this->getView();
-        if (!$this->_view->viewPath()) {
-            $this->_viewPath();
+        $builder = $this->viewBuilder();
+        if (!$builder->viewPath()) {
+            $builder->viewPath($this->_viewPath());
         }
 
         if (!empty($this->request->params['bare'])) {
-            $this->_view->autoLayout(false);
+            $builder->autoLayout(false);
         }
+        $builder->className($this->viewClass);
+
+        $this->autoRender = false;
 
-        $viewClass = $this->viewClass;
         $event = $this->dispatchEvent('Controller.beforeRender');
         if ($event->result instanceof Response) {
-            $this->autoRender = false;
             return $event->result;
         }
         if ($event->isStopped()) {
-            $this->autoRender = false;
             return $this->response;
         }
 
-        // Re-fetch View class to pass view variables set in beforeRender callbacks
-        $this->View = $this->getView();
-
-        if ($viewClass !== $this->viewClass) {
-            $this->View = $this->getView($this->viewClass);
-            if (!$this->_view->viewPath()) {
-                $this->_viewPath();
-            }
-        }
-
-        $this->autoRender = false;
-        if ($this->_view->view() === null &&
+        if ($builder->template() === null &&
             isset($this->request->params['action'])
         ) {
-            $this->_view->view($this->request->params['action']);
+            $builder->template($this->request->params['action']);
         }
 
+        $this->View = $this->_view = $this->createView();
         $this->response->body($this->_view->render($view, $layout));
         return $this->response;
     }
 
     /**
-     * Set View::$viewPath property based on controller name and request prefix.
+     * Get the viewPath based on controller name and request prefix.
      *
      * @return void
      */
@@ -610,7 +600,7 @@ class Controller implements EventListenerInterface, EventDispatcherInterface
             );
             $viewPath = implode(DS, $prefixes) . DS . $viewPath;
         }
-        $this->_view->viewPath($viewPath);
+        return $viewPath;
     }
 
     /**

+ 50 - 42
src/View/ViewVarsTrait.php

@@ -14,6 +14,7 @@
 namespace Cake\View;
 
 use Cake\Core\App;
+use Cake\View\ViewBuilder;
 
 /**
  * Provides the set() method for collecting template context.
@@ -29,6 +30,7 @@ trait ViewVarsTrait
      * The name of default View class.
      *
      * @var string
+     * @deprecated 3.1.0 Use `$this->viewBuilder()->className()` instead.
      */
     public $viewClass = null;
 
@@ -49,48 +51,51 @@ trait ViewVarsTrait
     public $viewVars = [];
 
     /**
-     * Get view instance
+     * The view builder instance being used.
+     *
+     * @var \Cake\View\ViewBuilder
+     */
+    protected $_viewBuilder;
+
+    /**
+     * Get the view builder being used.
+     *
+     * @return \Cake\View\ViewBuilder
+     */
+    public function viewBuilder()
+    {
+        if (!isset($this->_viewBuilder)) {
+            $this->_viewBuilder = new ViewBuilder();
+        }
+        return $this->_viewBuilder;
+    }
+
+    /**
+     * Get a view instance.
      *
      * @param string|null $viewClass View class name or null to use $viewClass
      * @return \Cake\View\View
      * @throws \Cake\View\Exception\MissingViewException If view class was not found.
+     * @deprecated 3.1.0 Use the viewBuilder() method to define view properties
+     *   before building a view with createView().
      */
     public function getView($viewClass = null)
     {
-        if ($viewClass === null && $this->_view) {
-            $this->_view->viewVars = $this->viewVars;
-            return $this->_view;
-        }
-
         if ($viewClass === null) {
             $viewClass = $this->viewClass;
         }
-        if ($viewClass === null) {
-            $viewClass = App::className('App', 'View', 'View');
-            if ($viewClass === false) {
-                $viewClass = 'Cake\View\View';
-            }
-        }
-        if ($viewClass === 'View') {
-            $viewClass = 'Cake\View\View';
+        if ($viewClass) {
+            $this->_view = null;
         }
-
-        $this->viewClass = $viewClass;
-        $className = App::className($this->viewClass, 'View', 'View');
-        if (!$className) {
-            throw new Exception\MissingViewException(['class' => $viewClass]);
+        if ($this->_view === null) {
+            $this->_view = $this->createView($viewClass);
         }
-
-        if ($this->_view && $this->_view instanceof $className) {
-            $this->_view->viewVars = $this->viewVars;
-            return $this->_view;
-        }
-
-        return $this->_view = $this->createView();
+        $this->_view->viewVars = $this->viewVars;
+        return $this->_view;
     }
 
     /**
-     * Constructs the view class instance based on object properties.
+     * Constructs the view class instance based on the current configuration.
      *
      * @param string|null $viewClass Optional namespaced class name of the View class to instantiate.
      * @return \Cake\View\View
@@ -98,16 +103,12 @@ trait ViewVarsTrait
      */
     public function createView($viewClass = null)
     {
+        $builder = $this->viewBuilder();
         if ($viewClass === null) {
             $viewClass = $this->viewClass;
         }
-        if ($viewClass === 'View') {
-            $className = App::className($viewClass, 'View');
-        } else {
-            $className = App::className($viewClass, 'View', 'View');
-        }
-        if (!$className) {
-            throw new Exception\MissingViewException([$viewClass]);
+        if ($viewClass) {
+            $builder->className($viewClass);
         }
 
         $validViewOptions = $this->viewOptions();
@@ -117,22 +118,29 @@ trait ViewVarsTrait
                 $viewOptions[$option] = $this->{$option};
             }
         }
-        $deprecatedOptions = array_diff(
-            ['layout', 'view', 'theme', 'autoLayout', 'viewPath', 'layoutPath'],
-            $validViewOptions
-        );
+        $deprecatedOptions = ['layout', 'view', 'theme', 'autoLayout', 'viewPath', 'layoutPath'];
         foreach ($deprecatedOptions as $option) {
             if (property_exists($this, $option)) {
-                $viewOptions[$option] = $this->{$option};
-                unset($this->{$option});
+                $builder->{$option}($this->{$option});
                 trigger_error(sprintf(
-                    'Property $%s is deprecated. Use $this->getView()->%s() instead in beforeRender().',
+                    'Property $%s is deprecated. Use $this->viewBuilder()->%s() instead in beforeRender().',
                     $option,
                     $option
                 ), E_USER_DEPRECATED);
             }
         }
-        return new $className($this->request, $this->response, $this->eventManager(), $viewOptions);
+
+        if (isset($this->name)) {
+            $builder->name($this->name);
+        }
+
+        return $builder->build(
+            $this->viewVars,
+            $this->request,
+            $this->response,
+            $this->eventManager(),
+            $viewOptions
+        );
     }
 
     /**

+ 8 - 8
tests/TestCase/Controller/Component/RequestHandlerComponentTest.php

@@ -447,8 +447,8 @@ class RequestHandlerComponentTest extends TestCase
             return $this->Controller->response;
         });
         $this->Controller->render();
-        $this->assertEquals('RequestHandlerTest' . DS . 'csv', $this->Controller->getView()->viewPath);
-        $this->assertEquals('csv', $this->Controller->getView()->layoutPath);
+        $this->assertEquals('RequestHandlerTest' . DS . 'csv', $this->Controller->viewBuilder()->viewPath());
+        $this->assertEquals('csv', $this->Controller->viewBuilder()->layoutPath());
     }
 
     /**
@@ -610,9 +610,9 @@ class RequestHandlerComponentTest extends TestCase
         $this->RequestHandler->renderAs($this->Controller, 'rss');
         $this->assertTrue(in_array('Rss', $this->Controller->helpers));
 
-        $this->Controller->getView()->viewPath = 'request_handler_test\\rss';
+        $this->Controller->viewBuilder()->viewPath('request_handler_test\\rss');
         $this->RequestHandler->renderAs($this->Controller, 'js');
-        $this->assertEquals('request_handler_test' . DS . 'js', $this->Controller->getView()->viewPath);
+        $this->assertEquals('request_handler_test' . DS . 'js', $this->Controller->viewBuilder()->viewPath());
     }
 
     /**
@@ -704,12 +704,12 @@ class RequestHandlerComponentTest extends TestCase
         $this->Controller->render();
 
         $this->RequestHandler->renderAs($this->Controller, 'print');
-        $this->assertEquals('RequestHandlerTest' . DS . 'print', $this->Controller->getView()->viewPath);
-        $this->assertEquals('print', $this->Controller->getView()->layoutPath);
+        $this->assertEquals('RequestHandlerTest' . DS . 'print', $this->Controller->viewBuilder()->viewPath());
+        $this->assertEquals('print', $this->Controller->viewBuilder()->layoutPath());
 
         $this->RequestHandler->renderAs($this->Controller, 'js');
-        $this->assertEquals('RequestHandlerTest' . DS . 'js', $this->Controller->getView()->viewPath);
-        $this->assertEquals('js', $this->Controller->getView()->layoutPath);
+        $this->assertEquals('RequestHandlerTest' . DS . 'js', $this->Controller->viewBuilder()->viewPath());
+        $this->assertEquals('js', $this->Controller->viewBuilder()->layoutPath());
     }
 
     /**

+ 3 - 3
tests/TestCase/Controller/ControllerTest.php

@@ -397,7 +397,7 @@ class ControllerTest extends TestCase
         $request->params['action'] = 'index';
 
         $Controller = new Controller($request, new Response());
-        $Controller->getView()->viewPath = 'Posts';
+        $Controller->viewBuilder()->viewPath('Posts');
 
         $result = $Controller->render('index');
         $this->assertRegExp('/posts index/', (string)$result);
@@ -421,10 +421,10 @@ class ControllerTest extends TestCase
     {
         $Controller = new Controller(new Request, new Response());
 
-        $Controller->eventManager()->attach(function ($event) {
+        $Controller->eventManager()->on('Controller.beforeRender', function ($event) {
             $controller = $event->subject();
             $controller->viewClass = 'Json';
-        }, 'Controller.beforeRender');
+        });
 
         $Controller->set([
             'test' => 'value',

+ 1 - 1
tests/TestCase/Controller/PagesControllerTest.php

@@ -40,7 +40,7 @@ class PagesControllerTest extends TestCase
     {
         $Pages = new PagesController(new Request(), new Response());
 
-        $Pages->getView()->viewPath = 'Posts';
+        $Pages->viewBuilder()->viewPath('Posts');
         $Pages->display('index');
         $this->assertRegExp('/posts index/', $Pages->response->body());
         $this->assertEquals('index', $Pages->viewVars['page']);

+ 2 - 2
tests/test_app/TestApp/Controller/RequestHandlerTestController.php

@@ -32,7 +32,7 @@ class RequestHandlerTestController extends Controller
      */
     public function destination()
     {
-        $this->getView()->viewPath('Posts');
+        $this->viewBuilder()->viewPath('Posts');
         $this->render('index');
     }
 
@@ -56,7 +56,7 @@ class RequestHandlerTestController extends Controller
      */
     public function ajax2_layout()
     {
-        $this->getView()->layout = 'ajax2';
+        $this->viewBuilder()->layout('ajax2');
         $this->destination();
     }
 }