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