[BUGFIX] Show mountpoint path in record + link browsers if enabled in UserTS
[Packages/TYPO3.CMS.git] / typo3 / sysext / recordlist / Classes / LinkHandler / PageLinkHandler.php
1 <?php
2 namespace TYPO3\CMS\Recordlist\LinkHandler;
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 Psr\Http\Message\ServerRequestInterface;
18 use TYPO3\CMS\Backend\Tree\View\ElementBrowserPageTreeView;
19 use TYPO3\CMS\Backend\Utility\BackendUtility;
20 use TYPO3\CMS\Core\Database\DatabaseConnection;
21 use TYPO3\CMS\Core\Imaging\Icon;
22 use TYPO3\CMS\Core\Page\PageRenderer;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24 use TYPO3\CMS\Core\Utility\MathUtility;
25 use TYPO3\CMS\Recordlist\Tree\View\LinkParameterProviderInterface;
26
27 /**
28 * Link handler for page (and content) links
29 */
30 class PageLinkHandler extends AbstractLinkHandler implements LinkHandlerInterface, LinkParameterProviderInterface
31 {
32 /**
33 * @var int
34 */
35 protected $expandPage = 0;
36
37 /**
38 * Parts of the current link
39 *
40 * @var array
41 */
42 protected $linkParts = [];
43
44 /**
45 * Checks if this is the handler for the given link
46 *
47 * The handler may store this information locally for later usage.
48 *
49 * @param array $linkParts Link parts as returned from TypoLinkCodecService
50 *
51 * @return bool
52 */
53 public function canHandleLink(array $linkParts)
54 {
55 if (!$linkParts['url']) {
56 return false;
57 }
58
59 $id = $linkParts['url'];
60 $parts = explode('#', $id);
61 if (count($parts) > 1) {
62 $id = $parts[0];
63 $anchor = $parts[1];
64 } else {
65 $anchor = '';
66 }
67 // Checking if the id-parameter is an alias.
68 if (!MathUtility::canBeInterpretedAsInteger($id)) {
69 $records = BackendUtility::getRecordsByField('pages', 'alias', $id);
70 if (empty($records)) {
71 return false;
72 }
73 $id = (int)$records[0]['uid'];
74 }
75 $pageRow = BackendUtility::getRecordWSOL('pages', $id);
76 if (!$pageRow) {
77 return false;
78 }
79
80 $this->linkParts = $linkParts;
81 $this->linkParts['pageid'] = $id;
82 $this->linkParts['anchor'] = $anchor;
83
84 return true;
85 }
86
87 /**
88 * Format the current link for HTML output
89 *
90 * @return string
91 */
92 public function formatCurrentUrl()
93 {
94 $lang = $this->getLanguageService();
95 $titleLen = (int)$this->getBackendUser()->uc['titleLen'];
96
97 $id = $this->linkParts['pageid'];
98 $pageRow = BackendUtility::getRecordWSOL('pages', $id);
99
100 return $lang->getLL('page', true)
101 . ' \'' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($pageRow['title'], $titleLen)) . '\''
102 . ' (ID:' . $id . ($this->linkParts['anchor'] ? ', #' . $this->linkParts['anchor'] : '') . ')';
103 }
104
105 /**
106 * Render the link handler
107 *
108 * @param ServerRequestInterface $request
109 *
110 * @return string
111 */
112 public function render(ServerRequestInterface $request)
113 {
114 GeneralUtility::makeInstance(PageRenderer::class)->loadRequireJsModule('TYPO3/CMS/Recordlist/PageLinkHandler');
115
116 $this->expandPage = isset($request->getQueryParams()['expandPage']) ? (int)$request->getQueryParams()['expandPage'] : 0;
117 $this->setTemporaryDbMounts();
118
119 $backendUser = $this->getBackendUser();
120
121 /** @var ElementBrowserPageTreeView $pageTree */
122 $pageTree = GeneralUtility::makeInstance(ElementBrowserPageTreeView::class);
123 $pageTree->setLinkParameterProvider($this);
124 $pageTree->ext_showNavTitle = (bool)$backendUser->getTSConfigVal('options.pageTree.showNavTitle');
125 $pageTree->ext_showPageId = (bool)$backendUser->getTSConfigVal('options.pageTree.showPageIdWithTitle');
126 $pageTree->ext_showPathAboveMounts = (bool)$backendUser->getTSConfigVal('options.pageTree.showPathAboveMounts');
127 $pageTree->addField('nav_title');
128 $tree = $pageTree->getBrowsableTree();
129
130 return '
131
132 <!--
133 Wrapper table for page tree / record list:
134 -->
135 <table border="0" cellpadding="0" cellspacing="0" id="typo3-linkPages">
136 <tr>
137 <td class="c-wCell" valign="top"><h3>' . $this->getLanguageService()->getLL('pageTree') . ':</h3>'
138 . $this->getTemporaryTreeMountCancelNotice() . $tree . '</td>
139 <td class="c-wCell" valign="top">' . $this->expandPage($this->expandPage) . '</td>
140 </tr>
141 </table>';
142 }
143
144 /**
145 * This displays all content elements on a page and lets you create a link to the element.
146 *
147 * @param int $expPageId Page uid to expand
148 *
149 * @return string HTML output. Returns content only if the ->expandPage value is set (pointing to a page uid to show tt_content records from ...)
150 */
151 public function expandPage($expPageId)
152 {
153 // If there is an anchor value (content element reference) in the element reference, then force an ID to expand:
154 if (!$expPageId && isset($this->linkParts['anchor'])) {
155 // Set to the current link page id.
156 $expPageId = $this->linkParts['pageid'];
157 }
158 // Draw the record list IF there is a page id to expand:
159 if (!$expPageId || !MathUtility::canBeInterpretedAsInteger($expPageId) || !$this->getBackendUser()->isInWebMount($expPageId)) {
160 return '';
161 }
162
163 // Set header:
164 $out = '<h3>' . $this->getLanguageService()->getLL('contentElements') . ':</h3>';
165 // Create header for listing, showing the page title/icon:
166 $mainPageRec = BackendUtility::getRecordWSOL('pages', $expPageId);
167 $db = $this->getDatabaseConnection();
168 $out .= '
169 <ul class="list-tree list-tree-root list-tree-root-clean">
170 <li class="list-tree-control-open">
171 <span class="list-tree-group">
172 <span class="list-tree-icon">' . $this->iconFactory->getIconForRecord('pages', $mainPageRec, Icon::SIZE_SMALL)->render() . '</span>
173 <span class="list-tree-title">' . htmlspecialchars(BackendUtility::getRecordTitle('pages', $mainPageRec, true)) . '</span>
174 </span>
175 <ul>
176 ';
177
178 // Look up tt_content elements from the expanded page:
179 $res = $db->exec_SELECTquery(
180 '*',
181 'tt_content',
182 'pid=' . (int)$expPageId . BackendUtility::deleteClause('tt_content')
183 . BackendUtility::versioningPlaceholderClause('tt_content'),
184 '',
185 'colPos,sorting'
186 );
187 // Traverse list of records:
188 $c = 0;
189 while ($row = $db->sql_fetch_assoc($res)) {
190 $c++;
191 $icon = $this->iconFactory->getIconForRecord('tt_content', $row, Icon::SIZE_SMALL)->render();
192 $selected = '';
193 if (!empty($this->linkParts) && (int)$this->linkParts['anchor'] === (int)$row['uid']) {
194 $selected = ' class="active"';
195 }
196 // Putting list element HTML together:
197 // Output of BackendUtility::getRecordTitle() is already hsc'ed
198 $out .= '
199 <li' . $selected . '>
200 <span class="list-tree-group">
201 <span class="list-tree-icon">
202 ' . $icon . '
203 </span>
204 <span class="list-tree-title">
205 <a href="#" class="t3js-pageLink" data-id="' . (int)$expPageId . '" data-anchor="#' . (int)$row['uid'] . '">
206 ' . BackendUtility::getRecordTitle('tt_content', $row, true) . '
207 </a>
208 </span>
209 </span>
210 </li>
211 ';
212 }
213 $out .= '
214 </ul>
215 </li>
216 </ul>
217 ';
218
219 return $out;
220 }
221
222 /**
223 * Check if a temporary tree mount is set and return a cancel button
224 *
225 * @return string HTML code
226 */
227 protected function getTemporaryTreeMountCancelNotice()
228 {
229 if ((int)$this->getBackendUser()->getSessionData('pageTree_temporaryMountPoint') === 0) {
230 return '';
231 }
232 $link = '<p><a href="' . htmlspecialchars(GeneralUtility::linkThisScript(['setTempDBmount' => 0])) . '" class="btn btn-primary">'
233 . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.temporaryDBmount', true) . '</a></p>';
234 return $link;
235 }
236
237 /**
238 * @return void
239 */
240 protected function setTemporaryDbMounts()
241 {
242 $backendUser = $this->getBackendUser();
243
244 // Clear temporary DB mounts
245 $tmpMount = GeneralUtility::_GET('setTempDBmount');
246 if (isset($tmpMount)) {
247 $backendUser->setAndSaveSessionData('pageTree_temporaryMountPoint', (int)$tmpMount);
248 }
249 // Set temporary DB mounts
250 $alternativeWebmountPoint = (int)$backendUser->getSessionData('pageTree_temporaryMountPoint');
251 if ($alternativeWebmountPoint) {
252 $alternativeWebmountPoint = GeneralUtility::intExplode(',', $alternativeWebmountPoint);
253 $backendUser->setWebmounts($alternativeWebmountPoint);
254 } else {
255 // Setting alternative browsing mounts (ONLY local to browse_links.php this script so they stay "read-only")
256 $alternativeWebmountPoints = trim($backendUser->getTSConfigVal('options.pageTree.altElementBrowserMountPoints'));
257 $appendAlternativeWebmountPoints = $backendUser->getTSConfigVal('options.pageTree.altElementBrowserMountPoints.append');
258 if ($alternativeWebmountPoints) {
259 $alternativeWebmountPoints = GeneralUtility::intExplode(',', $alternativeWebmountPoints);
260 $this->getBackendUser()->setWebmounts($alternativeWebmountPoints, $appendAlternativeWebmountPoints);
261 }
262 }
263 }
264
265 /**
266 * @return string[] Array of body-tag attributes
267 */
268 public function getBodyTagAttributes()
269 {
270 if (empty($this->linkParts)) {
271 return [];
272 }
273 return [
274 'data-current-link' => $this->linkParts['pageid'] . ($this->linkParts['anchor'] !== '' ? '#' . $this->linkParts['anchor'] : '')
275 ];
276 }
277
278 /**
279 * @param array $values Array of values to include into the parameters or which might influence the parameters
280 *
281 * @return string[] Array of parameters which have to be added to URLs
282 */
283 public function getUrlParameters(array $values)
284 {
285 $parameters = [
286 'expandPage' => isset($values['pid']) ? (int)$values['pid'] : $this->expandPage
287 ];
288 return array_merge($this->linkBrowser->getUrlParameters($values), $parameters);
289 }
290
291 /**
292 * @param array $values Values to be checked
293 *
294 * @return bool Returns TRUE if the given values match the currently selected item
295 */
296 public function isCurrentlySelectedItem(array $values)
297 {
298 return !empty($this->linkParts) && (int)$this->linkParts['pageid'] === (int)$values['pid'];
299 }
300
301 /**
302 * Returns the URL of the current script
303 *
304 * @return string
305 */
306 public function getScriptUrl()
307 {
308 return $this->linkBrowser->getScriptUrl();
309 }
310
311 /**
312 * @param string[] $fieldDefinitions Array of link attribute field definitions
313 * @return string[]
314 */
315 public function modifyLinkAttributes(array $fieldDefinitions)
316 {
317 $configuration = $this->linkBrowser->getConfiguration();
318 if (!empty($configuration['pageIdSelector.']['enabled'])) {
319 array_push($this->linkAttributes, 'pageIdSelector');
320 $fieldDefinitions['pageIdSelector'] = '
321 <tr>
322 <td>
323 <label>
324 ' . $this->getLanguageService()->getLL('page_id', true) . ':
325 </label>
326 </td>
327 <td colspan="3">
328 <input type="text" size="6" name="luid" id="luid" /> <input class="btn btn-default t3js-pageLink" type="submit" value="'
329 . $this->getLanguageService()->getLL('setLink', true) . '" />
330 </td>
331 </tr>';
332 }
333 return $fieldDefinitions;
334 }
335
336 /**
337 * @return DatabaseConnection
338 */
339 protected function getDatabaseConnection()
340 {
341 return $GLOBALS['TYPO3_DB'];
342 }
343 }