[BUGFIX] Pagetree should expand to the last selected node
authorStefan Galinski <stefan.galinski@gmail.com>
Thu, 12 Apr 2012 13:51:39 +0000 (15:51 +0200)
committerStefan Galinski <stefan.galinski@gmail.com>
Thu, 12 Apr 2012 22:03:14 +0000 (00:03 +0200)
The patch integrates the expansion to the last selected node
at least for the following functions:
- selected node of the filtering tree
- OpenDocs
- Shortcuts (if possible)
- Live Search

Fixes: #25006
Fixes: #33853
Releases: 6.0, 4.7, 4.6, 4.5

Change-Id: I1a47bedd10a37a8931ccd50c7fd119399834d909
Reviewed-on: http://review.typo3.org/10357
Reviewed-by: Jigal van Hemert
Tested-by: Jigal van Hemert
Reviewed-by: Wouter Wolters
Tested-by: Marcus Schwemer
Reviewed-by: Stefan Galinski
Tested-by: Stefan Galinski
t3lib/js/extjs/components/pagetree/javascript/actions.js
t3lib/js/extjs/components/pagetree/javascript/app.js
t3lib/search/class.t3lib_search_livesearch.php
t3lib/tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php
t3lib/tree/pagetree/class.t3lib_tree_pagetree_node.php
t3lib/tree/pagetree/extdirect/class.t3lib_tree_pagetree_extdirect_commands.php
t3lib/tree/pagetree/extdirect/class.t3lib_tree_pagetree_extdirect_tree.php
typo3/classes/class.shortcutmenu.php
typo3/js/backend.js
typo3/js/livesearch.js
typo3/sysext/opendocs/class.tx_opendocs.php

index df9875b..07dfd09 100644 (file)
@@ -706,6 +706,14 @@ TYPO3.Components.PageTree.Actions = {
                node.select();
                if (tree.stateHash) {
                        tree.stateHash.lastSelectedNode = node.id;
+               } else {
+                       TYPO3.Components.PageTree.Commands.addRootlineOfNodeToStateHash(
+                               TYPO3.Backend.NavigationContainer.PageTree.mainTree.stateId,
+                               node.attributes.nodeData.id, function(stateHash) {
+                                       TYPO3.Backend.NavigationContainer.PageTree.mainTree.stateHash = stateHash;
+                                       TYPO3.Backend.NavigationContainer.PageTree.mainTree.refreshTree();
+                               }
+                       );
                }
 
                fsMod.recentIds['web'] = node.attributes.nodeData.id;
index 6a178f5..64d275c 100644 (file)
@@ -64,6 +64,13 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, {
        activeTree: null,
 
        /**
+        * Main pagetree
+        *
+        * @type {TYPO3.Components.PageTree.Tree}
+        */
+       mainTree: null,
+
+       /**
         * Initializes the application
         *
         * Set's the necessary language labels, configuration options and sprite icons by an
@@ -77,7 +84,7 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, {
                        TYPO3.Components.PageTree.Configuration = response['Configuration'];
                        TYPO3.Components.PageTree.Sprites = response['Sprites'];
 
-                       var tree = this.activeTree = new TYPO3.Components.PageTree.Tree({
+                       this.mainTree = this.activeTree = new TYPO3.Components.PageTree.Tree({
                                id: this.id + '-tree',
                                deletionDropZoneId: this.id + '-deletionDropZone',
                                ddGroup: this.id,
@@ -120,7 +127,7 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, {
                                dataProvider: TYPO3.Components.PageTree.DataProvider,
                                filteringTree: filteringTree,
                                ddGroup: this.id,
-                               tree: tree,
+                               tree: this.mainTree,
                                app: this
                        });
 
@@ -155,7 +162,7 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, {
                                                id: this.id + '-treeContainer',
                                                region: 'center',
                                                layout: 'fit',
-                                               items: [tree, filteringTree]
+                                               items: [this.mainTree, filteringTree]
                                        },
                                        deletionDropZone
                                ]
@@ -350,26 +357,18 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, {
         * store the new location into the state hash.
         *
         * @param {int} pageId
-        * @param {Boolean} saveState
         * @return {Boolean}
         */
-       select: function(pageId, saveState) {
-               if (saveState !== false) {
-                       saveState = true;
-               }
-
-               var tree = this.getTree();
-               var succeeded = false;
-               var node = tree.getRootNode().findChild('realId', pageId, true);
-               if (node) {
-                       succeeded = true;
-                       tree.selectPath(node.getPath());
-                       if (!!saveState && tree.stateHash) {
-                               tree.stateHash.lastSelectedNode = node.id;
+       select: function(pageId) {
+               TYPO3.Components.PageTree.Commands.addRootlineOfNodeToStateHash(
+                       TYPO3.Backend.NavigationContainer.PageTree.mainTree.stateId,
+                       pageId, function(stateHash) {
+                               TYPO3.Backend.NavigationContainer.PageTree.mainTree.stateHash = stateHash;
+                               TYPO3.Backend.NavigationContainer.PageTree.mainTree.refreshTree();
                        }
-               }
+               );
 
-               return succeeded;
+               return true;
        },
 
        /**
index 5c79596..1182e75 100644 (file)
@@ -246,6 +246,7 @@ class t3lib_search_livesearch {
                while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
                        $collect[] = array(
                                'id' => $tableName . ':' . $row['uid'],
+                               'pageId' => ($tableName === 'pages' ? $row['uid'] : $row['pid']),
                                'recordTitle' => ($isFirst) ? $this->getRecordTitlePrep($this->getTitleOfCurrentRecordType($tableName), self::GROUP_TITLE_MAX_LENGTH) : '',
                                'iconHTML' => t3lib_iconWorks::getSpriteIconForRecord($tableName, $row),
                                'title' => $this->getRecordTitlePrep($this->getTitleFromCurrentRow($tableName, $row), self::RECORD_TITLE_MAX_LENGTH),
index 9ff4617..2998f10 100644 (file)
@@ -124,24 +124,25 @@ class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider {
                        // check if fetching subpages the "root"-page
                        // and in case of a virtual root return the mountpoints as virtual "subpages"
                if (intval($node->getId()) === 0) {
-                       $mountPoints = intval($GLOBALS['BE_USER']->uc['pageTree_temporaryMountPoint']);
                                // check no temporary mountpoint is used
-                       if (!$mountPoints) {
+                       if (!intval($GLOBALS['BE_USER']->uc['pageTree_temporaryMountPoint'])) {
                                $mountPoints = array_map('intval', $GLOBALS['BE_USER']->returnWebmounts());
                                $mountPoints = array_unique($mountPoints);
                                if (!in_array(0, $mountPoints)) {
                                                // using a virtual root node
                                                // so then return the mount points here as "subpages" of the first node
                                        $subpages = array();
-                                       foreach ($mountPoints as $mountPoint) {
-                                               $subpages[] = array('uid' => $mountPoint);
+                                       foreach ($mountPoints as $webMountPoint) {
+                                               $subpages[] = array(
+                                                       'uid' => $webMountPoint,
+                                                       'isMountPoint' => TRUE,
+                                               );
                                        }
                                }
                        }
                }
 
                if (is_array($subpages) && count($subpages) > 0) {
-
                        foreach ($subpages as $subpage) {
                                if (in_array($subpage['uid'], $this->hiddenRecords)) {
                                        continue;
@@ -152,6 +153,12 @@ class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider {
                                        continue;
                                }
 
+                                       // This was the real mountpoint below the virtual root node.
+                                       // Use this as mountpoint for the subpages of this page.
+                               if ($subpage['isMountPoint']) {
+                                       $mountPoint = $subpage['uid'];
+                               }
+
                                $subNode = t3lib_tree_pagetree_Commands::getNewNode($subpage, $mountPoint);
                                if ($this->nodeCounter < $this->nodeLimit) {
                                        $childNodes = $this->getNodes($subNode, $mountPoint, $level + 1);
@@ -193,6 +200,15 @@ class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider {
                        return $nodeCollection;
                }
 
+                       // check no temporary mountpoint is used
+               $mountPoints = intval($GLOBALS['BE_USER']->uc['pageTree_temporaryMountPoint']);
+               if (!$mountPoints) {
+                       $mountPoints = array_map('intval', $GLOBALS['BE_USER']->returnWebmounts());
+                       $mountPoints = array_unique($mountPoints);
+               } else {
+                       $mountPoints = array($mountPoints);
+               }
+
                $isNumericSearchFilter = (is_numeric($searchFilter) && $searchFilter > 0);
                $nodeId = intval($node->getId());
                foreach ($records as $record) {
@@ -201,18 +217,34 @@ class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider {
                                continue;
                        }
 
-                       $rootline = t3lib_BEfunc::BEgetRootLine($record['uid'], ' AND uid != ' . $nodeId);
+                       $rootline = t3lib_BEfunc::BEgetRootLine(
+                               $record['uid'], '', ($GLOBALS['BE_USER']->workspace != 0)
+                       );
                        $rootline = array_reverse($rootline);
                        if ($nodeId === 0) {
                                array_shift($rootline);
                        }
+
+                       if ($mountPoints != array(0)) {
+                               $isInsideMountPoints = FALSE;
+                               foreach ($rootline as $rootlineElement) {
+                                       if (in_array(intval($rootlineElement['uid']), $mountPoints, TRUE)) {
+                                               $isInsideMountPoints = TRUE;
+                                               break;
+                                       }
+                               }
+
+                               if (!$isInsideMountPoints) {
+                                       continue;
+                               }
+                       }
                        $reference = $nodeCollection;
 
                        $inFilteredRootline = FALSE;
                        $amountOfRootlineElements = count($rootline);
                        for ($i = 0; $i < $amountOfRootlineElements; ++$i) {
                                $rootlineElement = $rootline[$i];
-                               if (intval($rootlineElement['pid']) === $nodeId) {
+                               if (intval($rootlineElement['pid']) === $nodeId || intval($rootlineElement['uid']) === $nodeId) {
                                        $inFilteredRootline = TRUE;
                                }
 
@@ -252,7 +284,7 @@ class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider {
                                        /** @var $childCollection t3lib_tree_pagetree_NodeCollection */
                                        $childCollection = t3lib_div::makeInstance('t3lib_tree_pagetree_NodeCollection');
 
-                                       if (($i +1) >= $amountOfRootlineElements) {
+                                       if (($i + 1) >= $amountOfRootlineElements) {
                                                $childNodes = $this->getNodes($refNode, $mountPoint);
                                                foreach ($childNodes as $childNode) {
                                                        /** @var $childNode t3lib_tree_pagetree_Node */
index 91af17c..0365b97 100644 (file)
@@ -299,6 +299,16 @@ class t3lib_tree_pagetree_Node extends t3lib_tree_extdirect_Node {
        }
 
        /**
+        * Returns the calculated id representation of this node
+        *
+        * @param string $prefix defaults to 'p'
+        * @return string
+        */
+       public function calculateNodeId($prefix = 'p') {
+               return $prefix . dechex($this->getId()) . ($this->getMountPoint() ? '-' . dechex($this->getMountPoint()) : '');
+       }
+
+       /**
         * Returns the node in an array representation that can be used for serialization
         *
         * @param bool $addChildNodes
@@ -307,7 +317,7 @@ class t3lib_tree_pagetree_Node extends t3lib_tree_extdirect_Node {
        public function toArray($addChildNodes = TRUE) {
                $arrayRepresentation = parent::toArray();
 
-               $arrayRepresentation['id'] = 'p' . dechex($this->getId()) . ($this->getMountPoint() ? '-' . dechex($this->getMountPoint()) : '');
+               $arrayRepresentation['id'] = $this->calculateNodeId();
                $arrayRepresentation['realId'] = $this->getId();
                $arrayRepresentation['nodeData']['id'] = $this->getId();
 
index a3a33da..c8f317f 100644 (file)
@@ -43,9 +43,6 @@ class t3lib_tree_pagetree_extdirect_Commands {
                /** @var $node t3lib_tree_pagetree_Node */
                $node = t3lib_div::makeInstance('t3lib_tree_pagetree_Node', (array) $nodeData);
 
-               /** @var $dataProvider t3lib_tree_pagetree_DataProvider */
-               $dataProvider = t3lib_div::makeInstance('t3lib_tree_pagetree_DataProvider');
-
                try {
                        t3lib_tree_pagetree_Commands::visiblyNode($node);
                        $newNode = t3lib_tree_pagetree_Commands::getNode($node->getId());
@@ -71,9 +68,6 @@ class t3lib_tree_pagetree_extdirect_Commands {
                /** @var $node t3lib_tree_pagetree_Node */
                $node = t3lib_div::makeInstance('t3lib_tree_pagetree_Node', (array) $nodeData);
 
-               /** @var $dataProvider t3lib_tree_pagetree_DataProvider */
-               $dataProvider = t3lib_div::makeInstance('t3lib_tree_pagetree_DataProvider');
-
                try {
                        t3lib_tree_pagetree_Commands::disableNode($node);
                        $newNode = t3lib_tree_pagetree_Commands::getNode($node->getId());
@@ -370,6 +364,58 @@ class t3lib_tree_pagetree_extdirect_Commands {
 
                return $match[1];
        }
+
+       /**
+        * Adds the rootline of a given node to the tree expansion state and adds the node
+        * itself as the current selected page. This leads to the expansion and selection of
+        * the node in the tree after a refresh.
+        *
+        * @static
+        * @param string $stateId
+        * @param int $nodeId
+        * @return array
+        */
+       public static function addRootlineOfNodeToStateHash($stateId, $nodeId) {
+               $mountPoints = array_map('intval', $GLOBALS['BE_USER']->returnWebmounts());
+               if (count($mountPoints) == 0) {
+                       $mountPoints = array(0);
+               }
+               $mountPoints[] = intval($GLOBALS['BE_USER']->uc['pageTree_temporaryMountPoint']);
+               $mountPoints = array_unique($mountPoints);
+
+               /** @var $userSettings extDirect_DataProvider_BackenduserSettings */
+               $userSettings = t3lib_div::makeInstance('extDirect_DataProvider_BackenduserSettings');
+               $state = $userSettings->get('BackendComponents.States.' . $stateId);
+               $state->stateHash = (object) $state->stateHash;
+
+               $rootline = t3lib_BEfunc::BEgetRootLine($nodeId, '', ($GLOBALS['BE_USER']->workspace != 0));
+               $rootlineIds = array();
+               foreach ($rootline as $pageData) {
+                       $rootlineIds[] = intval($pageData['uid']);
+               }
+
+               foreach ($mountPoints as $mountPoint) {
+                       if (!in_array($mountPoint, $rootlineIds, TRUE)) {
+                               continue;
+                       }
+
+                       $isFirstNode = TRUE;
+                       foreach ($rootline as $pageData) {
+                               $node = t3lib_tree_pagetree_Commands::getNewNode($pageData, $mountPoint);
+
+                               if ($isFirstNode) {
+                                       $isFirstNode = FALSE;
+                                       $state->stateHash->lastSelectedNode = $node->calculateNodeId();
+                               } else {
+                                       $state->stateHash->{$node->calculateNodeId('')} = 1;
+                               }
+                       }
+               }
+
+               $userSettings->set('BackendComponents.States.' . $stateId, $state);
+
+               return (array)$state->stateHash;
+       }
 }
 
 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/tree/pagetree/extdirect/class.t3lib_tree_pagetree_extdirect_commands.php'])) {
index e8df3f8..64e5847 100644 (file)
@@ -79,7 +79,7 @@ class t3lib_tree_pagetree_extdirect_Tree extends t3lib_tree_ExtDirect_AbstractEx
                if ($nodeId === 'root') {
                        $nodeCollection = $this->dataProvider->getTreeMounts();
                } else {
-                       $nodeCollection = $this->dataProvider->getNodes($node);
+                       $nodeCollection = $this->dataProvider->getNodes($node, $node->getMountPoint());
                }
 
                return $nodeCollection->toArray();
index a023307..7e0124c 100644 (file)
@@ -286,6 +286,7 @@ class ShortcutMenu implements backend_toolbarItem {
                        }
 
                                // check for module access
+                       $pageId = $this->getLinkedPageId($row['url']);
                        if(!$GLOBALS['BE_USER']->isAdmin()) {
                                if(!isset($GLOBALS['LANG']->moduleLabels['tabs_images'][implode('_', $moduleParts).'_tab'])) {
                                                // nice hack to check if the user has access to this module
@@ -293,7 +294,6 @@ class ShortcutMenu implements backend_toolbarItem {
                                        continue;
                                }
 
-                               $pageId = $this->getLinkedPageId($row['url']);
                                if(t3lib_utility_Math::canBeInterpretedAsInteger($pageId)) {
                                                // check for webmount access
                                        if(!$GLOBALS['BE_USER']->isInWebMount($pageId)) {
@@ -322,7 +322,7 @@ class ShortcutMenu implements backend_toolbarItem {
                        $shortcut['group']     = $shortcutGroup;
                        $shortcut['icon']      = $this->getShortcutIcon($row, $shortcut);
                        $shortcut['iconTitle'] = $this->getShortcutIconTitle($shortcutLabel, $row['module_name'], $row['M_module_name']);
-                       $shortcut['action']    = 'jump(unescape(\''.rawurlencode($row['url']).'\'),\''.implode('_',$moduleParts).'\',\''.$moduleParts[0].'\');';
+                       $shortcut['action']    = 'jump(unescape(\''.rawurlencode($row['url']).'\'),\''.implode('_',$moduleParts).'\',\''.$moduleParts[0].'\', ' . intval($pageId) . ');';
 
                        $lastGroup   = $row['sc_group'];
                        $shortcuts[] = $shortcut;
index a392fd7..1402429 100644 (file)
@@ -33,10 +33,13 @@ Ext.ns('TYPO3.configuration');
 /**
  * jump the backend to a module
  */
-function jump(url, modName, mainModName) {
+function jump(url, modName, mainModName, pageId) {
+       if (isNaN(pageId)) {
+               pageId = -2;
+       }
                // clear information about which entry in nav. tree that might have been highlighted.
        top.fsMod.navFrameHighlightedID = [];
-       top.fsMod.recentIds['web'] = -2;
+       top.fsMod.recentIds['web'] = pageId;
 
        if (top.TYPO3.Backend.NavigationContainer.PageTree) {
                top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
index 531a379..6d54bf7 100644 (file)
@@ -74,6 +74,7 @@ TYPO3.BackendLiveSearch = Ext.extend(Ext.form.ComboBox, {
                root : 'searchItems',
                fields : [
                        {name: 'recordTitle'},
+                       {name: 'pageId'},
                        {name: 'id'},
                        {name: 'iconHTML'},
                        {name: 'title'},
@@ -84,7 +85,7 @@ TYPO3.BackendLiveSearch = Ext.extend(Ext.form.ComboBox, {
                select : {
                        scope: this,
                        fn: function (combo, record, index) {
-                               jump(record.data.editLink, 'web_list', 'web');
+                               jump(record.data.editLink, 'web_list', 'web', record.data.pageId);
                        }
                },
                focus : {
index 7d7096c..c57ae99 100644 (file)
@@ -166,6 +166,11 @@ class tx_opendocs implements backend_toolbarItem {
                $icon   = t3lib_iconWorks::getSpriteIconForRecord($table, $record);
                $link   = $GLOBALS['BACK_PATH'] . 'alt_doc.php?' . $document[2];
 
+               $pageId = intval($document[3]['uid']);
+               if ($document[3]['table'] !== 'pages') {
+                       $pageId = intval($document[3]['pid']);
+               }
+
                $firstRow = '';
                if ($isFirstDoc) {
                        $firstRow = ' first-row';
@@ -180,7 +185,7 @@ class tx_opendocs implements backend_toolbarItem {
                        $entry = '
                                <tr class="opendoc' . $firstRow . '">
                                        <td class="icon">' . $icon . '</td>
-                                       <td class="label"><a href="#" onclick="jump(unescape(\'' . htmlspecialchars($link) . '\'), \'web_list\', \'web\'); TYPO3BackendOpenDocs.toggleMenu(); return false;" target="content">' . $label . '</a></td>
+                                       <td class="label"><a href="#" onclick="jump(unescape(\'' . htmlspecialchars($link) . '\'), \'web_list\', \'web\', ' . $pageId . '); TYPO3BackendOpenDocs.toggleMenu(); return false;" target="content">' . $label . '</a></td>
                                        <td class="close" onclick="return TYPO3BackendOpenDocs.closeDocument(\'' . $md5sum . '\');">' . $closeIcon . '</td>
                                </tr>';
                } else {
@@ -188,7 +193,7 @@ class tx_opendocs implements backend_toolbarItem {
                        $entry = '
                                <tr class="recentdoc' . $firstRow . '">
                                        <td class="icon">' . $icon . '</td>
-                                       <td class="label" colspan="2"><a href="#" onclick="jump(unescape(\'' . htmlspecialchars($link) . '\'), \'web_list\', \'web\'); TYPO3BackendOpenDocs.toggleMenu(); return false;" target="content">' . $label . '</a></td>
+                                       <td class="label" colspan="2"><a href="#" onclick="jump(unescape(\'' . htmlspecialchars($link) . '\'), \'web_list\', \'web\', ' . $pageId . '); TYPO3BackendOpenDocs.toggleMenu(); return false;" target="content">' . $label . '</a></td>
                                </tr>';
                }