| Total Complexity | 101 |
| Total Lines | 688 |
| Duplicated Lines | 3.63 % |
| Changes | 0 | ||
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like FolderTreeView often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use FolderTreeView, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 33 | class FolderTreeView extends AbstractTreeView |
||
| 34 | { |
||
| 35 | /** |
||
| 36 | * The users' file Storages |
||
| 37 | * |
||
| 38 | * @var ResourceStorage[] |
||
| 39 | */ |
||
| 40 | protected $storages = null; |
||
| 41 | |||
| 42 | /** |
||
| 43 | * @var array |
||
| 44 | */ |
||
| 45 | protected $storageHashNumbers; |
||
| 46 | |||
| 47 | /** |
||
| 48 | * Indicates, whether the AJAX call was successful, |
||
| 49 | * i.e. the requested page has been found |
||
| 50 | * |
||
| 51 | * @var bool |
||
| 52 | */ |
||
| 53 | protected $ajaxStatus = false; |
||
| 54 | |||
| 55 | /** |
||
| 56 | * @var array |
||
| 57 | */ |
||
| 58 | protected $scope; |
||
| 59 | |||
| 60 | /** |
||
| 61 | * @var IconFactory |
||
| 62 | */ |
||
| 63 | protected $iconFactory; |
||
| 64 | |||
| 65 | /** |
||
| 66 | * If file-drag mode is set, temp and recycler folders are filtered out. |
||
| 67 | * @var bool |
||
| 68 | */ |
||
| 69 | public $ext_noTempRecyclerDirs = false; |
||
| 70 | |||
| 71 | /** |
||
| 72 | * override to not use a title attribute |
||
| 73 | * @var string |
||
| 74 | */ |
||
| 75 | public $titleAttrib = ''; |
||
| 76 | |||
| 77 | /** |
||
| 78 | * override to use this treeName |
||
| 79 | * does not need to be set in __construct() |
||
| 80 | * @var string |
||
| 81 | */ |
||
| 82 | public $treeName = 'folder'; |
||
| 83 | |||
| 84 | /** |
||
| 85 | * override to use this domIdPrefix |
||
| 86 | * @var string |
||
| 87 | */ |
||
| 88 | public $domIdPrefix = 'folder'; |
||
| 89 | |||
| 90 | /** |
||
| 91 | * Constructor function of the class |
||
| 92 | */ |
||
| 93 | public function __construct() |
||
| 94 | { |
||
| 95 | parent::__construct(); |
||
| 96 | $this->init(); |
||
| 97 | $this->storages = $this->BE_USER->getFileStorages(); |
||
| 98 | $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class); |
||
| 99 | } |
||
| 100 | |||
| 101 | /** |
||
| 102 | * Generate the plus/minus icon for the browsable tree. |
||
| 103 | * |
||
| 104 | * @param Folder $folderObject Entry folder object |
||
| 105 | * @param int $subFolderCounter The current entry number |
||
| 106 | * @param int $totalSubFolders The total number of entries. If equal to $a, a "bottom" element is returned. |
||
| 107 | * @param int $nextCount The number of sub-elements to the current element. |
||
| 108 | * @param bool $isExpanded The element was expanded to render subelements if this flag is set. |
||
| 109 | * |
||
| 110 | * @return string Image tag with the plus/minus icon. |
||
| 111 | * @internal |
||
| 112 | * @see \TYPO3\CMS\Backend\Tree\View\PageTreeView::PMicon() |
||
| 113 | */ |
||
| 114 | public function PMicon($folderObject, $subFolderCounter, $totalSubFolders, $nextCount, $isExpanded) |
||
| 115 | { |
||
| 116 | $icon = ''; |
||
| 117 | if ($nextCount) { |
||
| 118 | $cmd = $this->generateExpandCollapseParameter($this->bank, !$isExpanded, $folderObject); |
||
| 119 | $icon = $this->PMiconATagWrap($icon, $cmd, !$isExpanded); |
||
| 120 | } |
||
| 121 | return $icon; |
||
| 122 | } |
||
| 123 | |||
| 124 | /** |
||
| 125 | * Wrap the plus/minus icon in a link |
||
| 126 | * |
||
| 127 | * @param string $icon HTML string to wrap, probably an image tag. |
||
| 128 | * @param string $cmd Command for 'PM' get var |
||
| 129 | * @param bool $isExpand Whether to be expanded |
||
| 130 | * @return string Link-wrapped input string |
||
| 131 | * @internal |
||
| 132 | */ |
||
| 133 | public function PMiconATagWrap($icon, $cmd, $isExpand = true) |
||
| 134 | { |
||
| 135 | View Code Duplication | if (empty($this->scope)) { |
|
| 136 | $this->scope = [ |
||
| 137 | 'class' => static::class, |
||
| 138 | 'script' => $this->thisScript, |
||
| 139 | 'ext_noTempRecyclerDirs' => $this->ext_noTempRecyclerDirs |
||
| 140 | ]; |
||
| 141 | } |
||
| 142 | |||
| 143 | if ($this->thisScript) { |
||
| 144 | // Activates dynamic AJAX based tree |
||
| 145 | $scopeData = serialize($this->scope); |
||
| 146 | $scopeHash = GeneralUtility::hmac($scopeData); |
||
| 147 | $js = htmlspecialchars('Tree.load(' . GeneralUtility::quoteJSvalue($cmd) . ', ' . (int)$isExpand . ', this, ' . GeneralUtility::quoteJSvalue($scopeData) . ', ' . GeneralUtility::quoteJSvalue($scopeHash) . ');'); |
||
| 148 | return '<a class="list-tree-control' . (!$isExpand ? ' list-tree-control-open' : ' list-tree-control-closed') . '" onclick="' . $js . '"><i class="fa"></i></a>'; |
||
| 149 | } |
||
| 150 | return $icon; |
||
| 151 | } |
||
| 152 | |||
| 153 | /** |
||
| 154 | * @param string $cmd |
||
| 155 | * @param bool $isOpen |
||
| 156 | * @return string |
||
| 157 | */ |
||
| 158 | protected function renderPMIconAndLink($cmd, $isOpen) |
||
| 159 | { |
||
| 160 | $link = $this->thisScript ? ' href="' . htmlspecialchars($this->getThisScript() . 'PM=' . $cmd) . '"' : ''; |
||
| 161 | return '<a class="list-tree-control list-tree-control-' . ($isOpen ? 'open' : 'closed') . '"' . $link . '><i class="fa"></i></a>'; |
||
| 162 | } |
||
| 163 | |||
| 164 | /** |
||
| 165 | * Wrapping the folder icon |
||
| 166 | * |
||
| 167 | * @param string $icon The image tag for the icon |
||
| 168 | * @param Folder $folderObject The row for the current element |
||
| 169 | * |
||
| 170 | * @return string The processed icon input value. |
||
| 171 | * @internal |
||
| 172 | */ |
||
| 173 | public function wrapIcon($icon, $folderObject) |
||
| 174 | { |
||
| 175 | // Add title attribute to input icon tag |
||
| 176 | $theFolderIcon = ''; |
||
| 177 | // Wrap icon in click-menu link. |
||
| 178 | if (!$this->ext_IconMode) { |
||
| 179 | // Check storage access to wrap with click menu |
||
| 180 | if (!$folderObject instanceof InaccessibleFolder) { |
||
| 181 | $tableName = $this->getTableNameForClickMenu($folderObject); |
||
| 182 | $theFolderIcon = BackendUtility::wrapClickMenuOnIcon($icon, $tableName, $folderObject->getCombinedIdentifier(), 'tree'); |
||
| 183 | } |
||
| 184 | View Code Duplication | } elseif ($this->ext_IconMode === 'titlelink') { |
|
| 185 | $aOnClick = 'return jumpTo(' . GeneralUtility::quoteJSvalue($this->getJumpToParam($folderObject)) . ',this,' . GeneralUtility::quoteJSvalue($this->domIdPrefix . $this->getId($folderObject)) . ',' . $this->bank . ');'; |
||
| 186 | $theFolderIcon = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . $icon . '</a>'; |
||
| 187 | } |
||
| 188 | return $theFolderIcon; |
||
| 189 | } |
||
| 190 | |||
| 191 | /** |
||
| 192 | * Wrapping $title in a-tags. |
||
| 193 | * |
||
| 194 | * @param string $title Title string |
||
| 195 | * @param Folder $folderObject the folder record |
||
| 196 | * @param int $bank Bank pointer (which mount point number) |
||
| 197 | * |
||
| 198 | * @return string |
||
| 199 | * @internal |
||
| 200 | */ |
||
| 201 | public function wrapTitle($title, $folderObject, $bank = 0) |
||
| 212 | } |
||
| 213 | |||
| 214 | /** |
||
| 215 | * Returns the id from the record - for folders, this is an md5 hash. |
||
| 216 | * |
||
| 217 | * @param Folder $folderObject The folder object |
||
| 218 | * |
||
| 219 | * @return int The "uid" field value. |
||
| 220 | */ |
||
| 221 | public function getId($folderObject) |
||
| 222 | { |
||
| 223 | return GeneralUtility::md5int($folderObject->getCombinedIdentifier()); |
||
| 224 | } |
||
| 225 | |||
| 226 | /** |
||
| 227 | * Returns jump-url parameter value. |
||
| 228 | * |
||
| 229 | * @param Folder $folderObject The folder object |
||
| 230 | * |
||
| 231 | * @return string The jump-url parameter. |
||
| 232 | */ |
||
| 233 | public function getJumpToParam($folderObject) |
||
| 234 | { |
||
| 235 | return rawurlencode($folderObject->getCombinedIdentifier()); |
||
| 236 | } |
||
| 237 | |||
| 238 | /** |
||
| 239 | * Returns the title for the input record. If blank, a "no title" label (localized) will be returned. |
||
| 240 | * '_title' is used for setting an alternative title for folders. |
||
| 241 | * |
||
| 242 | * @param array $row The input row array (where the key "_title" is used for the title) |
||
| 243 | * @param int $titleLen Title length (30) |
||
| 244 | * @return string The title |
||
| 245 | */ |
||
| 246 | public function getTitleStr($row, $titleLen = 30) |
||
| 247 | { |
||
| 248 | return $row['_title'] ?? parent::getTitleStr($row, $titleLen); |
||
| 249 | } |
||
| 250 | |||
| 251 | /** |
||
| 252 | * Returns the value for the image "title" attribute |
||
| 253 | * |
||
| 254 | * @param Folder $folderObject The folder to be used |
||
| 255 | * |
||
| 256 | * @return string The attribute value (is htmlspecialchared() already) |
||
| 257 | */ |
||
| 258 | public function getTitleAttrib($folderObject) |
||
| 259 | { |
||
| 260 | return htmlspecialchars($folderObject->getName()); |
||
| 261 | } |
||
| 262 | |||
| 263 | /** |
||
| 264 | * Will create and return the HTML code for a browsable tree of folders. |
||
| 265 | * Is based on the mounts found in the internal array ->MOUNTS (set in the constructor) |
||
| 266 | * |
||
| 267 | * @return string HTML code for the browsable tree |
||
| 268 | */ |
||
| 269 | public function getBrowsableTree() |
||
| 270 | { |
||
| 271 | // Get stored tree structure AND updating it if needed according to incoming PM GET var. |
||
| 272 | $this->initializePositionSaving(); |
||
| 273 | // Init done: |
||
| 274 | $treeItems = []; |
||
| 275 | // Traverse mounts: |
||
| 276 | foreach ($this->storages as $storageObject) { |
||
| 277 | $this->getBrowseableTreeForStorage($storageObject); |
||
| 278 | // Add tree: |
||
| 279 | $treeItems = array_merge($treeItems, $this->tree); |
||
| 280 | } |
||
| 281 | return $this->printTree($treeItems); |
||
| 282 | } |
||
| 283 | |||
| 284 | /** |
||
| 285 | * Get a tree for one storage |
||
| 286 | * |
||
| 287 | * @param ResourceStorage $storageObject |
||
| 288 | */ |
||
| 289 | public function getBrowseableTreeForStorage(ResourceStorage $storageObject) |
||
| 290 | { |
||
| 291 | // If there are filemounts, show each, otherwise just the rootlevel folder |
||
| 292 | $fileMounts = $storageObject->getFileMounts(); |
||
| 293 | $rootLevelFolders = []; |
||
| 294 | if (!empty($fileMounts)) { |
||
| 295 | foreach ($fileMounts as $fileMountInfo) { |
||
| 296 | $rootLevelFolders[] = [ |
||
| 297 | 'folder' => $fileMountInfo['folder'], |
||
| 298 | 'name' => $fileMountInfo['title'] |
||
| 299 | ]; |
||
| 300 | } |
||
| 301 | } elseif ($this->BE_USER->isAdmin()) { |
||
| 302 | $rootLevelFolders[] = [ |
||
| 303 | 'folder' => $storageObject->getRootLevelFolder(), |
||
| 304 | 'name' => $storageObject->getName() |
||
| 305 | ]; |
||
| 306 | } |
||
| 307 | // Clean the tree |
||
| 308 | $this->reset(); |
||
| 309 | // Go through all "root level folders" of this tree (can be the rootlevel folder or any file mount points) |
||
| 310 | foreach ($rootLevelFolders as $rootLevelFolderInfo) { |
||
| 311 | /** @var $rootLevelFolder Folder */ |
||
| 312 | $rootLevelFolder = $rootLevelFolderInfo['folder']; |
||
| 313 | $rootLevelFolderName = $rootLevelFolderInfo['name']; |
||
| 314 | $folderHashSpecUID = GeneralUtility::md5int($rootLevelFolder->getCombinedIdentifier()); |
||
| 315 | $this->specUIDmap[$folderHashSpecUID] = $rootLevelFolder->getCombinedIdentifier(); |
||
| 316 | // Hash key |
||
| 317 | $storageHashNumber = $this->getShortHashNumberForStorage($storageObject, $rootLevelFolder); |
||
| 318 | // Set first: |
||
| 319 | $this->bank = $storageHashNumber; |
||
| 320 | $isOpen = $this->stored[$storageHashNumber][$folderHashSpecUID] || $this->expandFirst; |
||
| 321 | // Set PM icon: |
||
| 322 | $cmd = $this->generateExpandCollapseParameter($this->bank, !$isOpen, $rootLevelFolder); |
||
| 323 | // Only show and link icon if storage is browseable |
||
| 324 | if (!$storageObject->isBrowsable() || $this->getNumberOfSubfolders($rootLevelFolder) === 0) { |
||
| 325 | $firstHtml = ''; |
||
| 326 | } else { |
||
| 327 | $firstHtml = $this->renderPMIconAndLink($cmd, $isOpen); |
||
| 328 | } |
||
| 329 | // Mark a storage which is not online, as offline |
||
| 330 | // maybe someday there will be a special icon for this |
||
| 331 | if ($storageObject->isOnline() === false) { |
||
| 332 | $rootLevelFolderName .= ' (' . $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_file.xlf:sys_file_storage.isOffline') . ')'; |
||
| 333 | } |
||
| 334 | // Preparing rootRec for the mount |
||
| 335 | $icon = $this->iconFactory->getIconForResource($rootLevelFolder, Icon::SIZE_SMALL, null, ['mount-root' => true]); |
||
| 336 | $firstHtml .= $this->wrapIcon($icon, $rootLevelFolder); |
||
| 337 | $row = [ |
||
| 338 | 'uid' => $folderHashSpecUID, |
||
| 339 | 'title' => $rootLevelFolderName, |
||
| 340 | 'path' => $rootLevelFolder->getCombinedIdentifier(), |
||
| 341 | 'folder' => $rootLevelFolder |
||
| 342 | ]; |
||
| 343 | // Add the storage root to ->tree |
||
| 344 | $this->tree[] = [ |
||
| 345 | 'HTML' => $firstHtml, |
||
| 346 | 'row' => $row, |
||
| 347 | 'bank' => $this->bank, |
||
| 348 | // hasSub is TRUE when the root of the storage is expanded |
||
| 349 | 'hasSub' => $isOpen && $storageObject->isBrowsable(), |
||
| 350 | 'invertedDepth' => 1000, |
||
| 351 | ]; |
||
| 352 | // If the mount is expanded, go down: |
||
| 353 | if ($isOpen && $storageObject->isBrowsable()) { |
||
| 354 | // Set depth: |
||
| 355 | $this->getFolderTree($rootLevelFolder, 999); |
||
| 356 | } |
||
| 357 | } |
||
| 358 | } |
||
| 359 | |||
| 360 | /** |
||
| 361 | * Fetches the data for the tree |
||
| 362 | * |
||
| 363 | * @param Folder $folderObject the folderobject |
||
| 364 | * @param int $depth Max depth (recursivity limit) |
||
| 365 | * @param string $type HTML-code prefix for recursive calls. |
||
| 366 | * |
||
| 367 | * @return int The count of items on the level |
||
| 368 | * @see getBrowsableTree() |
||
| 369 | */ |
||
| 370 | public function getFolderTree(Folder $folderObject, $depth = 999, $type = '') |
||
| 371 | { |
||
| 372 | $depth = (int)$depth; |
||
| 373 | |||
| 374 | // This generates the directory tree |
||
| 375 | /* array of \TYPO3\CMS\Core\Resource\Folder */ |
||
| 376 | if ($folderObject instanceof InaccessibleFolder) { |
||
| 377 | $subFolders = []; |
||
| 378 | } else { |
||
| 379 | $subFolders = $folderObject->getSubfolders(); |
||
| 380 | $subFolders = \TYPO3\CMS\Core\Resource\Utility\ListUtility::resolveSpecialFolderNames($subFolders); |
||
| 381 | uksort($subFolders, 'strnatcasecmp'); |
||
| 382 | } |
||
| 383 | |||
| 384 | $totalSubFolders = count($subFolders); |
||
| 385 | $HTML = ''; |
||
| 386 | $subFolderCounter = 0; |
||
| 387 | $treeKey = ''; |
||
| 388 | /** @var Folder $subFolder */ |
||
| 389 | foreach ($subFolders as $subFolderName => $subFolder) { |
||
| 390 | $subFolderCounter++; |
||
| 391 | // Reserve space. |
||
| 392 | $this->tree[] = []; |
||
| 393 | // Get the key for this space |
||
| 394 | end($this->tree); |
||
| 395 | $isLocked = $subFolder instanceof InaccessibleFolder; |
||
| 396 | $treeKey = key($this->tree); |
||
| 397 | $specUID = GeneralUtility::md5int($subFolder->getCombinedIdentifier()); |
||
| 398 | $this->specUIDmap[$specUID] = $subFolder->getCombinedIdentifier(); |
||
| 399 | $row = [ |
||
| 400 | 'uid' => $specUID, |
||
| 401 | 'path' => $subFolder->getCombinedIdentifier(), |
||
| 402 | 'title' => $subFolderName, |
||
| 403 | 'folder' => $subFolder |
||
| 404 | ]; |
||
| 405 | // Make a recursive call to the next level |
||
| 406 | if (!$isLocked && $depth > 1 && $this->expandNext($specUID)) { |
||
| 407 | $nextCount = $this->getFolderTree($subFolder, $depth - 1, $type); |
||
| 408 | // Set "did expand" flag |
||
| 409 | $isOpen = 1; |
||
| 410 | } else { |
||
| 411 | $nextCount = $isLocked ? 0 : $this->getNumberOfSubfolders($subFolder); |
||
| 412 | // Clear "did expand" flag |
||
| 413 | $isOpen = 0; |
||
| 414 | } |
||
| 415 | // Set HTML-icons, if any: |
||
| 416 | if ($this->makeHTML) { |
||
| 417 | $HTML = $this->PMicon($subFolder, $subFolderCounter, $totalSubFolders, $nextCount, $isOpen); |
||
| 418 | $type = ''; |
||
| 419 | |||
| 420 | $role = $subFolder->getRole(); |
||
| 421 | if ($role !== FolderInterface::ROLE_DEFAULT) { |
||
| 422 | $row['_title'] = '<strong>' . $subFolderName . '</strong>'; |
||
| 423 | } |
||
| 424 | $icon = '<span title="' . htmlspecialchars($subFolderName) . '">' |
||
| 425 | . $this->iconFactory->getIconForResource($subFolder, Icon::SIZE_SMALL, null, ['folder-open' => (bool)$isOpen]) |
||
| 426 | . '</span>'; |
||
| 427 | $HTML .= $this->wrapIcon($icon, $subFolder); |
||
| 428 | } |
||
| 429 | // Finally, add the row/HTML content to the ->tree array in the reserved key. |
||
| 430 | $this->tree[$treeKey] = [ |
||
| 431 | 'row' => $row, |
||
| 432 | 'HTML' => $HTML, |
||
| 433 | 'hasSub' => $nextCount && $this->expandNext($specUID), |
||
| 434 | 'isFirst' => $subFolderCounter == 1, |
||
| 435 | 'isLast' => false, |
||
| 436 | 'invertedDepth' => $depth, |
||
| 437 | 'bank' => $this->bank |
||
| 438 | ]; |
||
| 439 | } |
||
| 440 | if ($subFolderCounter > 0) { |
||
| 441 | $this->tree[$treeKey]['isLast'] = true; |
||
| 442 | } |
||
| 443 | return $totalSubFolders; |
||
| 444 | } |
||
| 445 | |||
| 446 | /** |
||
| 447 | * Compiles the HTML code for displaying the structure found inside the ->tree array |
||
| 448 | * |
||
| 449 | * @param array|string $treeItems "tree-array" - if blank string, the internal ->tree array is used. |
||
| 450 | * @return string The HTML code for the tree |
||
| 451 | */ |
||
| 452 | public function printTree($treeItems = '') |
||
| 555 | } |
||
| 556 | |||
| 557 | /** |
||
| 558 | * Returns table name for click menu |
||
| 559 | * |
||
| 560 | * @param Folder $folderObject |
||
| 561 | * @return string |
||
| 562 | */ |
||
| 563 | protected function getTableNameForClickMenu(Folder $folderObject) |
||
| 564 | { |
||
| 565 | if (strpos($folderObject->getRole(), FolderInterface::ROLE_MOUNT) !== false) { |
||
| 566 | $tableName = 'sys_filemounts'; |
||
| 567 | } elseif ($folderObject->getIdentifier() === $folderObject->getStorage()->getRootLevelFolder()->getIdentifier()) { |
||
| 568 | $tableName = 'sys_file_storage'; |
||
| 569 | } else { |
||
| 570 | $tableName = 'sys_file'; |
||
| 571 | } |
||
| 572 | return $tableName; |
||
| 573 | } |
||
| 574 | |||
| 575 | /** |
||
| 576 | * Counts the number of directories in a file path. |
||
| 577 | * |
||
| 578 | * @param Folder $folderObject File path. |
||
| 579 | * |
||
| 580 | * @return int |
||
| 581 | */ |
||
| 582 | public function getNumberOfSubfolders(Folder $folderObject) |
||
| 583 | { |
||
| 584 | $subFolders = $folderObject->getSubfolders(); |
||
| 585 | return count($subFolders); |
||
| 586 | } |
||
| 587 | |||
| 588 | /** |
||
| 589 | * Get stored tree structure AND updating it if needed according to incoming PM GET var. |
||
| 590 | * |
||
| 591 | * @access private |
||
| 592 | */ |
||
| 593 | public function initializePositionSaving() |
||
| 594 | { |
||
| 595 | // Get stored tree structure: |
||
| 596 | $this->stored = unserialize($this->BE_USER->uc['browseTrees'][$this->treeName]); |
||
| 597 | $this->getShortHashNumberForStorage(); |
||
| 598 | // PM action: |
||
| 599 | // (If an plus/minus icon has been clicked, |
||
| 600 | // the PM GET var is sent and we must update the stored positions in the tree): |
||
| 601 | // 0: mount key, 1: set/clear boolean, 2: item ID (cannot contain "_"), 3: treeName |
||
| 602 | list($storageHashNumber, $doExpand, $numericFolderHash, $treeName) = $this->evaluateExpandCollapseParameter(); |
||
| 603 | if ($treeName && $treeName == $this->treeName) { |
||
| 604 | if (in_array($storageHashNumber, $this->storageHashNumbers)) { |
||
| 605 | if ($doExpand == 1) { |
||
| 606 | // Set |
||
| 607 | $this->stored[$storageHashNumber][$numericFolderHash] = 1; |
||
| 608 | } else { |
||
| 609 | // Clear |
||
| 610 | unset($this->stored[$storageHashNumber][$numericFolderHash]); |
||
| 611 | } |
||
| 612 | $this->savePosition(); |
||
| 613 | } |
||
| 614 | } |
||
| 615 | } |
||
| 616 | |||
| 617 | /** |
||
| 618 | * Helper method to map md5-hash to shorter number |
||
| 619 | * |
||
| 620 | * @param ResourceStorage $storageObject |
||
| 621 | * @param Folder $startingPointFolder |
||
| 622 | * |
||
| 623 | * @return int |
||
| 624 | */ |
||
| 625 | protected function getShortHashNumberForStorage(ResourceStorage $storageObject = null, Folder $startingPointFolder = null) |
||
| 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 | { |
||
| 665 | if ($PM === null) { |
||
| 666 | $PM = GeneralUtility::_GP('PM'); |
||
| 667 | // IE takes anchor as parameter |
||
| 668 | View Code Duplication | if (($PMpos = strpos($PM, '#')) !== false) { |
|
| 669 | $PM = substr($PM, 0, $PMpos); |
||
| 670 | } |
||
| 671 | } |
||
| 672 | // Take the first three parameters |
||
| 673 | list($mountKey, $doExpand, $folderIdentifier) = array_pad(explode('_', $PM, 3), 3, null); |
||
| 674 | // In case the folder identifier contains "_", we just need to get the fourth/last parameter |
||
| 675 | list($folderIdentifier, $treeName) = array_pad(GeneralUtility::revExplode('_', $folderIdentifier, 2), 2, null); |
||
| 676 | return [ |
||
| 677 | $mountKey, |
||
| 678 | $doExpand, |
||
| 679 | $folderIdentifier, |
||
| 680 | $treeName |
||
| 681 | ]; |
||
| 682 | } |
||
| 683 | |||
| 684 | /** |
||
| 685 | * Generates the "PM" string to sent to expand/collapse items |
||
| 686 | * |
||
| 687 | * @param string $mountKey The mount key / storage UID |
||
| 688 | * @param bool $doExpand Whether to expand/collapse |
||
| 689 | * @param Folder $folderObject The folder object |
||
| 690 | * @param string $treeName The name of the tree |
||
| 691 | * |
||
| 692 | * @return string |
||
| 693 | */ |
||
| 694 | protected function generateExpandCollapseParameter($mountKey = null, $doExpand = false, Folder $folderObject = null, $treeName = null) |
||
| 695 | { |
||
| 696 | $parts = [ |
||
| 697 | $mountKey !== null ? $mountKey : $this->bank, |
||
| 698 | $doExpand == 1 ? 1 : 0, |
||
| 699 | $folderObject !== null ? GeneralUtility::md5int($folderObject->getCombinedIdentifier()) : '', |
||
| 700 | $treeName !== null ? $treeName : $this->treeName |
||
| 701 | ]; |
||
| 702 | return implode('_', $parts); |
||
| 703 | } |
||
| 704 | |||
| 705 | /** |
||
| 706 | * Gets the AJAX status. |
||
| 707 | * |
||
| 708 | * @return bool |
||
| 709 | */ |
||
| 710 | public function getAjaxStatus() |
||
| 711 | { |
||
| 712 | return $this->ajaxStatus; |
||
| 713 | } |
||
| 714 | |||
| 715 | /** |
||
| 716 | * @return LanguageService |
||
| 717 | */ |
||
| 718 | protected function getLanguageService() |
||
| 721 | } |
||
| 722 | } |
||
| 723 |