[TASK] Remove superfluous parenthesis in sysext backend
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Tree / View / FolderTreeView.php
1 <?php
2 namespace TYPO3\CMS\Backend\Tree\View;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
30 * Generate a folder tree
31 *
32 * Revised for TYPO3 3.6 November/2003 by Kasper Skårhøj
33 *
34 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
35 * @coauthor René Fritz <r.fritz@colorcube.de>
36 */
37 /**
38 * Extension class for the t3lib_treeView class, specially made for browsing folders in the File module
39 *
40 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
41 * @coauthor René Fritz <r.fritz@colorcube.de>
42 * @package TYPO3
43 * @subpackage t3lib
44 * @see class t3lib_treeView
45 */
46 class FolderTreeView extends \TYPO3\CMS\Backend\Tree\View\AbstractTreeView {
47
48 /**
49 * The users' file Storages
50 *
51 * @var \TYPO3\CMS\Core\Resource\ResourceStorage[]
52 */
53 protected $storages = NULL;
54
55 /**
56 * @var array
57 */
58 protected $storageHashNumbers;
59
60 /**
61 * Indicates, whether the AJAX call was successful,
62 * i.e. the requested page has been found
63 *
64 * @var boolean
65 */
66 protected $ajaxStatus = FALSE;
67
68 /**
69 * Constructor function of the class
70 */
71 public function __construct() {
72 parent::init();
73 $this->storages = $GLOBALS['BE_USER']->getFileStorages();
74 $this->treeName = 'folder';
75 // Don't apply any title
76 $this->titleAttrib = '';
77 $this->domIdPrefix = 'folder';
78 }
79
80 /**
81 * Generate the plus/minus icon for the browsable tree.
82 *
83 * @param \TYPO3\CMS\Core\Resource\Folder $folderObject Entry folder object
84 * @param integer $subFolderCounter The current entry number
85 * @param integer $totalSubFolders The total number of entries. If equal to $a, a "bottom" element is returned.
86 * @param integer $nextCount The number of sub-elements to the current element.
87 * @param boolean $isExpanded The element was expanded to render subelements if this flag is set.
88 * @return string Image tag with the plus/minus icon.
89 * @internal
90 * @see t3lib_pageTree::PMicon()
91 */
92 public function PMicon(\TYPO3\CMS\Core\Resource\Folder $folderObject, $subFolderCounter, $totalSubFolders, $nextCount, $isExpanded) {
93 $PM = $nextCount ? ($isExpanded ? 'minus' : 'plus') : 'join';
94 $BTM = $subFolderCounter == $totalSubFolders ? 'bottom' : '';
95 $icon = '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->backPath, ('gfx/ol/' . $PM . $BTM . '.gif'), 'width="18" height="16"') . ' alt="" />';
96 if ($nextCount) {
97 $cmd = $this->generateExpandCollapseParameter($this->bank, !$isExpanded, $folderObject);
98 $icon = $this->PMiconATagWrap($icon, $cmd, !$isExpanded);
99 }
100 return $icon;
101 }
102
103 /**
104 * Wrap the plus/minus icon in a link
105 *
106 * @param string $icon HTML string to wrap, probably an image tag.
107 * @param string $cmd Command for 'PM' get var
108 * @param boolean $isExpand Whether to be expanded
109 * @return string Link-wrapped input string
110 * @internal
111 */
112 public function PMiconATagWrap($icon, $cmd, $isExpand = TRUE) {
113 if ($this->thisScript) {
114 // Activates dynamic AJAX based tree
115 $js = htmlspecialchars('Tree.load(\'' . $cmd . '\', ' . intval($isExpand) . ', this);');
116 return '<a class="pm" onclick="' . $js . '">' . $icon . '</a>';
117 } else {
118 return $icon;
119 }
120 }
121
122 /**
123 * Wrapping the folder icon
124 *
125 * @param string $icon The image tag for the icon
126 * @param \TYPO3\CMS\Core\Resource\Folder $folderObject The row for the current element
127 * @return string The processed icon input value.
128 * @internal
129 */
130 public function wrapIcon($icon, \TYPO3\CMS\Core\Resource\Folder $folderObject) {
131 // Add title attribute to input icon tag
132 $theFolderIcon = $this->addTagAttributes($icon, $this->titleAttrib ? $this->titleAttrib . '="' . $this->getTitleAttrib($folderObject) . '"' : '');
133 // Wrap icon in click-menu link.
134 if (!$this->ext_IconMode) {
135 $theFolderIcon = $GLOBALS['TBE_TEMPLATE']->wrapClickMenuOnIcon($theFolderIcon, $folderObject->getCombinedIdentifier(), '', 0);
136 } elseif (!strcmp($this->ext_IconMode, 'titlelink')) {
137 $aOnClick = 'return jumpTo(\'' . $this->getJumpToParam($folderObject) . '\',this,\'' . $this->domIdPrefix . $this->getId($folderObject) . '\',' . $this->bank . ');';
138 $theFolderIcon = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . $theFolderIcon . '</a>';
139 }
140 return $theFolderIcon;
141 }
142
143 /**
144 * Wrapping $title in a-tags.
145 *
146 * @param string $title Title string
147 * @param \TYPO3\CMS\Core\Resource\Folder $folderObject the folder record
148 * @param integer $bank Bank pointer (which mount point number)
149 * @return string
150 * @internal
151 */
152 public function wrapTitle($title, \TYPO3\CMS\Core\Resource\Folder $folderObject, $bank = 0) {
153 $aOnClick = 'return jumpTo(\'' . $this->getJumpToParam($folderObject) . '\', this, \'' . $this->domIdPrefix . $this->getId($folderObject) . '\', ' . $bank . ');';
154 $CSM = ' oncontextmenu="' . htmlspecialchars($GLOBALS['TBE_TEMPLATE']->wrapClickMenuOnIcon('', $folderObject->getCombinedIdentifier(), '', 0, ('&bank=' . $this->bank), '', TRUE)) . '"';
155 return '<a href="#" title="' . htmlspecialchars($title) . '" onclick="' . htmlspecialchars($aOnClick) . '"' . $CSM . '>' . $title . '</a>';
156 }
157
158 /**
159 * Returns the id from the record - for folders, this is an md5 hash.
160 *
161 * @param \TYPO3\CMS\Core\Resource\Folder $folderObject The folder object
162 * @return integer The "uid" field value.
163 */
164 public function getId(\TYPO3\CMS\Core\Resource\Folder $folderObject) {
165 return \TYPO3\CMS\Core\Utility\GeneralUtility::md5Int($folderObject->getCombinedIdentifier());
166 }
167
168 /**
169 * Returns jump-url parameter value.
170 *
171 * @param \TYPO3\CMS\Core\Resource\Folder $folderObject The folder object
172 * @return string The jump-url parameter.
173 */
174 public function getJumpToParam(\TYPO3\CMS\Core\Resource\Folder $folderObject) {
175 return rawurlencode($folderObject->getCombinedIdentifier());
176 }
177
178 /**
179 * Returns the title for the input record. If blank, a "no title" labele (localized) will be returned.
180 * '_title' is used for setting an alternative title for folders.
181 *
182 * @param array $row The input row array (where the key "_title" is used for the title)
183 * @param integer $titleLen Title length (30)
184 * @return string The title
185 */
186 public function getTitleStr($row, $titleLen = 30) {
187 return $row['_title'] ? $row['_title'] : parent::getTitleStr($row, $titleLen);
188 }
189
190 /**
191 * Returns the value for the image "title" attribute
192 *
193 * @param \TYPO3\CMS\Core\Resource\Folder $folderObject The folder to be used
194 * @return string The attribute value (is htmlspecialchared() already)
195 * @todo Define visibility
196 */
197 public function getTitleAttrib(\TYPO3\CMS\Core\Resource\Folder $folderObject) {
198 return htmlspecialchars($folderObject->getName());
199 }
200
201 /**
202 * Will create and return the HTML code for a browsable tree of folders.
203 * Is based on the mounts found in the internal array ->MOUNTS (set in the constructor)
204 *
205 * @return string HTML code for the browsable tree
206 */
207 public function getBrowsableTree() {
208 // Get stored tree structure AND updating it if needed according to incoming PM GET var.
209 $this->initializePositionSaving();
210 // Init done:
211 $treeItems = array();
212 // Traverse mounts:
213 foreach ($this->storages as $storageObject) {
214 $this->getBrowseableTreeForStorage($storageObject);
215 // Add tree:
216 $treeItems = array_merge($treeItems, $this->tree);
217 // if this is an AJAX call, don't run through all mounts, only
218 // show the expansion of the current one, not the rest of the mounts
219 if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
220
221 }
222 }
223 return $this->printTree($treeItems);
224 }
225
226 /**
227 * Get a tree for one storage
228 *
229 * @param \TYPO3\CMS\Core\Resource\ResourceStorage $storageObject
230 * @return void
231 */
232 public function getBrowseableTreeForStorage(\TYPO3\CMS\Core\Resource\ResourceStorage $storageObject) {
233 // If there are filemounts, show each, otherwise just the rootlevel folder
234 $fileMounts = $storageObject->getFileMounts();
235 $rootLevelFolders = array();
236 if (count($fileMounts)) {
237 foreach ($fileMounts as $fileMountInfo) {
238 $rootLevelFolders[] = array(
239 'folder' => $fileMountInfo['folder'],
240 'name' => $fileMountInfo['title']
241 );
242 }
243 } else {
244 $rootLevelFolders[] = array(
245 'folder' => $storageObject->getRootLevelFolder(),
246 'name' => $storageObject->getName()
247 );
248 }
249 // Clean the tree
250 $this->reset();
251 // Go through all "root level folders" of this tree (can be the rootlevel folder or any file mount points)
252 foreach ($rootLevelFolders as $rootLevelFolderInfo) {
253 /** @var $rootLevelFolder \TYPO3\CMS\Core\Resource\Folder */
254 $rootLevelFolder = $rootLevelFolderInfo['folder'];
255 $rootLevelFolderName = $rootLevelFolderInfo['name'];
256 $folderHashSpecUID = \TYPO3\CMS\Core\Utility\GeneralUtility::md5int($rootLevelFolder->getCombinedIdentifier());
257 $this->specUIDmap[$folderHashSpecUID] = $rootLevelFolder->getCombinedIdentifier();
258 // Hash key
259 $storageHashNumber = $this->getShortHashNumberForStorage($storageObject, $rootLevelFolder);
260 // Set first:
261 $this->bank = $storageHashNumber;
262 $isOpen = $this->stored[$storageHashNumber][$folderHashSpecUID] || $this->expandFirst;
263 // Set PM icon:
264 $cmd = $this->generateExpandCollapseParameter($this->bank, !$isOpen, $rootLevelFolder);
265 if (!$storageObject->isBrowsable() || $this->getNumberOfSubfolders($storageObject->getRootLevelFolder()) === 0) {
266 $rootIcon = 'blank';
267 } elseif (!$isOpen) {
268 $rootIcon = 'plusonly';
269 } else {
270 $rootIcon = 'minusonly';
271 }
272 $icon = '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->backPath, ('gfx/ol/' . $rootIcon . '.gif')) . ' alt="" />';
273 $firstHtml = $this->PM_ATagWrap($icon, $cmd);
274 // @todo: create sprite icons for user/group mounts etc
275 if ($storageObject->isBrowsable() === FALSE) {
276 $icon = 'apps-filetree-folder-locked';
277 } else {
278 $icon = 'apps-filetree-root';
279 }
280 // Mark a storage which is not online, as offline
281 // maybe someday there will be a special icon for this
282 if ($storageObject->isOnline() === FALSE) {
283 $rootLevelFolderName .= ' (' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_file.xlf:sys_file_storage.isOffline') . ')';
284 }
285 // Preparing rootRec for the mount
286 $firstHtml .= $this->wrapIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon($icon), $rootLevelFolder);
287 $row = array(
288 'uid' => $folderHashSpecUID,
289 'title' => $rootLevelFolderName,
290 'path' => $rootLevelFolder->getCombinedIdentifier(),
291 'folder' => $rootLevelFolder
292 );
293 // Add the storage root to ->tree
294 $this->tree[] = array(
295 'HTML' => $firstHtml,
296 'row' => $row,
297 'bank' => $this->bank,
298 // hasSub is TRUE when the root of the storage is expanded
299 'hasSub' => $isOpen && $storageObject->isBrowsable()
300 );
301 // If the mount is expanded, go down:
302 if ($isOpen && $storageObject->isBrowsable()) {
303 // Set depth:
304 $this->getFolderTree($rootLevelFolder, 999);
305 }
306 }
307 }
308
309 /**
310 * Fetches the data for the tree
311 *
312 * @param \TYPO3\CMS\Core\Resource\Folder $folderObject the folderobject
313 * @param integer $depth Max depth (recursivity limit)
314 * @param string $type HTML-code prefix for recursive calls.
315 * @return integer The count of items on the level
316 * @see getBrowsableTree()
317 */
318 public function getFolderTree(\TYPO3\CMS\Core\Resource\Folder $folderObject, $depth = 999, $type = '') {
319 $depth = intval($depth);
320 // This generates the directory tree
321 $subFolders = $folderObject->getSubfolders();
322 sort($subFolders);
323 $totalSubFolders = count($subFolders);
324 $HTML = '';
325 $subFolderCounter = 0;
326 foreach ($subFolders as $subFolder) {
327 $subFolderCounter++;
328 // Reserve space.
329 $this->tree[] = array();
330 // Get the key for this space
331 end($this->tree);
332 $treeKey = key($this->tree);
333 $specUID = \TYPO3\CMS\Core\Utility\GeneralUtility::md5int($subFolder->getCombinedIdentifier());
334 $this->specUIDmap[$specUID] = $subFolder->getCombinedIdentifier();
335 $row = array(
336 'uid' => $specUID,
337 'path' => $subFolder->getCombinedIdentifier(),
338 'title' => $subFolder->getName(),
339 'folder' => $subFolder
340 );
341 // Make a recursive call to the next level
342 if ($depth > 1 && $this->expandNext($specUID)) {
343 $nextCount = $this->getFolderTree($subFolder, $depth - 1, $type);
344 // Set "did expand" flag
345 $isOpen = 1;
346 } else {
347 $nextCount = $this->getNumberOfSubfolders($subFolder);
348 // Clear "did expand" flag
349 $isOpen = 0;
350 }
351 // Set HTML-icons, if any:
352 if ($this->makeHTML) {
353 $HTML = $this->PMicon($subFolder, $subFolderCounter, $totalSubFolders, $nextCount, $isOpen);
354 if ($subFolder->checkActionPermission('write')) {
355 $type = '';
356 $overlays = array();
357 } else {
358 $type = 'readonly';
359 $overlays = array('status-overlay-locked' => array());
360 }
361 if ($isOpen) {
362 $icon = 'apps-filetree-folder-opened';
363 } else {
364 $icon = 'apps-filetree-folder-default';
365 }
366 if ($subFolder->getIdentifier() == '_temp_') {
367 $icon = 'apps-filetree-folder-temp';
368 $row['title'] = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_file_list.xml:temp', TRUE);
369 $row['_title'] = '<strong>' . $row['title'] . '</strong>';
370 }
371 if ($subFolder->getIdentifier() == '_recycler_') {
372 $icon = 'apps-filetree-folder-recycler';
373 $row['title'] = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_file_list.xml:recycler', TRUE);
374 $row['_title'] = '<strong>' . $row['title'] . '</strong>';
375 }
376 $icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon($icon, array('title' => $subFolder->getIdentifier()), $overlays);
377 $HTML .= $this->wrapIcon($icon, $subFolder);
378 }
379 // Finally, add the row/HTML content to the ->tree array in the reserved key.
380 $this->tree[$treeKey] = array(
381 'row' => $row,
382 'HTML' => $HTML,
383 'hasSub' => $nextCount && $this->expandNext($specUID),
384 'isFirst' => $subFolderCounter == 1,
385 'isLast' => FALSE,
386 'invertedDepth' => $depth,
387 'bank' => $this->bank
388 );
389 }
390 if ($subFolderCounter > 0) {
391 $this->tree[$treeKey]['isLast'] = TRUE;
392 }
393 return $totalSubFolders;
394 }
395
396 /**
397 * Compiles the HTML code for displaying the structure found inside the ->tree array
398 *
399 * @param array|string $treeItems "tree-array" - if blank string, the internal ->tree array is used.
400 * @return string The HTML code for the tree
401 */
402 public function printTree($treeItems = '') {
403 $doExpand = FALSE;
404 $doCollapse = FALSE;
405 $ajaxOutput = '';
406 $titleLength = intval($this->BE_USER->uc['titleLen']);
407 if (!is_array($treeItems)) {
408 $treeItems = $this->tree;
409 }
410 $out = '
411 <!-- TYPO3 folder tree structure. -->
412 <ul class="tree" id="treeRoot">
413 ';
414 // Evaluate AJAX request
415 if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
416 list(, $expandCollapseCommand, $expandedFolderHash, ) = $this->evaluateExpandCollapseParameter();
417 if ($expandCollapseCommand == 1) {
418 // We don't know yet. Will be set later.
419 $invertedDepthOfAjaxRequestedItem = 0;
420 $doExpand = TRUE;
421 } else {
422 $doCollapse = TRUE;
423 }
424 }
425 // We need to count the opened <ul>'s every time we dig into another level,
426 // so we know how many we have to close when all children are done rendering
427 $closeDepth = array();
428 foreach ($treeItems as $treeItem) {
429 /** @var $folderObject \TYPO3\CMS\Core\Resource\Folder */
430 $folderObject = $treeItem['row']['folder'];
431 $classAttr = $treeItem['row']['_CSSCLASS'];
432 $folderIdentifier = $folderObject->getCombinedIdentifier();
433 // this is set if the AJAX request has just opened this folder (via the PM command)
434 $isExpandedFolderIdentifier = $expandedFolderHash == \TYPO3\CMS\Core\Utility\GeneralUtility::md5int($folderIdentifier);
435 $idAttr = htmlspecialchars($this->domIdPrefix . $this->getId($folderObject) . '_' . $treeItem['bank']);
436 $itemHTML = '';
437 // If this item is the start of a new level,
438 // then a new level <ul> is needed, but not in ajax mode
439 if ($treeItem['isFirst'] && !$doCollapse && !($doExpand && $isExpandedFolderIdentifier)) {
440 $itemHTML = '<ul>
441 ';
442 }
443 // Add CSS classes to the list item
444 if ($treeItem['hasSub']) {
445 $classAttr .= ' expanded';
446 }
447 if ($treeItem['isLast']) {
448 $classAttr .= ' last';
449 }
450 $itemHTML .= '
451 <li id="' . $idAttr . '" ' . ($classAttr ? ' class="' . trim($classAttr) . '"' : '') . '><div class="treeLinkItem">' . $treeItem['HTML'] . $this->wrapTitle($this->getTitleStr($treeItem['row'], $titleLength), $folderObject, $treeItem['bank']) . '</div>';
452 if (!$treeItem['hasSub']) {
453 $itemHTML .= '</li>
454 ';
455 }
456 // We have to remember if this is the last one
457 // on level X so the last child on level X+1 closes the <ul>-tag
458 if ($treeItem['isLast'] && !($doExpand && $isExpandedFolderIdentifier)) {
459 $closeDepth[$treeItem['invertedDepth']] = 1;
460 }
461 // If this is the last one and does not have subitems, we need to close
462 // the tree as long as the upper levels have last items too
463 if ($treeItem['isLast'] && !$treeItem['hasSub'] && !$doCollapse && !($doExpand && $isExpandedFolderIdentifier)) {
464 for ($i = $treeItem['invertedDepth']; $closeDepth[$i] == 1; $i++) {
465 $closeDepth[$i] = 0;
466 $itemHTML .= '</ul></li>
467 ';
468 }
469 }
470 // Ajax request: collapse
471 if ($doCollapse && $isExpandedFolderIdentifier) {
472 $this->ajaxStatus = TRUE;
473 return $itemHTML;
474 }
475 // Ajax request: expand
476 if ($doExpand && $isExpandedFolderIdentifier) {
477 $ajaxOutput .= $itemHTML;
478 $invertedDepthOfAjaxRequestedItem = $treeItem['invertedDepth'];
479 } elseif ($invertedDepthOfAjaxRequestedItem) {
480 if ($treeItem['invertedDepth'] < $invertedDepthOfAjaxRequestedItem) {
481 $ajaxOutput .= $itemHTML;
482 } else {
483 $this->ajaxStatus = TRUE;
484 return $ajaxOutput;
485 }
486 }
487 $out .= $itemHTML;
488 }
489 // If this is a AJAX request, output directly
490 if ($ajaxOutput) {
491 $this->ajaxStatus = TRUE;
492 return $ajaxOutput;
493 }
494 // Finally close the first ul
495 $out .= '</ul>
496 ';
497 return $out;
498 }
499
500 /**
501 * Counts the number of directories in a file path.
502 *
503 * @param string $file File path.
504 * @return integer
505 * @deprecated since TYPO3 6.0, as the folder objects do the counting automatically
506 */
507 public function getCount($file) {
508 \TYPO3\CMS\Core\Utility\GeneralUtility::logDeprecatedFunction();
509 // This generates the directory tree
510 $dirs = \TYPO3\CMS\Core\Utility\GeneralUtility::get_dirs($file);
511 $c = 0;
512 if (is_array($dirs)) {
513 $c = count($dirs);
514 }
515 return $c;
516 }
517
518 /**
519 * Counts the number of directories in a file path.
520 *
521 * @param \TYPO3\CMS\Core\Resource\Folder $folderObject File path.
522 * @return integer
523 */
524 public function getNumberOfSubfolders(\TYPO3\CMS\Core\Resource\Folder $folderObject) {
525 $subFolders = $folderObject->getSubfolders();
526 return count($subFolders);
527 }
528
529 /**
530 * Get stored tree structure AND updating it if needed according to incoming PM GET var.
531 *
532 * @return void
533 * @access private
534 * @todo Define visibility
535 */
536 public function initializePositionSaving() {
537 // Get stored tree structure:
538 $this->stored = unserialize($this->BE_USER->uc['browseTrees'][$this->treeName]);
539 $this->getShortHashNumberForStorage();
540 // PM action:
541 // (If an plus/minus icon has been clicked,
542 // the PM GET var is sent and we must update the stored positions in the tree):
543 // 0: mount key, 1: set/clear boolean, 2: item ID (cannot contain "_"), 3: treeName
544 list($storageHashNumber, $doExpand, $numericFolderHash, $treeName) = $this->evaluateExpandCollapseParameter();
545 if ($treeName && $treeName == $this->treeName) {
546 if (in_array($storageHashNumber, $this->storageHashNumbers)) {
547 if ($doExpand == 1) {
548 // Set
549 $this->stored[$storageHashNumber][$numericFolderHash] = 1;
550 } else {
551 // Clear
552 unset($this->stored[$storageHashNumber][$numericFolderHash]);
553 }
554 $this->savePosition();
555 }
556 }
557 }
558
559 /**
560 * Helper method to map md5-hash to shorter number
561 *
562 * @param \TYPO3\CMS\Core\Resource\ResourceStorage $storageObject
563 * @param \TYPO3\CMS\Core\Resource\Folder $startingPointFolder
564 * @return integer
565 */
566 protected function getShortHashNumberForStorage(\TYPO3\CMS\Core\Resource\ResourceStorage $storageObject = NULL, \TYPO3\CMS\Core\Resource\Folder $startingPointFolder = NULL) {
567 if (!$this->storageHashNumbers) {
568 $this->storageHashNumbers = array();
569 // Mapping md5-hash to shorter number:
570 $hashMap = array();
571 foreach ($this->storages as $storageUid => $storage) {
572 $fileMounts = $storage->getFileMounts();
573 if (count($fileMounts)) {
574 foreach ($fileMounts as $fileMount) {
575 $nkey = hexdec(substr(\TYPO3\CMS\Core\Utility\GeneralUtility::md5int($fileMount['folder']->getCombinedIdentifier()), 0, 4));
576 $this->storageHashNumbers[$storageUid . $fileMount['folder']->getCombinedIdentifier()] = $nkey;
577 }
578 } else {
579 $folder = $storage->getRootLevelFolder();
580 $nkey = hexdec(substr(\TYPO3\CMS\Core\Utility\GeneralUtility::md5int($folder->getCombinedIdentifier()), 0, 4));
581 $this->storageHashNumbers[$storageUid . $folder->getCombinedIdentifier()] = $nkey;
582 }
583 }
584 }
585 if ($storageObject) {
586 if ($startingPointFolder) {
587 return $this->storageHashNumbers[$storageObject->getUid() . $startingPointFolder->getCombinedIdentifier()];
588 } else {
589 return $this->storageHashNumbers[$storageObject->getUid()];
590 }
591 } else {
592 return NULL;
593 }
594 }
595
596 /**
597 * Gets the values from the Expand/Collapse Parameter (&PM)
598 * previously known as "PM" (plus/minus)
599 * PM action:
600 * (If an plus/minus icon has been clicked,
601 * the PM GET var is sent and we must update the stored positions in the tree):
602 * 0: mount key, 1: set/clear boolean, 2: item ID (cannot contain "_"), 3: treeName
603 *
604 * @param string $PM The "plus/minus" command
605 * @return array
606 */
607 protected function evaluateExpandCollapseParameter($PM = NULL) {
608 if ($PM === NULL) {
609 $PM = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('PM');
610 // IE takes anchor as parameter
611 if (($PMpos = strpos($PM, '#')) !== FALSE) {
612 $PM = substr($PM, 0, $PMpos);
613 }
614 }
615 // Take the first three parameters
616 list($mountKey, $doExpand, $folderIdentifier) = explode('_', $PM, 3);
617 // In case the folder identifier contains "_", we just need to get the fourth/last parameter
618 list($folderIdentifier, $treeName) = \TYPO3\CMS\Core\Utility\GeneralUtility::revExplode('_', $folderIdentifier, 2);
619 return array(
620 $mountKey,
621 $doExpand,
622 $folderIdentifier,
623 $treeName
624 );
625 }
626
627 /**
628 * Generates the "PM" string to sent to expand/collapse items
629 *
630 * @param string $mountKey The mount key / storage UID
631 * @param boolean $doExpand Whether to expand/collapse
632 * @param \TYPO3\CMS\Core\Resource\Folder $folderObject The folder object
633 * @param string $treeName The name of the tree
634 * @return string
635 */
636 protected function generateExpandCollapseParameter($mountKey = NULL, $doExpand = FALSE, \TYPO3\CMS\Core\Resource\Folder $folderObject = NULL, $treeName = NULL) {
637 $parts = array(
638 $mountKey !== NULL ? $mountKey : $this->bank,
639 $doExpand == 1 ? 1 : 0,
640 $folderObject !== NULL ? \TYPO3\CMS\Core\Utility\GeneralUtility::md5int($folderObject->getCombinedIdentifier()) : '',
641 $treeName !== NULL ? $treeName : $this->treeName
642 );
643 return implode('_', $parts);
644 }
645
646 /**
647 * Gets the AJAX status.
648 *
649 * @return boolean
650 */
651 public function getAjaxStatus() {
652 return $this->ajaxStatus;
653 }
654
655 }
656
657
658 ?>