0011704 / PHP 7 can't decode empty JSON
authorJohannes Nohl <lab@nohl.eu>
Wed, 23 Mar 2016 00:58:15 +0000 (01:58 +0100)
committerPhilipp Schüle <p.schuele@metaways.de>
Mon, 4 Apr 2016 15:24:55 +0000 (17:24 +0200)
https://forge.tine20.org/view.php?id=11704

Change-Id: I38d9f35754f7e6815e2c122a9c0b5c3da08f3795
Reviewed-on: http://gerrit.tine20.com/customers/2960
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
tests/tine20/Addressbook/JsonTest.php
tine20/Tinebase/Frontend/Json.php
tine20/Tinebase/Frontend/Json/Abstract.php

index 94c92a7..2716db2 100644 (file)
@@ -1751,4 +1751,18 @@ Steuernummer 33/111/32212";
             $this->assertCount(2, $contactData['tags'], $contactData['n_fn'] . ' tags failed');
         }
     }
+
+    /**
+     * @see 0011704: PHP 7 can't decode empty JSON-strings
+     */
+    public function testEmptyPagingParamJsonDecode()
+    {
+        $filter = array(array(
+            'field'    => 'n_family',
+            'operator' => 'equals',
+            'value'    => 'somename'
+        ));
+        $result = $this->_instance->searchContacts($filter, '');
+        $this->assertEquals(0, $result['totalcount']);
+    }
 }
index 3a9c415..82c561e 100644 (file)
@@ -929,7 +929,7 @@ class Tinebase_Frontend_Json extends Tinebase_Frontend_Json_Abstract
      */
     public function searchPreferencesForApplication($applicationName, $filter)
     {
-        $decodedFilter = is_array($filter) ? $filter : Zend_Json::decode($filter);
+        $decodedFilter = $this->_prepareParameter($filter);
         
         $filter = new Tinebase_Model_PreferenceFilter();
         if (! empty($decodedFilter)) {
@@ -992,7 +992,7 @@ class Tinebase_Frontend_Json extends Tinebase_Frontend_Json_Abstract
      */
     public function savePreferences($data, $adminMode)
     {
-        $decodedData = is_array($data) ? $data : Zend_Json::decode($data);
+        $decodedData = $this->_prepareParameter($data);
         
         $result = array();
         foreach ($decodedData as $applicationName => $data) {
index 1cd6116..82c5b8a 100644 (file)
@@ -189,7 +189,7 @@ abstract class Tinebase_Frontend_Json_Abstract extends Tinebase_Frontend_Abstrac
      */
     protected function _search($_filter, $_paging, Tinebase_Controller_SearchInterface $_controller, $_filterModel, $_getRelations = FALSE, $_totalCountMethod = self::TOTALCOUNT_CONTROLLER)
     {
-        $decodedPagination = is_array($_paging) ? $_paging : Zend_Json::decode($_paging);
+        $decodedPagination = $this->_prepareParameter($_paging);
         $pagination = new Tinebase_Model_Pagination($decodedPagination);
         $filter = $this->_decodeFilter($_filter, $_filterModel);
         
@@ -217,7 +217,7 @@ abstract class Tinebase_Frontend_Json_Abstract extends Tinebase_Frontend_Abstrac
     protected function _decodeFilter($_filter, $_filterModel, $_throwExceptionIfEmpty = FALSE)
     {
         $filterModel = $this->_getPluginForFilterModel($_filterModel);
-        $decodedFilter = is_array($_filter) || strlen($_filter) == 40 ? $_filter : Zend_Json::decode($_filter);
+        $decodedFilter = is_array($_filter) || strlen($_filter) == 40 ? $_filter : $this->_prepareParameter($_filter);
 
         if (is_array($decodedFilter)) {
             $filter = new $filterModel(array());
@@ -308,7 +308,7 @@ abstract class Tinebase_Frontend_Json_Abstract extends Tinebase_Frontend_Abstrac
     protected function _updateMultiple($_filter, $_data, Tinebase_Controller_Record_Interface $_controller, $_filterModel)
     {
         $this->_longRunningRequest();
-        $decodedData   = is_array($_data) ? $_data : Zend_Json::decode($_data);
+        $decodedData   = $this->_prepareParameter($_data);
         $filter = $this->_decodeFilter($_filter, $_filterModel, TRUE);
         
         $result = $_controller->updateMultiple($filter, $decodedData);
@@ -371,7 +371,7 @@ abstract class Tinebase_Frontend_Json_Abstract extends Tinebase_Frontend_Abstrac
     protected function _delete($_ids, Tinebase_Controller_Record_Interface $_controller, $additionalArguments = array())
     {
         if (! is_array($_ids) && strpos($_ids, '[') !== false) {
-            $_ids = Zend_Json::decode($_ids);
+            $_ids = $this->_prepareParameter($_ids);
         }
         $args = array_merge(array($_ids), $additionalArguments);
         call_user_func_array(array($_controller, 'delete'), $args);
@@ -435,6 +435,28 @@ abstract class Tinebase_Frontend_Json_Abstract extends Tinebase_Frontend_Abstrac
     }
 
     /**
+     * returns function parameter as object, decode Json if needed
+     *
+     * Prepare function input to be an object. Input maybe already an array or (empty) text.
+     * Starting PHP 7 Zend_Json::decode can't handle empty strings.
+     *
+     * @param  mixed $_dataAsArrayOrJson
+     * @return array
+     */
+    protected function _prepareParameter($_dataAsArrayOrJson)
+    {
+        if (is_array($_dataAsArrayOrJson)) {
+            return $_dataAsArrayOrJson;
+        }
+        else if (trim($_dataAsArrayOrJson) == '') {
+            return Zend_Json::decode("{}");
+        }
+        else {
+            return Zend_Json::decode($_dataAsArrayOrJson);
+        }
+    }
+
+    /**
      * returns record prepared for json transport
      *
      * @param Tinebase_Record_Interface $_record