[BUGFIX] Faulty expand/collapse behavior in Element Browser 77/23877/5
authorOliver Hader <oliver@typo3.org>
Wed, 7 Aug 2013 17:01:53 +0000 (19:01 +0200)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Tue, 17 Sep 2013 18:31:46 +0000 (20:31 +0200)
On using the element browser in combination with files, the
expand/collapse behavior is wrong. On opening a collapsed folder,
an AJAX call fetches the sub-nodes that will be added to the DOM
tree. However, the calling scope of the original rendering
process and the AJAX call differ a lot.
The only possibility to get this working is to transfer the
scope and rebuild it in the AJAX context.

Change-Id: I1bf7b56ae2d82d15e0246bd651f77793adde705b
Fixes: #45859
Releases: 6.0, 6.1, 6.2
Reviewed-on: https://review.typo3.org/23877
Reviewed-by: Wouter Wolters
Tested-by: Wouter Wolters
Reviewed-by: Anja Leichsenring
Tested-by: Anja Leichsenring
typo3/class.browse_links.php
typo3/js/tree.js
typo3/sysext/backend/Classes/Controller/FileSystemNavigationFrameController.php
typo3/sysext/backend/Classes/Tree/View/FolderTreeView.php

index 00513ff..bab1c60 100644 (file)
@@ -292,6 +292,11 @@ class TBE_FolderTree extends localFolderTree {
        public $ext_noTempRecyclerDirs = 0;
 
        /**
+        * @var array
+        */
+       protected $scope;
+
+       /**
         * Returns TRUE if the input "record" contains a folder which can be linked.
         *
         * @param \TYPO3\CMS\Core\Resource\Folder $folderObject object with information about the folder element. Contains keys like title, uid, path, _title
@@ -323,6 +328,28 @@ class TBE_FolderTree extends localFolderTree {
                }
        }
 
+       /**
+        * Wrap the plus/minus icon in a link
+        *
+        * @param string $icon HTML string to wrap, probably an image tag.
+        * @param string $cmd Command for 'PM' get var
+        * @param boolean $isExpand Whether to be expanded
+        * @return string Link-wrapped input string
+        * @internal
+        */
+       public function PMiconATagWrap($icon, $cmd, $isExpand = TRUE) {
+               $this->scope = array(
+                       'class' => get_class($this),
+                       'script' => $this->thisScript,
+                       'ext_noTempRecyclerDirs' => $this->ext_noTempRecyclerDirs,
+                       'browser' => array(
+                               'mode' => $GLOBALS['SOBE']->browser->mode,
+                               'act' => $GLOBALS['SOBE']->browser->act,
+                       ),
+               );
+
+               return parent::PMiconATagWrap($icon, $cmd, $isExpand);
+       }
 }
 
 /*
index 36e3e24..d3d21c2 100644 (file)
@@ -124,10 +124,16 @@ var Tree = {
        pageID: 0,
 
        // reloads a part of the page tree (useful when "expand" / "collapse")
-       load: function(params, isExpand, obj) {
+       load: function(params, isExpand, obj, scopeData, scopeHash) {
+               var scope = '';
+
+               if (scopeData && scopeHash) {
+                       scope = '&scopeData=' + encodeURIComponent(scopeData) + '&scopeHash=' + encodeURIComponent(scopeHash);
+               }
+
                        // fallback if AJAX is not possible (e.g. IE < 6)
                if (typeof Ajax.getTransport() !== 'object') {
-                       window.location.href = this.thisScript + '?ajaxID=' + this.ajaxID + '&PM=' + encodeURIComponent(params);
+                       window.location.href = this.thisScript + '?ajaxID=' + this.ajaxID + '&PM=' + encodeURIComponent(params) + scope;
                        return;
                }
 
@@ -150,7 +156,7 @@ var Tree = {
                
                var call = new Ajax.Request(this.thisScript, {
                        method: 'get',
-                       parameters: 'ajaxID=' + this.ajaxID + '&PM=' + encodeURIComponent(params),
+                       parameters: 'ajaxID=' + this.ajaxID + '&PM=' + encodeURIComponent(params) + scope,
                        onComplete: function(xhr) {
                                // the parent node needs to be overwritten, not the object
                                $(obj.parentNode.parentNode).replace(xhr.responseText);
index 479b148..468371e 100644 (file)
@@ -72,6 +72,11 @@ class FileSystemNavigationFrameController {
        public $cMR;
 
        /**
+        * @var array
+        */
+       protected $scopeData;
+
+       /**
         * Initialiation of the script class
         *
         * @return      void
@@ -83,11 +88,28 @@ class FileSystemNavigationFrameController {
                // Setting GPvars:
                $this->currentSubScript = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('currentSubScript');
                $this->cMR = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('cMR');
+
+               $scopeData = (string)\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('scopeData');
+               $scopeHash = (string)\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('scopeHash');
+
+               if (!empty($scopeData) && \TYPO3\CMS\Core\Utility\GeneralUtility::hmac($scopeData) === $scopeHash) {
+                       $this->scopeData = unserialize($scopeData);
+               }
+
                // Create folder tree object:
-               /** @var $foldertree \TYPO3\CMS\Filelist\FileListFolderTree */
-               $this->foldertree = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Filelist\\FileListFolderTree');
+               if (!empty($this->scopeData)) {
+                       $this->foldertree = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($this->scopeData['class']);
+                       $this->foldertree->thisScript = $this->scopeData['script'];
+                       $this->foldertree->ext_noTempRecyclerDirs = $this->scopeData['ext_noTempRecyclerDirs'];
+                       $GLOBALS['SOBE']->browser = new \stdClass();
+                       $GLOBALS['SOBE']->browser->mode = $this->scopeData['browser']['mode'];
+                       $GLOBALS['SOBE']->browser->act = $this->scopeData['browser']['act'];
+               } else {
+                       $this->foldertree = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Filelist\\FileListFolderTree');
+                       $this->foldertree->thisScript = 'alt_file_navframe.php';
+               }
+
                $this->foldertree->ext_IconMode = $GLOBALS['BE_USER']->getTSConfigVal('options.folderTree.disableIconLinkToContextmenu');
-               $this->foldertree->thisScript = 'alt_file_navframe.php';
        }
 
        /**
index 742a5c6..4e97f1b 100644 (file)
@@ -103,7 +103,14 @@ class FolderTreeView extends \TYPO3\CMS\Backend\Tree\View\AbstractTreeView {
        public function PMiconATagWrap($icon, $cmd, $isExpand = TRUE) {
                if ($this->thisScript) {
                        // Activates dynamic AJAX based tree
-                       $js = htmlspecialchars('Tree.load(\'' . $cmd . '\', ' . intval($isExpand) . ', this);');
+                       $scopeData = '';
+                       $scopeHash = '';
+                       // $this->scope is defined in TBE_FolderTree
+                       if (!empty($this->scope)) {
+                               $scopeData = serialize($this->scope);
+                               $scopeHash = \TYPO3\CMS\Core\Utility\GeneralUtility::hmac($scopeData);
+                       }
+                       $js = htmlspecialchars('Tree.load(\'' . $cmd . '\', ' . intval($isExpand) . ', this, \'' . $scopeData . '\', \'' . $scopeHash . '\');');
                        return '<a class="pm" onclick="' . $js . '">' . $icon . '</a>';
                } else {
                        return $icon;