Browse Source

Add SerializationFailureException.

ADmad 6 years ago
parent
commit
feae337ea4

+ 0 - 5
psalm-baseline.xml

@@ -1558,9 +1558,4 @@
       <code>include func_get_arg(0)</code>
     </UnresolvableInclude>
   </file>
-  <file src="src/View/XmlView.php">
-    <PossiblyUndefinedMethod occurrences="1">
-      <code>asXML</code>
-    </PossiblyUndefinedMethod>
-  </file>
 </files>

+ 26 - 0
src/View/Exception/SerializationFailureException.php

@@ -0,0 +1,26 @@
+<?php
+declare(strict_types=1);
+
+/**
+ * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+ * @link          https://cakephp.org CakePHP(tm) Project
+ * @since         4.0.0
+ * @license       https://opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\View\Exception;
+
+use Cake\Core\Exception\Exception;
+
+/**
+ * Used when a SerializedView class fails to serialize data.
+ */
+class SerializationFailureException extends Exception
+{
+}

+ 9 - 6
src/View/JsonView.php

@@ -17,6 +17,7 @@ declare(strict_types=1);
 namespace Cake\View;
 
 use Cake\Core\Configure;
+use RuntimeException;
 
 /**
  * A view class that is used for JSON responses.
@@ -127,12 +128,9 @@ class JsonView extends SerializedView
     }
 
     /**
-     * Serialize view vars
-     *
-     * @param array|string $serialize The name(s) of the view variable(s) that need(s) to be serialized.
-     * @return string|false The serialized data, or boolean false if not serializable.
+     * @inheritDoc
      */
-    protected function _serialize($serialize)
+    protected function _serialize($serialize): string
     {
         $data = $this->_dataToSerialize($serialize);
 
@@ -147,7 +145,12 @@ class JsonView extends SerializedView
             $jsonOptions |= JSON_PRETTY_PRINT;
         }
 
-        return json_encode($data, $jsonOptions);
+        $return = json_encode($data, $jsonOptions);
+        if ($return === false) {
+            throw new RuntimeException(json_last_error_msg(),  json_last_error());
+        }
+
+        return $return;
     }
 
     /**

+ 13 - 8
src/View/SerializedView.php

@@ -19,7 +19,8 @@ namespace Cake\View;
 use Cake\Event\EventManager;
 use Cake\Http\Response;
 use Cake\Http\ServerRequest;
-use RuntimeException;
+use Cake\View\Exception\SerializationFailureException;
+use Exception;
 
 /**
  * Parent class for view classes generating serialized outputs like JsonView and XmlView.
@@ -89,9 +90,9 @@ abstract class SerializedView extends View
      *
      * @param array|string $serialize The name(s) of the view variable(s) that
      *   need(s) to be serialized
-     * @return string|false The serialized data or false.
+     * @return string The serialized data.
      */
-    abstract protected function _serialize($serialize);
+    abstract protected function _serialize($serialize): string;
 
     /**
      * Render view template or return serialized data.
@@ -99,6 +100,7 @@ abstract class SerializedView extends View
      * @param string|null $template The template being rendered.
      * @param string|null|false $layout The layout being rendered.
      * @return string The rendered view.
+     * @throws \Cake\View\SerializationFailureException When serialization fails.
      */
     public function render(?string $template = null, $layout = null): string
     {
@@ -118,12 +120,15 @@ abstract class SerializedView extends View
             );
         }
         if ($serialize !== false) {
-            $result = $this->_serialize($serialize);
-            if ($result === false) {
-                throw new RuntimeException('Serialization of View data failed.');
+            try {
+                return $this->_serialize($serialize);
+            } catch (Exception $e) {
+                throw new SerializationFailureException(
+                    'Serialization of View data failed.',
+                    null,
+                    $e
+                );
             }
-
-            return $result;
         }
 
         return parent::render($template, false);

+ 3 - 10
src/View/XmlView.php

@@ -112,12 +112,9 @@ class XmlView extends SerializedView
     ];
 
     /**
-     * Serialize view vars.
-     *
-     * @param array|string $serialize The name(s) of the view variable(s) that need(s) to be serialized
-     * @return string|false The serialized data
+     * @inheritDoc
      */
-    protected function _serialize($serialize)
+    protected function _serialize($serialize): string
     {
         $rootNode = $this->getConfig('rootNode', 'response');
 
@@ -151,10 +148,6 @@ class XmlView extends SerializedView
             $options['pretty'] = true;
         }
 
-        if (isset($options['return']) && strtolower($options['return']) === 'domdocument') {
-            return Xml::fromArray($data, $options)->saveXML();
-        }
-
-        return Xml::fromArray($data, $options)->asXML();
+        return Xml::fromArray($data, $options)->saveXML();
     }
 }

+ 20 - 0
tests/TestCase/View/JsonViewTest.php

@@ -23,6 +23,7 @@ use Cake\Core\Configure;
 use Cake\Http\Response;
 use Cake\Http\ServerRequest;
 use Cake\TestSuite\TestCase;
+use Cake\View\Exception\SerializationFailureException;
 
 /**
  * JsonViewTest
@@ -338,4 +339,23 @@ class JsonViewTest extends TestCase
         $this->assertSame($expected, $output);
         $this->assertSame('application/json', $View->getResponse()->getType());
     }
+
+    public function testSerializationFailureException()
+    {
+        $this->expectException(SerializationFailureException::class);
+        $this->expectExceptionMessage('Serialization of View data failed.');
+
+        $Request = new ServerRequest();
+        $Response = new Response();
+        $Controller = new Controller($Request, $Response);
+
+        $data = "\xB1\x31";
+        $Controller->set('data', $data);
+        $Controller->viewBuilder()
+            ->setOption('serialize', 'data')
+            ->setOption('jsonOptions', false)
+            ->setClassName('Json');
+        $View = $Controller->createView();
+        $View->render();
+    }
 }