[!!!][TASK] Remove ExtDirect State Provider 24/51224/8
authorBenni Mack <benni@typo3.org>
Mon, 9 Jan 2017 19:13:09 +0000 (20:13 +0100)
committerSusanne Moog <susanne.moog@typo3.org>
Wed, 11 Jan 2017 12:00:56 +0000 (13:00 +0100)
The ExtDirect component for fetching the state (for the pagetree)
can be simplified by simply using the Storage.Persistent logic
which does the same.

For this, a simple inline ExtJS onReady code block is added.

All functionality related to ExtDirect State Provider is removed.

Resolves: #79227
Releases: master
Change-Id: I464ffd0608c1fd38cd81c8324f044da6f4140847
Reviewed-on: https://review.typo3.org/51224
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
typo3/sysext/backend/Classes/Controller/BackendController.php
typo3/sysext/backend/Classes/InterfaceState/ExtDirect/DataProvider.php [deleted file]
typo3/sysext/backend/Classes/Template/DocumentTemplate.php
typo3/sysext/backend/Classes/Tree/AbstractExtJsTree.php [deleted file]
typo3/sysext/backend/Classes/Tree/AbstractTreeStateProvider.php [deleted file]
typo3/sysext/backend/Classes/Tree/Pagetree/ExtdirectTreeDataProvider.php
typo3/sysext/backend/Resources/Public/JavaScript/ExtDirect.StateProvider.js [deleted file]
typo3/sysext/core/Classes/Core/Bootstrap.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-79227-RemovedExtDirectStateProvider.rst [new file with mode: 0644]

index fb5c0fc..ba7be90 100644 (file)
@@ -289,24 +289,23 @@ class BackendController
         $this->generateJavascript();
         $this->pageRenderer->addJsInlineCode('BackendInlineJavascript', $this->js, false);
         $this->loadResourcesForRegisteredNavigationComponents();
-
-        // Add state provider
-        $this->getDocumentTemplate()->setExtDirectStateProvider();
-        $states = $this->getBackendUser()->uc['BackendComponents']['States'];
-        // Save states in BE_USER->uc
-        $extOnReadyCode = '
-                       Ext.state.Manager.setProvider(new TYPO3.state.ExtDirectProvider({
-                               key: "BackendComponents.States",
-                               autoRead: false
-                       }));
-               ';
-
-        if ($states) {
-            $extOnReadyCode .= 'Ext.state.Manager.getProvider().initState(' . json_encode($states) . ');';
-        }
-
-        $this->pageRenderer->addExtOnReadyCode($extOnReadyCode);
-
+        // @todo: remove this when ExtJS is removed
+        $this->pageRenderer->addExtOnReadyCode('
+            var TYPO3ExtJSStateProviderBridge = function() {};
+            Ext.extend(TYPO3ExtJSStateProviderBridge, Ext.state.Provider, {
+                prefix: "BackendComponents.States.",
+                get: function(name, defaultValue) {
+                    return TYPO3.Storage.Persistent.isset(this.prefix + name) ? TYPO3.Storage.Persistent.get(this.prefix + name) : defaultValue;
+                },
+                clear: function(name) {
+                    TYPO3.Storage.Persistent.unset(this.prefix + name);
+                },
+                set: function(name, value) {
+                    TYPO3.Storage.Persistent.set(this.prefix + name, value);
+                }
+            });
+            Ext.state.Manager.setProvider(new TYPO3ExtJSStateProviderBridge());
+               ');
         // Set document title:
         $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . ' [TYPO3 CMS ' . TYPO3_version . ']' : 'TYPO3 CMS ' . TYPO3_version;
         // Renders the module page
diff --git a/typo3/sysext/backend/Classes/InterfaceState/ExtDirect/DataProvider.php b/typo3/sysext/backend/Classes/InterfaceState/ExtDirect/DataProvider.php
deleted file mode 100644 (file)
index b8bcae0..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-namespace TYPO3\CMS\Backend\InterfaceState\ExtDirect;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * ExtDirect DataProvider for State
- */
-class DataProvider
-{
-    /**
-     * @var \TYPO3\CMS\Backend\Controller\UserSettingsController
-     */
-    protected $userSettingsController;
-
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        // All data is saved in BE_USER->uc
-        $this->userSettingsController = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
-            \TYPO3\CMS\Backend\Controller\UserSettingsController::class
-        );
-    }
-
-    /**
-     * Gets state for given key
-     *
-     * @param \stdClass $parameter
-     * @return array
-     */
-    public function getState($parameter)
-    {
-        $key = $parameter->params->key;
-        $data = $this->userSettingsController->process('get', $key);
-        return [
-            'success' => true,
-            'data' => $data
-        ];
-    }
-
-    /**
-     * Save the state for a given key
-     *
-     * @param \stdClass $parameter
-     * @return array
-     */
-    public function setState($parameter)
-    {
-        $key = $parameter->params->key;
-        $data = json_decode($parameter->params->data);
-        foreach ($data as $setting) {
-            $this->userSettingsController->process('set', $key . '.' . $setting->name, $setting->value);
-        }
-        return [
-            'success' => true,
-            'params' => $parameter
-        ];
-    }
-}
index e4c5bdb..1468ce2 100644 (file)
@@ -235,11 +235,6 @@ function jumpToUrl(URL) {
     protected $pageHeaderFooterTemplateFile = '';
 
     /**
-     * @var bool
-     */
-    protected $extDirectStateProvider = false;
-
-    /**
      * Whether flashmessages should be rendered or not
      *
      * @var bool $showFlashMessages
@@ -338,16 +333,6 @@ function jumpToUrl(URL) {
         }
     }
 
-    /**
-     * Sets inclusion of StateProvider
-     *
-     * @return void
-     */
-    public function setExtDirectStateProvider()
-    {
-        $this->extDirectStateProvider = true;
-    }
-
     /*****************************************
      *
      * EVALUATION FUNCTIONS
@@ -614,9 +599,6 @@ function jumpToUrl(URL) {
         $this->pageRenderer->setTitle($title);
         // add docstyles
         $this->docStyle();
-        if ($this->extDirectStateProvider) {
-            $this->pageRenderer->addJsFile('EXT:backend/Resources/Public/JavaScript/ExtDirect.StateProvider.js');
-        }
         $this->pageRenderer->addHeaderData($this->JScode);
         foreach ($this->JScodeArray as $name => $code) {
             $this->pageRenderer->addJsInlineCode($name, $code, false);
diff --git a/typo3/sysext/backend/Classes/Tree/AbstractExtJsTree.php b/typo3/sysext/backend/Classes/Tree/AbstractExtJsTree.php
deleted file mode 100644 (file)
index e7ceb3d..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-namespace TYPO3\CMS\Backend\Tree;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Abstract ExtJS tree based on ExtDirect
- */
-abstract class AbstractExtJsTree extends \TYPO3\CMS\Backend\Tree\AbstractTree
-{
-    /**
-     * State Provider
-     *
-     * @var \TYPO3\CMS\Backend\Tree\AbstractTreeStateProvider
-     */
-    protected $stateProvider = null;
-
-    /**
-     * @param \TYPO3\CMS\Backend\Tree\AbstractTreeStateProvider $stateProvider
-     * @return void
-     */
-    public function setStateProvider(\TYPO3\CMS\Backend\Tree\AbstractTreeStateProvider $stateProvider)
-    {
-        $this->stateProvider = $stateProvider;
-    }
-
-    /**
-     * @return \TYPO3\CMS\Backend\Tree\AbstractTreeStateProvider
-     */
-    public function getStateProvider()
-    {
-        return $this->stateProvider;
-    }
-
-    /**
-     * Fetches the next tree level
-     *
-     * @param int $nodeId
-     * @param stdClass $nodeData
-     * @return array
-     */
-    abstract public function getNextTreeLevel($nodeId, $nodeData);
-}
diff --git a/typo3/sysext/backend/Classes/Tree/AbstractTreeStateProvider.php b/typo3/sysext/backend/Classes/Tree/AbstractTreeStateProvider.php
deleted file mode 100644 (file)
index 46d3205..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-namespace TYPO3\CMS\Backend\Tree;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Abstract State Provider
- *
- * @todo This class is incomplete, because the methods still need
- */
-abstract class AbstractTreeStateProvider
-{
-    /**
-     * Sets the current tree state
-     *
-     * @return void
-     */
-    abstract public function setState();
-
-    /**
-     * Returns the last tree state
-     *
-     * @return something
-     */
-    abstract public function getState();
-}
index 0ac6b48..638de87 100644 (file)
@@ -22,7 +22,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Data Provider of the Page Tree
  */
-class ExtdirectTreeDataProvider extends \TYPO3\CMS\Backend\Tree\AbstractExtJsTree
+class ExtdirectTreeDataProvider extends \TYPO3\CMS\Backend\Tree\AbstractTree
 {
     /**
      * Data Provider
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ExtDirect.StateProvider.js b/typo3/sysext/backend/Resources/Public/JavaScript/ExtDirect.StateProvider.js
deleted file mode 100644 (file)
index 978a7d1..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-Ext.ns('TYPO3.state');
-
-/**
- * Creates new ExtDirectProvider
- * @constructor
- * @param {Object} config Configuration object
- */
-
-TYPO3.state.ExtDirectProvider = function(config) {
-
-       this.addEvents(
-               /**
-                * @event readsuccess
-                * Fires after state has been successfully received from server and restored
-                * @param {HttpProvider} this
-                */
-                       'readsuccess',
-               /**
-                * @event readfailure
-                * Fires in the case of an error when attempting to read state from server
-                * @param {HttpProvider} this
-                */
-                       'readfailure',
-               /**
-                * @event savesuccess
-                * Fires after the state has been successfully saved to server
-                * @param {HttpProvider} this
-                */
-                       'savesuccess',
-               /**
-                * @event savefailure
-                * Fires in the case of an error when attempting to save state to the server
-                * @param {HttpProvider} this
-                */
-                       'savefailure'
-       );
-
-               // call parent
-       TYPO3.state.ExtDirectProvider.superclass.constructor.call(this);
-
-       Ext.apply(this, config, {
-               // defaults
-               delay: 750, // buffer changes for 750 ms
-               dirty: false,
-               started: false,
-               autoStart: true,
-               autoRead: true,
-               key: 'States.General',
-               logFailure: false,
-               logSuccess: false,
-               queue: [],
-               saveBaseParams: {},
-               readBaseParams: {},
-               paramNames:{
-                       key: 'key',
-                       name: 'name',
-                       value: 'value',
-                       data: 'data'
-               }
-       });
-
-       if (this.autoRead) {
-               this.readState();
-       }
-
-       this.dt = new Ext.util.DelayedTask(this.submitState, this);
-       if (this.autoStart) {
-               this.start();
-       }
-};
-
-
-Ext.extend(TYPO3.state.ExtDirectProvider, Ext.state.Provider, {
-
-               // localizable texts
-       saveSuccessText: 'Save Success',
-       saveFailureText: 'Save Failure',
-       readSuccessText: 'Read Success',
-       readFailureText: 'Read Failure',
-       dataErrorText: 'Data Error',
-
-
-
-       /**
-        * Initializes state from the passed state object or array.
-        * Use this with loading page using initial state in TYPO3.settings
-        *
-        * @param {Array/Object} state State to initialize state manager with
-        */
-       initState: function(state) {
-               if (Ext.isArray(state)) {
-                       Ext.each(state, function(item) {
-                               this.state[item.name] = item[this.paramNames.value];
-                       }, this);
-               } else if (Ext.isObject(state)) {
-                       Ext.iterate(state, function(key, value){
-                               this.state[key] = value;
-                       }, this);
-               } else {
-                       this.state = {};
-               }
-       },
-
-       /**
-        * Sets the passed state variable name to the passed value and queues the change
-        * @param {String} name Name of the state variable
-        * @param {Mixed} value Value of the state variable
-        */
-       set: function(name, value) {
-               if (!name) {
-                       return;
-               }
-               this.queueChange(name, value);
-       },
-
-
-       /**
-        * Starts submitting state changes to server
-        */
-       start: function() {
-               this.dt.delay(this.delay);
-               this.started = true;
-       },
-
-
-       /**
-        * Stops submitting state changes
-        */
-       stop: function() {
-               this.dt.cancel();
-               this.started = false;
-       },
-
-
-       /**
-        * private, queues the state change if state has changed
-        */
-       queueChange: function(name, value) {
-               var o = {};
-               var i;
-               var found = false;
-
-               var lastValue = this.state[name];
-               for (i = 0; i < this.queue.length; i++) {
-                       if (this.queue[i].name === name) {
-                               lastValue = this.queue[i].value;
-                       }
-               }
-               var changed = undefined === lastValue || lastValue !== value;
-
-               if (changed) {
-                       o[this.paramNames.name] = name;
-                       o[this.paramNames.value] = value;
-                       for (i = 0; i < this.queue.length; i++) {
-                               if (this.queue[i].name === o.name) {
-                                       this.queue[i] = o;
-                                       found = true;
-                               }
-                       }
-                       if (false === found) {
-                               this.queue.push(o);
-                       }
-                       this.dirty = true;
-               }
-               if (this.started) {
-                       this.start();
-               }
-               return changed;
-       },
-
-
-       /**
-        * private, submits state to server by asynchronous Ajax request
-        */
-       submitState: function() {
-               if (!this.dirty) {
-                       this.dt.delay(this.delay);
-                       return;
-               }
-               this.dt.cancel();
-
-               var o = {
-                       scope: this,
-                       success: this.onSaveSuccess,
-                       failure: this.onSaveFailure,
-                       queue: this.queue, //this.clone(this.queue),
-                       params: {}
-               };
-
-               var params = Ext.apply({}, this.saveBaseParams);
-               params[this.paramNames.key] = this.key;
-               params[this.paramNames.data] = Ext.encode(o.queue);
-
-               Ext.apply(o.params, params);
-
-               // be optimistic
-               this.dirty = false;
-
-          TYPO3.ExtDirectStateProvider.ExtDirect.setState(o, function(response, options) {
-                  if (response.success) {
-                               this.onSaveSuccess(response, options);
-                  } else {
-                               this.onSaveFailure(response, options);
-                  }
-          }, this);
-       },
-
-
-       /**
-        * Clears the state variable
-        * @param {String} name Name of the variable to clear
-        */
-       clear: function(name) {
-               this.set(name, undefined);
-       },
-
-
-       /**
-        * private, save success callback
-        */
-       onSaveSuccess: function(response, options) {
-               var o = response;
-               if (!o.success) {
-                       if (this.logFailure) {
-                               this.log(this.saveFailureText, o, response);
-                       }
-                       this.dirty = true;
-               } else {
-                       Ext.each(response.params.queue, function(item) {
-                               if (!item) {
-                                       return;
-                               }
-                               var name = item[this.paramNames.name];
-                               var value = item[this.paramNames.value];
-
-                               if (value === undefined || value === null) {
-                                       TYPO3.state.ExtDirectProvider.superclass.clear.call(this, name);
-                               } else {
-                                               // parent sets value and fires event
-                                       TYPO3.state.ExtDirectProvider.superclass.set.call(this, name, value);
-                               }
-                       }, this);
-                       if (!this.dirty) {
-                               this.queue = [];
-                       }else {
-                               var i, j, found;
-                               for (i = 0; i < response.params.queue.length; i++) {
-                                       found = false;
-                                       for (j = 0; j < this.queue.length; j++) {
-                                               if (response.params.queue[i].name === this.queue[j].name) {
-                                                       found = true;
-                                                       break;
-                                               }
-                                       }
-                                       if (found && response.params.queue[i].value === this.queue[j].value) {
-                                               this.queue.remove(this.queue[j]);
-                                       }
-                               }
-                       }
-                       if (this.logSuccess) {
-                               this.log(this.saveSuccessText, o, response);
-                       }
-                       this.fireEvent('savesuccess', this);
-               }
-       },
-
-
-       /**
-        * private, save failure callback
-        */
-       onSaveFailure: function(response, options) {
-               if (true === this.logFailure) {
-                       this.log(this.saveFailureText, response);
-               }
-               this.dirty = true;
-               this.fireEvent('savefailure', this);
-       },
-
-
-       /**
-        * private, read state callback
-        */
-       onReadFailure: function(response, options) {
-               if (this.logFailure) {
-                       this.log(this.readFailureText, response);
-               }
-               this.fireEvent('readfailure', this);
-
-       },
-
-
-       /**
-        * private, read success callback
-        */
-       onReadSuccess: function(response, options) {
-               var o = response, data;
-               if (!o.success) {
-                       if (this.logFailure) {
-                               this.log(this.readFailureText, o, response);
-                       }
-               } else {
-                       data = o[this.paramNames.data];
-                       Ext.iterate(data, function(key, value) {
-                               this.state[key] = value;
-                       }, this);
-                       this.queue = [];
-                       this.dirty = false;
-                       if (this.logSuccess) {
-                               this.log(this.readSuccessText, data, response);
-                       }
-                       this.fireEvent('readsuccess', this);
-               }
-       },
-
-
-       /**
-        * Reads saved state from server by sending asynchronous Ajax request and processing the response
-        */
-       readState: function() {
-               var o = {
-                       scope: this,
-                       params:{}
-               };
-
-               var params = Ext.apply({}, this.readBaseParams);
-               params[this.paramNames.key] = this.key;
-
-               Ext.apply(o.params, params);
-               TYPO3.ExtDirectStateProvider.ExtDirect.getState(o, function(response, options) {
-                  if (response.success) {
-                               this.onReadSuccess(response, options);
-                  } else {
-                               this.onReadFailure(response, options);
-                  }
-          }, this);
-       },
-
-
-       /**
-        * private, logs errors or successes
-        */
-       log: function() {
-               if (console) {
-                       console.log.apply(console, arguments);
-               }
-       },
-
-       logState: function() {
-          if (console) {
-                       console.log(this.state);
-               }
-       }
-
-});
index 4b95514..2ad8ab6 100644 (file)
@@ -544,10 +544,6 @@ class Bootstrap
                 'TYPO3.Components.PageTree.ContextMenuDataProvider',
                 \TYPO3\CMS\Backend\ContextMenu\Pagetree\Extdirect\ContextMenuConfiguration::class
             );
-            ExtensionManagementUtility::registerExtDirectComponent(
-                'TYPO3.ExtDirectStateProvider.ExtDirect',
-                \TYPO3\CMS\Backend\InterfaceState\ExtDirect\DataProvider::class
-            );
         }
         return $this;
     }
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-79227-RemovedExtDirectStateProvider.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-79227-RemovedExtDirectStateProvider.rst
new file mode 100644 (file)
index 0000000..bdca2e8
--- /dev/null
@@ -0,0 +1,51 @@
+.. include:: ../../Includes.txt
+
+===================================================
+Breaking: #79227 - Removed ExtDirect State Provider
+===================================================
+
+See :issue:`79227`
+
+Description
+===========
+
+The ExtDirect based State Provider for ExtJS applications (endpoint `TYPO3.ExtDirectStateProvider.ExtDirect`) has been removed.
+
+The ExtDirect endpoint `TYPO3.ExtDirectStateProvider.ExtDirect` is no longer available.
+
+The following PHP classes have been removed:
+* `\TYPO3\CMS\Backend\InterfaceState\ExtDirect\DataProvider`
+* `\TYPO3\CMS\Backend\Tree\AbstractTreeStateProvider`
+* `\TYPO3\CMS\Backend\Tree\AbstractExtJsTree`
+
+The relevant JavaScript file `ExtDirect.StateProvider.js` has been removed.
+
+The PHP method php:`DocumentTemplate->setExtDirectStateProvider()` to load the JavaScript file has been removed.
+
+Instead the jQuery-based AMD module `TYPO3\CMS\Backend\Storage` is incorporated to load the data the same way via an anonymous
+State Provider which is handed to ExtJS as long as ExtJS is still available in the TYPO3 Core.
+
+
+Impact
+======
+
+Accessing the ExtDirect endpoint will result in a JavaScript error. Loading the JavaScript file will result in a HTTP 404 error.
+
+Instantiating the PHP class will result in a fatal PHP error.
+
+
+Affected Installations
+======================
+
+Any installation using custom implementations with ExtDirect and the State Provider shipped with the TYPO3 Core.
+
+
+Migration
+=========
+
+Include the `TYPO3\CMS\Backend\Storage`, and use the UserSettingsController class directly on the PHP side to
+access the user settings.
+
+See the implementation of the JavaScript Storage object for a more detailed usage.
+
+.. index:: JavaScript