‪TYPO3CMS  9.5
PageTreeView.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
22 
28 {
32  public ‪$ext_showPageId = false;
33 
39  public ‪$ajaxStatus = false;
40 
44  public function ‪__construct()
45  {
46  parent::__construct();
47  $this->‪init();
48  }
49 
57  public function ‪wrapIcon($thePageIcon, $row)
58  {
60  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
61  // If the record is locked, present a warning sign.
62  if ($lockInfo = ‪BackendUtility::isRecordLocked('pages', $row['uid'])) {
63  $aOnClick = 'alert(' . GeneralUtility::quoteJSvalue($lockInfo['msg']) . ');return false;';
64  $lockIcon = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">'
65  . '<span title="' . htmlspecialchars($lockInfo['msg']) . '">' . $iconFactory->getIcon('warning-in-use', ‪Icon::SIZE_SMALL)->render() . '</span></a>';
66  } else {
67  $lockIcon = '';
68  }
69  // Wrap icon in click-menu link.
70  if (!$this->ext_IconMode) {
71  $thePageIcon = ‪BackendUtility::wrapClickMenuOnIcon($thePageIcon, 'pages', $row['uid'], 'tree');
72  } elseif ($this->ext_IconMode === 'titlelink') {
73  $aOnClick = 'return jumpTo(' . GeneralUtility::quoteJSvalue($this->‪getJumpToParam($row)) . ',this,' . GeneralUtility::quoteJSvalue($this->treeName) . ');';
74  $thePageIcon = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . $thePageIcon . '</a>';
75  }
76  // Wrap icon in a drag/drop span.
77  $dragDropIcon = '<span class="list-tree-icon dragIcon" id="dragIconID_' . $row['uid'] . '">' . $thePageIcon . '</span> ';
78  // Add Page ID:
79  $pageIdStr = '';
80  if ($this->ext_showPageId) {
81  $pageIdStr = '<span class="dragId">[' . $row['uid'] . ']</span> ';
82  }
83  // Call stats information hook
84  $stat = '';
85  $_params = ['pages', $row['uid']];
86  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] ?? [] as $_funcRef) {
87  $stat .= GeneralUtility::callUserFunction($_funcRef, $_params, $this);
88  }
89  return $dragDropIcon . $lockIcon . $pageIdStr . $stat;
90  }
91 
101  public function ‪wrapTitle(‪$title, $row, ‪$bank = 0)
102  {
103  // Hook for overriding the page title
104 
105  $_params = ['title' => &‪$title, 'row' => &$row];
106  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.webpagetree.php']['pageTitleOverlay'] ?? [] as $_funcRef) {
107  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
108  }
109 
110  $aOnClick = 'return jumpTo(' . GeneralUtility::quoteJSvalue($this->‪getJumpToParam($row)) . ',this,' . GeneralUtility::quoteJSvalue($this->domIdPrefix . $this->‪getId($row)) . ',' . ‪$bank . ');';
111  $clickMenuParts = ‪BackendUtility::wrapClickMenuOnIcon('', 'pages', $row['uid'], 'tree', '', '', true);
112 
113  $thePageTitle = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '" ' . GeneralUtility::implodeAttributes($clickMenuParts) . '>' . ‪$title . '</a>';
114  // Wrap title in a drag/drop span.
115  return '<span class="list-tree-title dragTitle" id="dragTitleID_' . $row['uid'] . '">' . $thePageTitle . '</span>';
116  }
117 
124  public function ‪printTree($treeArr = '')
125  {
126  $titleLen = (int)$this->BE_USER->uc['titleLen'];
127  if (!is_array($treeArr)) {
128  $treeArr = ‪$this->tree;
129  }
130  $out = '<ul class="list-tree list-tree-root">';
131  // -- evaluate AJAX request
132  // IE takes anchor as parameter
133  $PM = GeneralUtility::_GP('PM');
134  if (($PMpos = strpos($PM, '#')) !== false) {
135  $PM = substr($PM, 0, $PMpos);
136  }
137  $PM = explode('_', $PM);
138 
139  $doCollapse = false;
140  $doExpand = false;
141  $expandedPageUid = null;
142  $collapsedPageUid = null;
143  if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX && is_array($PM) && count($PM) === 4 && $PM[2] != 0) {
144  if ($PM[1]) {
145  $expandedPageUid = $PM[2];
146  $doExpand = true;
147  } else {
148  $collapsedPageUid = $PM[2];
149  $doCollapse = true;
150  }
151  }
152  // We need to count the opened <ul>'s every time we dig into another level,
153  // so we know how many we have to close when all children are done rendering
154  $closeDepth = [];
155  $ajaxOutput = '';
156  $invertedDepthOfAjaxRequestedItem = 0;
157  foreach ($treeArr as $k => $treeItem) {
158  $classAttr = $treeItem['row']['_CSSCLASS'];
159  $uid = $treeItem['row']['uid'];
160  $idAttr = htmlspecialchars($this->domIdPrefix . $this->‪getId($treeItem['row']) . '_' . $treeItem['bank']);
161  $itemHTML = '';
162  // If this item is the start of a new level,
163  // then a new level <ul> is needed, but not in ajax mode
164  if ($treeItem['isFirst'] && !$doCollapse && (!$doExpand || (int)$expandedPageUid !== (int)$uid)) {
165  $itemHTML = '<ul class="list-tree">';
166  }
167 
168  // Add CSS classes to the list item
169  if ($treeItem['hasSub']) {
170  $classAttr .= ' list-tree-control-open';
171  }
172  $itemHTML .= '<li id="' . $idAttr . '" ' . ($classAttr ? ' class="' . trim($classAttr) . '"' : '')
173  . '><span class="list-tree-group">' . $treeItem['HTML']
174  . $this->‪wrapTitle($this->‪getTitleStr($treeItem['row'], $titleLen), $treeItem['row'], $treeItem['bank']) . '</span>';
175  if (!$treeItem['hasSub']) {
176  $itemHTML .= '</li>';
177  }
178 
179  // We have to remember if this is the last one
180  // on level X so the last child on level X+1 closes the <ul>-tag
181  if ($treeItem['isLast'] && !($doExpand && $expandedPageUid == $uid)) {
182  $closeDepth[$treeItem['invertedDepth']] = 1;
183  }
184  // If this is the last one and does not have subitems, we need to close
185  // the tree as long as the upper levels have last items too
186  if ($treeItem['isLast'] && !$treeItem['hasSub'] && !$doCollapse && !($doExpand && $expandedPageUid == $uid)) {
187  for ($i = $treeItem['invertedDepth']; $closeDepth[$i] == 1; $i++) {
188  $closeDepth[$i] = 0;
189  $itemHTML .= '</ul></li>';
190  }
191  }
192  // Ajax request: collapse
193  if ($doCollapse && (int)$collapsedPageUid === (int)$uid) {
194  $this->ajaxStatus = true;
195  return $itemHTML;
196  }
197  // ajax request: expand
198  if ($doExpand && (int)$expandedPageUid === (int)$uid) {
199  $ajaxOutput .= $itemHTML;
200  $invertedDepthOfAjaxRequestedItem = $treeItem['invertedDepth'];
201  } elseif ($invertedDepthOfAjaxRequestedItem) {
202  if ($treeItem['invertedDepth'] < $invertedDepthOfAjaxRequestedItem) {
203  $ajaxOutput .= $itemHTML;
204  } else {
205  $this->ajaxStatus = true;
206  return $ajaxOutput;
207  }
208  }
209  $out .= $itemHTML;
210  }
211  if ($ajaxOutput) {
212  $this->ajaxStatus = true;
213  return $ajaxOutput;
214  }
215  // Finally close the first ul
216  $out .= '</ul>';
217  return $out;
218  }
219 
232  public function ‪PMicon($row, $a, $c, $nextCount, $exp)
233  {
234  $icon = '';
235  if ($nextCount) {
236  $cmd = $this->bank . '_' . ($exp ? '0_' : '1_') . $row['uid'] . '_' . $this->treeName;
237  $icon = $this->‪PMiconATagWrap($icon, $cmd, !$exp);
238  }
239  return $icon;
240  }
241 
251  public function ‪PMiconATagWrap($icon, $cmd, $isExpand = true)
252  {
253  if ($this->thisScript) {
254  // Activate dynamic ajax-based tree
255  $js = htmlspecialchars('Tree.load(' . GeneralUtility::quoteJSvalue($cmd) . ', ' . (int)$isExpand . ', this);');
256  return '<a class="list-tree-control' . (!$isExpand ? ' list-tree-control-open' : ' list-tree-control-closed') . '" onclick="' . $js . '"><i class="fa"></i></a>';
257  }
258  return $icon;
259  }
260 
267  public function ‪getBrowsableTree()
268  {
269  // Get stored tree structure AND updating it if needed according to incoming PM GET var.
271  // Init done:
272  $treeArr = [];
273  // Traverse mounts:
274  $firstHtml = '';
275  foreach ($this->MOUNTS as $idx => $uid) {
276  // Set first:
277  $this->bank = $idx;
278  $isOpen = $this->stored[$idx][$uid] || $this->expandFirst || $uid === '0';
279  // Save ids while resetting everything else.
280  $curIds = ‪$this->ids;
281  $this->‪reset();
282  $this->ids = $curIds;
283  // Only, if not for uid 0
284  if ($uid) {
285  // Set PM icon for root of mount:
286  $cmd = $this->bank . '_' . ($isOpen ? '0_' : '1_') . $uid . '_' . $this->treeName;
287  $firstHtml = '<a class="list-tree-control list-tree-control-' . ($isOpen ? 'open' : 'closed')
288  . '" href="' . htmlspecialchars($this->‪getThisScript() . 'PM=' . $cmd) . '"><i class="fa"></i></a>';
289  }
290  // Preparing rootRec for the mount
291  if ($uid) {
292  $rootRec = $this->‪getRecord($uid);
293  $firstHtml .= $this->‪getIcon($rootRec);
294  } else {
295  // Artificial record for the tree root, id=0
296  $rootRec = $this->‪getRootRecord();
297  $firstHtml .= $this->‪getRootIcon($rootRec);
298  }
299  if (is_array($rootRec)) {
300  // In case it was swapped inside getRecord due to workspaces.
301  $uid = $rootRec['uid'];
302  // Add the root of the mount to ->tree
303  $this->tree[] = ['HTML' => $firstHtml, 'row' => $rootRec, 'bank' => ‪$this->bank, 'hasSub' => true, 'invertedDepth' => 1000];
304  // If the mount is expanded, go down:
305  if ($isOpen) {
306  // Set depth:
307  if ($this->addSelfId) {
308  $this->ids[] = $uid;
309  }
310  $this->‪getTree($uid);
311  }
312  // Add tree:
313  $treeArr = array_merge($treeArr, $this->tree);
314  }
315  }
316  return $this->‪printTree($treeArr);
317  }
318 }
‪TYPO3\CMS\Core\Imaging\Icon\SIZE_SMALL
‪const SIZE_SMALL
Definition: Icon.php:29
‪TYPO3\CMS\Backend\View\PageTreeView\$ajaxStatus
‪bool $ajaxStatus
Definition: PageTreeView.php:37
‪TYPO3\CMS\Backend\View\PageTreeView\wrapTitle
‪string wrapTitle($title, $row, $bank=0)
Definition: PageTreeView.php:99
‪TYPO3\CMS\Backend\Tree\View\PageTreeView\PMicon
‪string PMicon($row, $a, $c, $nextCount, $isExpand)
Definition: PageTreeView.php:96
‪TYPO3\CMS\Core\Imaging\Icon
Definition: Icon.php:25
‪TYPO3\CMS\Backend\View
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\$title
‪string $title
Definition: AbstractTreeView.php:73
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\$ids
‪array $ids
Definition: AbstractTreeView.php:189
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:31
‪TYPO3\CMS\Backend\Tree\View\PageTreeView
Definition: PageTreeView.php:23
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\getBrowsableTree
‪string getBrowsableTree()
Definition: AbstractTreeView.php:347
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\getId
‪int getId($row)
Definition: AbstractTreeView.php:694
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\getRootRecord
‪array getRootRecord()
Definition: AbstractTreeView.php:846
‪TYPO3\CMS\Backend\View\PageTreeView\$ext_showPageId
‪bool $ext_showPageId
Definition: PageTreeView.php:31
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\reset
‪reset()
Definition: AbstractTreeView.php:327
‪TYPO3\CMS\Backend\Utility\BackendUtility\wrapClickMenuOnIcon
‪static string wrapClickMenuOnIcon( $content, $table, $uid=0, $context='', $_addParams='', $_enDisItems='', $returnTagParameters=false)
Definition: BackendUtility.php:2759
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\$tree
‪array $tree
Definition: AbstractTreeView.php:230
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\__construct
‪__construct()
Definition: AbstractTreeView.php:255
‪TYPO3\CMS\Backend\View\PageTreeView\PMicon
‪string PMicon($row, $a, $c, $nextCount, $exp)
Definition: PageTreeView.php:230
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\getRootIcon
‪string getRootIcon($rec)
Definition: AbstractTreeView.php:637
‪TYPO3\CMS\Backend\View\PageTreeView\PMiconATagWrap
‪string PMiconATagWrap($icon, $cmd, $isExpand=true)
Definition: PageTreeView.php:249
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\$bank
‪int $bank
Definition: AbstractTreeView.php:240
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\wrapIcon
‪string wrapIcon($icon, $row)
Definition: AbstractTreeView.php:533
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\getJumpToParam
‪string getJumpToParam($row)
Definition: AbstractTreeView.php:705
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Backend\View\PageTreeView\__construct
‪__construct()
Definition: PageTreeView.php:42
‪TYPO3\CMS\Backend\View\PageTreeView\wrapIcon
‪string wrapIcon($thePageIcon, $row)
Definition: PageTreeView.php:55
‪TYPO3\CMS\Backend\Tree\View\PageTreeView\init
‪init($clause='', $orderByFields='')
Definition: PageTreeView.php:67
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\getIcon
‪string getIcon($row)
Definition: AbstractTreeView.php:649
‪TYPO3\CMS\Backend\Tree\View\BrowseTreeView
Definition: BrowseTreeView.php:28
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\getTree
‪int getTree($uid, $depth=999, $depthData='')
Definition: AbstractTreeView.php:723
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\getRecord
‪array getRecord($uid)
Definition: AbstractTreeView.php:859
‪TYPO3\CMS\Backend\Tree\View\PageTreeView\getTitleStr
‪string getTitleStr($row, $titleLen=30)
Definition: PageTreeView.php:120
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\getThisScript
‪string getThisScript()
Definition: AbstractTreeView.php:276
‪TYPO3\CMS\Backend\View\PageTreeView\getBrowsableTree
‪string getBrowsableTree()
Definition: PageTreeView.php:265
‪TYPO3\CMS\Backend\Tree\View\PageTreeView\initializePositionSaving
‪initializePositionSaving()
Definition: PageTreeView.php:107
‪TYPO3\CMS\Backend\View\PageTreeView\printTree
‪string printTree($treeArr='')
Definition: PageTreeView.php:122
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\wrapTitle
‪string wrapTitle($title, $row, $bank=0)
Definition: AbstractTreeView.php:519
‪TYPO3\CMS\Backend\Utility\BackendUtility\isRecordLocked
‪static array bool isRecordLocked($table, $uid)
Definition: BackendUtility.php:3397
‪TYPO3\CMS\Backend\Tree\View\AbstractTreeView\printTree
‪string printTree($treeArr='')
Definition: AbstractTreeView.php:413