Browse Source

Add Controller::addViewClasses().

This allows setting view classes for content negotiation from outside
the controller, for e.g. from components and event listeners.
ADmad 3 years ago
parent
commit
13561af4e3

+ 26 - 1
src/Controller/Controller.php

@@ -171,6 +171,13 @@ class Controller implements EventListenerInterface, EventDispatcherInterface
     protected $middlewares = [];
 
     /**
+     * View classes for content negotiation.
+     *
+     * @var array<string>
+     */
+    protected $viewClasses = [];
+
+    /**
      * Constructor.
      *
      * Sets a number of properties based on conventions if they are empty. To override the
@@ -791,7 +798,25 @@ class Controller implements EventListenerInterface, EventDispatcherInterface
      */
     public function viewClasses(): array
     {
-        return [];
+        return $this->viewClasses;
+    }
+
+    /**
+     * Add View classes this controller can perform content negotiation with.
+     *
+     * Each view class must implement the `getContentType()` hook method
+     * to participate in negotiation.
+     *
+     * @param array $viewClasses View classes list.
+     * @return $this
+     * @see Cake\Http\ContentTypeNegotiation
+     * @since 4.5.0
+     */
+    public function addViewClasses(array $viewClasses)
+    {
+        $this->viewClasses = array_merge($this->viewClasses, $viewClasses);
+
+        return $this;
     }
 
     /**

+ 14 - 0
tests/TestCase/Controller/ControllerTest.php

@@ -27,6 +27,7 @@ use Cake\Http\ServerRequest;
 use Cake\Routing\Router;
 use Cake\TestSuite\TestCase;
 use Cake\View\View;
+use Cake\View\XmlView;
 use Laminas\Diactoros\Uri;
 use ReflectionFunction;
 use RuntimeException;
@@ -39,6 +40,7 @@ use TestApp\Controller\TestController;
 use TestApp\Controller\WithDefaultTableController;
 use TestApp\Model\Table\ArticlesTable;
 use TestApp\Model\Table\PostsTable;
+use TestApp\View\PlainTextView;
 use TestPlugin\Controller\Admin\CommentsController;
 use TestPlugin\Controller\TestPluginController;
 use UnexpectedValueException;
@@ -272,6 +274,18 @@ class ControllerTest extends TestCase
         $this->assertMatchesRegularExpression('/this is the test element/', (string)$result);
     }
 
+    public function testAddViewClasses()
+    {
+        $controller = new ContentTypesController();
+        $this->assertSame([], $controller->viewClasses());
+
+        $controller->addViewClasses([PlainTextView::class]);
+        $this->assertSame([PlainTextView::class], $controller->viewClasses());
+
+        $controller->addViewClasses([XmlView::class]);
+        $this->assertSame([PlainTextView::class, XmlView::class], $controller->viewClasses());
+    }
+
     /**
      * Test that render() will do content negotiation when supported
      * by the controller.

+ 0 - 10
tests/test_app/TestApp/Controller/ContentTypesController.php

@@ -26,16 +26,6 @@ use TestApp\View\PlainTextView;
  */
 class ContentTypesController extends AppController
 {
-    /**
-     * @var array<string>
-     */
-    protected $viewClasses = [];
-
-    public function viewClasses(): array
-    {
-        return $this->viewClasses;
-    }
-
     public function all()
     {
         $this->viewClasses = [JsonView::class, XmlView::class];