[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\ConnectionPool;
21 use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
22 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
23 use TYPO3\CMS\Core\Imaging\Icon;
24 use TYPO3\CMS\Core\LinkHandling\LinkService;
25 use TYPO3\CMS\Core\Page\PageRenderer;
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27 use TYPO3\CMS\Core\Utility\MathUtility;
28 use TYPO3\CMS\Recordlist\Tree\View\LinkParameterProviderInterface;
29
30 /**
31 * Link handler for page (and content) links
32 */
33 class PageLinkHandler extends AbstractLinkHandler implements LinkHandlerInterface, LinkParameterProviderInterface
34 {
35 /**
36 * @var int
37 */
38 protected $expandPage = 0;
39
40 /**
41 * Parts of the current link
42 *
43 * @var array
44 */
45 protected $linkParts = [];
46
47 /**
48 * Checks if this is the handler for the given link
49 *
50 * The handler may store this information locally for later usage.
51 *
52 * @param array $linkParts Link parts as returned from TypoLinkCodecService
53 *
54 * @return bool
55 */
56 public function canHandleLink(array $linkParts)
57 {
58 if (!$linkParts['url']) {
59 return false;
60 }
61
62 $data = $linkParts['url'];
63 // Checking if the id-parameter is an alias.
64 if (isset($data['pagealias'])) {
65 $records = BackendUtility::getRecordsByField('pages', 'alias', $data['pagealias']);
66 if (empty($records)) {
67 return false;
68 }
69 $data['pageuid'] = (int)$records[0]['uid'];
70 }
71 // Check if the page still exists
72 if ((int)$data['pageuid'] > 0) {
73 $pageRow = BackendUtility::getRecordWSOL('pages', $data['pageuid']);
74 if (!$pageRow) {
75 return false;
76 }
77 } elseif ($data['pageuid'] !== 'current') {
78 return false;
79 }
80
81 $this->linkParts = $linkParts;
82 return true;
83 }
84
85 /**
86 * Format the current link for HTML output
87 *
88 * @return string
89 */
90 public function formatCurrentUrl()
91 {
92 $lang = $this->getLanguageService();
93 $titleLen = (int)$this->getBackendUser()->uc['titleLen'];
94
95 $id = $this->linkParts['url']['pageuid'];
96 $pageRow = BackendUtility::getRecordWSOL('pages', $id);
97
98 return htmlspecialchars($lang->getLL('page'))
99 . ' \'' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($pageRow['title'], $titleLen)) . '\''
100 . ' (ID: ' . $id . ($this->linkParts['url']['fragment'] ? ', #' . $this->linkParts['url']['fragment'] : '') . ')';
101 }
102
103 /**
104 * Render the link handler
105 *
106 * @param ServerRequestInterface $request
107 *
108 * @return string
109 */
110 public function render(ServerRequestInterface $request)
111 {
112 GeneralUtility::makeInstance(PageRenderer::class)->loadRequireJsModule('TYPO3/CMS/Recordlist/PageLinkHandler');
113
114 $this->expandPage = isset($request->getQueryParams()['expandPage']) ? (int)$request->getQueryParams()['expandPage'] : 0;
115 $this->setTemporaryDbMounts();
116
117 $backendUser = $this->getBackendUser();
118
119 /** @var ElementBrowserPageTreeView $pageTree */
120 $pageTree = GeneralUtility::makeInstance(ElementBrowserPageTreeView::class);
121 $pageTree->setLinkParameterProvider($this);
122 $pageTree->ext_showNavTitle = (bool)$backendUser->getTSConfigVal('options.pageTree.showNavTitle');
123 $pageTree->ext_showPageId = (bool)$backendUser->getTSConfigVal('options.pageTree.showPageIdWithTitle');
124 $pageTree->ext_showPathAboveMounts = (bool)$backendUser->getTSConfigVal('options.pageTree.showPathAboveMounts');
125 $pageTree->addField('nav_title');
126
127 $this->view->assign('temporaryTreeMountCancelLink', $this->getTemporaryTreeMountCancelNotice());
128 $this->view->assign('tree', $pageTree->getBrowsableTree());
129 $this->getRecordsOnExpandedPage($this->expandPage);
130 return $this->view->render('Page');
131 }
132
133 /**
134 * This adds all content elements on a page to the view and lets you create a link to the element.
135 *
136 * @param int $pageId Page uid to expand
137 *
138 * @return void
139 */
140 protected function getRecordsOnExpandedPage($pageId)
141 {
142 // If there is an anchor value (content element reference) in the element reference, then force an ID to expand:
143 if (!$pageId && isset($this->linkParts['url']['fragment'])) {
144 // Set to the current link page id.
145 $pageId = $this->linkParts['url']['pageuid'];
146 }
147 // Draw the record list IF there is a page id to expand:
148 if ($pageId && MathUtility::canBeInterpretedAsInteger($pageId) && $this->getBackendUser()->isInWebMount($pageId)) {
149 $pageId = (int)$pageId;
150
151 $activePageRecord = BackendUtility::getRecordWSOL('pages', $pageId);
152 $this->view->assign('expandActivePage', true);
153
154 // Create header for listing, showing the page title/icon
155 $this->view->assign('activePage', $activePageRecord);
156 $this->view->assign('activePageTitle', BackendUtility::getRecordTitle('pages', $activePageRecord, true));
157 $this->view->assign('activePageIcon', $this->iconFactory->getIconForRecord('pages', $activePageRecord, Icon::SIZE_SMALL)->render());
158
159 // Look up tt_content elements from the expanded page
160 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
161 ->getQueryBuilderForTable('tt_content');
162
163 $queryBuilder->getRestrictions()
164 ->removeAll()
165 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
166 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
167
168 $contentElements = $queryBuilder
169 ->select('*')
170 ->from('tt_content')
171 ->where(
172 $queryBuilder->expr()->eq(
173 'pid',
174 $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
175 )
176 )
177 ->orderBy('colPos')
178 ->addOrderBy('sorting')
179 ->execute()
180 ->fetchAll();
181
182 // Enrich list of records
183 foreach ($contentElements as &$contentElement) {
184 $contentElement['url'] = GeneralUtility::makeInstance(LinkService::class)->asString(['type' => LinkService::TYPE_PAGE, 'pageuid' => (int)$pageId, 'fragment' => $contentElement['uid']]);
185 $contentElement['isSelected'] = !empty($this->linkParts) && (int)$this->linkParts['url']['fragment'] === (int)$contentElement['uid'];
186 $contentElement['icon'] = $this->iconFactory->getIconForRecord('tt_content', $contentElement, Icon::SIZE_SMALL)->render();
187 $contentElement['title'] = BackendUtility::getRecordTitle('tt_content', $contentElement, true);
188 }
189 $this->view->assign('contentElements', $contentElements);
190 }
191 }
192
193 /**
194 * Check if a temporary tree mount is set and return a cancel button link
195 *
196 * @return string the link to cancel the temporary tree mount
197 */
198 protected function getTemporaryTreeMountCancelNotice()
199 {
200 if ((int)$this->getBackendUser()->getSessionData('pageTree_temporaryMountPoint') > 0) {
201 return GeneralUtility::linkThisScript(['setTempDBmount' => 0]);
202 } else {
203 return '';
204 }
205 }
206
207 /**
208 * @return void
209 */
210 protected function setTemporaryDbMounts()
211 {
212 $backendUser = $this->getBackendUser();
213
214 // Clear temporary DB mounts
215 $tmpMount = GeneralUtility::_GET('setTempDBmount');
216 if (isset($tmpMount)) {
217 $backendUser->setAndSaveSessionData('pageTree_temporaryMountPoint', (int)$tmpMount);
218 }
219 // Set temporary DB mounts
220 $alternativeWebmountPoint = (int)$backendUser->getSessionData('pageTree_temporaryMountPoint');
221 if ($alternativeWebmountPoint) {
222 $alternativeWebmountPoint = GeneralUtility::intExplode(',', $alternativeWebmountPoint);
223 $backendUser->setWebmounts($alternativeWebmountPoint);
224 } else {
225 // Setting alternative browsing mounts (ONLY local to browse_links.php this script so they stay "read-only")
226 $alternativeWebmountPoints = trim($backendUser->getTSConfigVal('options.pageTree.altElementBrowserMountPoints'));
227 $appendAlternativeWebmountPoints = $backendUser->getTSConfigVal('options.pageTree.altElementBrowserMountPoints.append');
228 if ($alternativeWebmountPoints) {
229 $alternativeWebmountPoints = GeneralUtility::intExplode(',', $alternativeWebmountPoints);
230 $this->getBackendUser()->setWebmounts($alternativeWebmountPoints, $appendAlternativeWebmountPoints);
231 }
232 }
233 }
234
235 /**
236 * @return string[] Array of body-tag attributes
237 */
238 public function getBodyTagAttributes()
239 {
240 if (count($this->linkParts) === 0 || empty($this->linkParts['url']['pageuid'])) {
241 return [];
242 }
243 return [
244 'data-current-link' => GeneralUtility::makeInstance(LinkService::class)->asString([
245 'type' => LinkService::TYPE_PAGE,
246 'pageuid' => (int)$this->linkParts['url']['pageuid'],
247 'fragment' => $this->linkParts['url']['fragment']
248 ])
249 ];
250 }
251
252 /**
253 * @param array $values Array of values to include into the parameters or which might influence the parameters
254 *
255 * @return string[] Array of parameters which have to be added to URLs
256 */
257 public function getUrlParameters(array $values)
258 {
259 $parameters = [
260 'expandPage' => isset($values['pid']) ? (int)$values['pid'] : $this->expandPage
261 ];
262 return array_merge($this->linkBrowser->getUrlParameters($values), $parameters);
263 }
264
265 /**
266 * @param array $values Values to be checked
267 *
268 * @return bool Returns TRUE if the given values match the currently selected item
269 */
270 public function isCurrentlySelectedItem(array $values)
271 {
272 return !empty($this->linkParts) && (int)$this->linkParts['url']['pageuid'] === (int)$values['pid'];
273 }
274
275 /**
276 * Returns the URL of the current script
277 *
278 * @return string
279 */
280 public function getScriptUrl()
281 {
282 return $this->linkBrowser->getScriptUrl();
283 }
284
285 /**
286 * @param string[] $fieldDefinitions Array of link attribute field definitions
287 * @return string[]
288 */
289 public function modifyLinkAttributes(array $fieldDefinitions)
290 {
291 $configuration = $this->linkBrowser->getConfiguration();
292 if (!empty($configuration['pageIdSelector.']['enabled'])) {
293 array_push($this->linkAttributes, 'pageIdSelector');
294 $fieldDefinitions['pageIdSelector'] = '
295 <tr>
296 <td>
297 <label>
298 ' . htmlspecialchars($this->getLanguageService()->getLL('page_id')) . ':
299 </label>
300 </td>
301 <td colspan="3">
302 <input type="text" size="6" name="luid" id="luid" /> <input class="btn btn-default t3js-pageLink" type="submit" value="'
303 . htmlspecialchars($this->getLanguageService()->getLL('setLink')) . '" />
304 </td>
305 </tr>';
306 }
307 return $fieldDefinitions;
308 }
309 }