[BUGFIX] Show mountpoint path in record + link browsers if enabled in UserTS
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Tree / View / ElementBrowserPageTreeView.php
1 <?php
2 namespace TYPO3\CMS\Backend\Tree\View;
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
17 use TYPO3\CMS\Core\LinkHandling\LinkService;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19 use TYPO3\CMS\Frontend\Page\PageRepository;
20 use TYPO3\CMS\Recordlist\Tree\View\LinkParameterProviderInterface;
21
22 /**
23 * Class which generates the selectable page tree
24 *
25 * Browsable tree, used in PagePositionMaps (move elements), the Link Wizard and the Database Browser (for which it will be extended)
26 */
27 class ElementBrowserPageTreeView extends BrowseTreeView
28 {
29 /**
30 * whether the page ID should be shown next to the title, activate through
31 * userTSconfig (options.pageTree.showPageIdWithTitle)
32 *
33 * @var bool
34 */
35 public $ext_showPageId = false;
36
37 /**
38 * @var bool
39 */
40 public $ext_pArrPages = true;
41
42 /**
43 * @var LinkParameterProviderInterface
44 */
45 protected $linkParameterProvider;
46
47 /**
48 * Constructor. Just calling init()
49 */
50 public function __construct()
51 {
52 parent::__construct();
53 $this->init();
54 $this->clause = ' AND doktype <> ' . PageRepository::DOKTYPE_RECYCLER . $this->clause;
55 }
56
57 /**
58 * @param LinkParameterProviderInterface $linkParameterProvider
59 *
60 * @return void
61 */
62 public function setLinkParameterProvider(LinkParameterProviderInterface $linkParameterProvider)
63 {
64 $this->linkParameterProvider = $linkParameterProvider;
65 $this->thisScript = $linkParameterProvider->getScriptUrl();
66 }
67
68 /**
69 * Wrapping the title in a link, if applicable.
70 *
71 * @param string $title Title, (must be ready for output, that means it must be htmlspecialchars()'ed).
72 * @param array $v The record
73 * @param bool $ext_pArrPages (ignored)
74 * @return string Wrapping title string.
75 */
76 public function wrapTitle($title, $v, $ext_pArrPages = false)
77 {
78 if ($this->ext_isLinkable($v['doktype'], $v['uid'])) {
79 $url = GeneralUtility::makeInstance(LinkService::class)->asString(['type' => LinkService::TYPE_PAGE, 'pageuid' => (int)$v['uid']]);
80 return '<span class="list-tree-title"><a href="' . htmlspecialchars($url) . '" class="t3js-pageLink">' . $title . '</a></span>';
81 } else {
82 return '<span class="list-tree-title text-muted">' . $title . '</span>';
83 }
84 }
85
86 /**
87 * Create the page navigation tree in HTML
88 *
89 * @param array|string $treeArr Tree array
90 * @return string HTML output.
91 */
92 public function printTree($treeArr = '')
93 {
94 $titleLen = (int)$GLOBALS['BE_USER']->uc['titleLen'];
95 if (!is_array($treeArr)) {
96 $treeArr = $this->tree;
97 }
98 $out = '';
99 // We need to count the opened <ul>'s every time we dig into another level,
100 // so we know how many we have to close when all children are done rendering
101 $closeDepth = [];
102 foreach ($treeArr as $treeItem) {
103 if ($treeItem['isMountPointPath']) {
104 $out .= '<li class="list-tree-path">' . $treeItem['title'] . '</li>';
105 continue;
106 }
107
108 $classAttr = $treeItem['row']['_CSSCLASS'];
109 if ($treeItem['isFirst']) {
110 $out .= '<ul class="list-tree">';
111 }
112
113 // Add CSS classes to the list item
114 if ($treeItem['hasSub']) {
115 $classAttr .= ' list-tree-control-open';
116 }
117
118 $selected = '';
119 if ($this->linkParameterProvider->isCurrentlySelectedItem(['pid' => (int)$treeItem['row']['uid']])) {
120 $selected = ' bg-success';
121 $classAttr .= ' active';
122 }
123 $urlParameters = $this->linkParameterProvider->getUrlParameters(['pid' => (int)$treeItem['row']['uid']]);
124 $aOnClick = 'return jumpToUrl(' . GeneralUtility::quoteJSvalue($this->getThisScript() . ltrim(GeneralUtility::implodeArrayForUrl('', $urlParameters), '&')) . ');';
125 $cEbullet = $this->ext_isLinkable($treeItem['row']['doktype'], $treeItem['row']['uid'])
126 ? '<a href="#" class="list-tree-show" onclick="' . htmlspecialchars($aOnClick) . '"><i class="fa fa-caret-square-o-right"></i></a>'
127 : '';
128 $out .= '
129 <li' . ($classAttr ? ' class="' . trim($classAttr) . '"' : '') . '>
130 <span class="list-tree-group' . $selected . '">
131 ' . $cEbullet . $treeItem['HTML'] . $this->wrapTitle($this->getTitleStr($treeItem['row'], $titleLen), $treeItem['row'], $this->ext_pArrPages) . '
132 </span>
133 ';
134 if (!$treeItem['hasSub']) {
135 $out .= '</li>';
136 }
137
138 // We have to remember if this is the last one
139 // on level X so the last child on level X+1 closes the <ul>-tag
140 if ($treeItem['isLast']) {
141 $closeDepth[$treeItem['invertedDepth']] = 1;
142 }
143 // If this is the last one and does not have subitems, we need to close
144 // the tree as long as the upper levels have last items too
145 if ($treeItem['isLast'] && !$treeItem['hasSub']) {
146 for ($i = $treeItem['invertedDepth']; $closeDepth[$i] == 1; $i++) {
147 $closeDepth[$i] = 0;
148 $out .= '</ul></li>';
149 }
150 }
151 }
152 return '<ul class="list-tree list-tree-root">' . $out . '</ul>';
153 }
154
155 /**
156 * Returns TRUE if a doktype can be linked.
157 *
158 * @param int $doktype Doktype value to test
159 * @param int $uid uid to test.
160 * @return bool
161 */
162 public function ext_isLinkable($doktype, $uid)
163 {
164 return $uid && $doktype < PageRepository::DOKTYPE_SPACER;
165 }
166
167 /**
168 * Wrap the plus/minus icon in a link
169 *
170 * @param string $icon HTML string to wrap, probably an image tag.
171 * @param string $cmd Command for 'PM' get var
172 * @param string $bMark If set, the link will have an anchor point (=$bMark) and a name attribute (=$bMark)
173 * @param bool $isOpen
174 * @return string Link-wrapped input string
175 */
176 public function PM_ATagWrap($icon, $cmd, $bMark = '', $isOpen = false)
177 {
178 $anchor = $bMark ? '#' . $bMark : '';
179 $name = $bMark ? ' name=' . $bMark : '';
180 $urlParameters = $this->linkParameterProvider->getUrlParameters([]);
181 $urlParameters['PM'] = $cmd;
182 $aOnClick = 'return jumpToUrl(' . GeneralUtility::quoteJSvalue($this->getThisScript() . ltrim(GeneralUtility::implodeArrayForUrl('', $urlParameters), '&')) . ',' . GeneralUtility::quoteJSvalue($anchor) . ');';
183 return '<a class="list-tree-control ' . ($isOpen ? 'list-tree-control-open' : 'list-tree-control-closed')
184 . '" href="#"' . htmlspecialchars($name) . ' onclick="' . htmlspecialchars($aOnClick) . '"><i class="fa"></i></a>';
185 }
186
187 /**
188 * Wrapping the image tag, $icon, for the row, $row
189 *
190 * @param string $icon The image tag for the icon
191 * @param array $row The row for the current element
192 * @return string The processed icon input value.
193 */
194 public function wrapIcon($icon, $row)
195 {
196 if ($this->ext_showPageId) {
197 $icon .= '[' . $row['uid'] . ']&nbsp;';
198 }
199 return $icon;
200 }
201 }