diff --git a/typo3/sysext/backend/Classes/Controller/BackendController.php b/typo3/sysext/backend/Classes/Controller/BackendController.php index fb5c0fcf87d83c2685ef5c4a0f4ba8829ceafa22..ba7be9039182efae124966c403003de4a69d75a1 100644 --- a/typo3/sysext/backend/Classes/Controller/BackendController.php +++ b/typo3/sysext/backend/Classes/Controller/BackendController.php @@ -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 index b8bcae0c1a5a76efdbb0ed9ec33566b5e854ddd4..0000000000000000000000000000000000000000 --- a/typo3/sysext/backend/Classes/InterfaceState/ExtDirect/DataProvider.php +++ /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 - ]; - } -} diff --git a/typo3/sysext/backend/Classes/Template/DocumentTemplate.php b/typo3/sysext/backend/Classes/Template/DocumentTemplate.php index e4c5bdbf3f0953924b3aa2834cac4790bc71dcf8..1468ce28ff7d033a6f6ec87440486e17de21fd95 100644 --- a/typo3/sysext/backend/Classes/Template/DocumentTemplate.php +++ b/typo3/sysext/backend/Classes/Template/DocumentTemplate.php @@ -234,11 +234,6 @@ function jumpToUrl(URL) { */ protected $pageHeaderFooterTemplateFile = ''; - /** - * @var bool - */ - protected $extDirectStateProvider = false; - /** * Whether flashmessages should be rendered or not * @@ -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 index e7ceb3d72a90173761b5d7bdc187433eab01ee5c..0000000000000000000000000000000000000000 --- a/typo3/sysext/backend/Classes/Tree/AbstractExtJsTree.php +++ /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 index 46d320506363d23e6823121f643d3183c645ee14..0000000000000000000000000000000000000000 --- a/typo3/sysext/backend/Classes/Tree/AbstractTreeStateProvider.php +++ /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(); -} diff --git a/typo3/sysext/backend/Classes/Tree/Pagetree/ExtdirectTreeDataProvider.php b/typo3/sysext/backend/Classes/Tree/Pagetree/ExtdirectTreeDataProvider.php index 0ac6b4894106aeef063136a8374949a10395eada..638de8793b75c7b63c77473506f7b9faab6fbef7 100644 --- a/typo3/sysext/backend/Classes/Tree/Pagetree/ExtdirectTreeDataProvider.php +++ b/typo3/sysext/backend/Classes/Tree/Pagetree/ExtdirectTreeDataProvider.php @@ -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 index 978a7d118bad5116902b1a3a234efbb9a21b08f5..0000000000000000000000000000000000000000 --- a/typo3/sysext/backend/Resources/Public/JavaScript/ExtDirect.StateProvider.js +++ /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); - } - } - -}); diff --git a/typo3/sysext/core/Classes/Core/Bootstrap.php b/typo3/sysext/core/Classes/Core/Bootstrap.php index 4b95514cf93deda2a6e7220bc40c8db8cad2c010..2ad8ab6d4dba70142e59ee707a56240a41600f4b 100644 --- a/typo3/sysext/core/Classes/Core/Bootstrap.php +++ b/typo3/sysext/core/Classes/Core/Bootstrap.php @@ -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 index 0000000000000000000000000000000000000000..bdca2e8db16177aa398c97f1ca086b1c170d5108 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Breaking-79227-RemovedExtDirectStateProvider.rst @@ -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