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