[TASK] Use Fluid for rendering LinkBrowsers
[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 htmlspecialchars($lang->getLL('page'))
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_showPageId = (bool)$backendUser->getTSConfigVal('options.pageTree.showPageIdWithTitle');
125 $pageTree->ext_showNavTitle = (bool)$backendUser->getTSConfigVal('options.pageTree.showNavTitle');
126 $pageTree->addField('nav_title');
127
128 $this->view->assign('temporaryTreeMountCancelLink', $this->getTemporaryTreeMountCancelNotice());
129 $this->view->assign('tree', $pageTree->getBrowsableTree());
130 $this->getRecordsOnExpandedPage($this->expandPage);
131 return $this->view->render('Page');
132 }
133
134 /**
135 * This adds all content elements on a page to the view and lets you create a link to the element.
136 *
137 * @param int $pageId Page uid to expand
138 *
139 * @return void
140 */
141 protected function getRecordsOnExpandedPage($pageId)
142 {
143 // If there is an anchor value (content element reference) in the element reference, then force an ID to expand:
144 if (!$pageId && isset($this->linkParts['anchor'])) {
145 // Set to the current link page id.
146 $pageId = $this->linkParts['pageid'];
147 }
148 // Draw the record list IF there is a page id to expand:
149 if ($pageId && MathUtility::canBeInterpretedAsInteger($pageId) && $this->getBackendUser()->isInWebMount($pageId)) {
150 $pageId = (int)$pageId;
151
152 $activePageRecord = BackendUtility::getRecordWSOL('pages', $pageId);
153 $this->view->assign('expandActivePage', true);
154
155 // Create header for listing, showing the page title/icon
156 $this->view->assign('activePage', $activePageRecord);
157 $this->view->assign('activePageTitle', BackendUtility::getRecordTitle('pages', $activePageRecord, true));
158 $this->view->assign('activePageIcon', $this->iconFactory->getIconForRecord('pages', $activePageRecord, Icon::SIZE_SMALL)->render());
159
160 // Look up tt_content elements from the expanded page
161 $contentElements = $this->getDatabaseConnection()->exec_SELECTgetRows(
162 'uid,header,hidden,starttime,endtime,fe_group,CType,colPos,bodytext',
163 'tt_content',
164 'pid=' . (int)$pageId . BackendUtility::deleteClause('tt_content')
165 . BackendUtility::versioningPlaceholderClause('tt_content'),
166 '',
167 'colPos,sorting'
168 );
169
170 // Enrich list of records
171 foreach ($contentElements as &$contentElement) {
172 $contentElement['isSelected'] = !empty($this->linkParts) && (int)$this->linkParts['anchor'] === (int)$contentElement['uid'];
173 $contentElement['icon'] = $this->iconFactory->getIconForRecord('tt_content', $contentElement, Icon::SIZE_SMALL)->render();
174 $contentElement['title'] = BackendUtility::getRecordTitle('tt_content', $contentElement, true);
175 }
176 $this->view->assign('contentElements', $contentElements);
177 }
178 }
179
180 /**
181 * Check if a temporary tree mount is set and return a cancel button link
182 *
183 * @return string the link to cancel the temporary tree mount
184 */
185 protected function getTemporaryTreeMountCancelNotice()
186 {
187 if ((int)$this->getBackendUser()->getSessionData('pageTree_temporaryMountPoint') > 0) {
188 return GeneralUtility::linkThisScript(['setTempDBmount' => 0]);
189 } else {
190 return '';
191 }
192 }
193
194 /**
195 * @return void
196 */
197 protected function setTemporaryDbMounts()
198 {
199 $backendUser = $this->getBackendUser();
200
201 // Clear temporary DB mounts
202 $tmpMount = GeneralUtility::_GET('setTempDBmount');
203 if (isset($tmpMount)) {
204 $backendUser->setAndSaveSessionData('pageTree_temporaryMountPoint', (int)$tmpMount);
205 }
206 // Set temporary DB mounts
207 $alternativeWebmountPoint = (int)$backendUser->getSessionData('pageTree_temporaryMountPoint');
208 if ($alternativeWebmountPoint) {
209 $alternativeWebmountPoint = GeneralUtility::intExplode(',', $alternativeWebmountPoint);
210 $backendUser->setWebmounts($alternativeWebmountPoint);
211 } else {
212 // Setting alternative browsing mounts (ONLY local to browse_links.php this script so they stay "read-only")
213 $alternativeWebmountPoints = trim($backendUser->getTSConfigVal('options.pageTree.altElementBrowserMountPoints'));
214 $appendAlternativeWebmountPoints = $backendUser->getTSConfigVal('options.pageTree.altElementBrowserMountPoints.append');
215 if ($alternativeWebmountPoints) {
216 $alternativeWebmountPoints = GeneralUtility::intExplode(',', $alternativeWebmountPoints);
217 $this->getBackendUser()->setWebmounts($alternativeWebmountPoints, $appendAlternativeWebmountPoints);
218 }
219 }
220 }
221
222 /**
223 * @return string[] Array of body-tag attributes
224 */
225 public function getBodyTagAttributes()
226 {
227 if (empty($this->linkParts)) {
228 return [];
229 }
230 return [
231 'data-current-link' => $this->linkParts['pageid'] . ($this->linkParts['anchor'] !== '' ? '#' . $this->linkParts['anchor'] : '')
232 ];
233 }
234
235 /**
236 * @param array $values Array of values to include into the parameters or which might influence the parameters
237 *
238 * @return string[] Array of parameters which have to be added to URLs
239 */
240 public function getUrlParameters(array $values)
241 {
242 $parameters = [
243 'expandPage' => isset($values['pid']) ? (int)$values['pid'] : $this->expandPage
244 ];
245 return array_merge($this->linkBrowser->getUrlParameters($values), $parameters);
246 }
247
248 /**
249 * @param array $values Values to be checked
250 *
251 * @return bool Returns TRUE if the given values match the currently selected item
252 */
253 public function isCurrentlySelectedItem(array $values)
254 {
255 return !empty($this->linkParts) && (int)$this->linkParts['pageid'] === (int)$values['pid'];
256 }
257
258 /**
259 * Returns the URL of the current script
260 *
261 * @return string
262 */
263 public function getScriptUrl()
264 {
265 return $this->linkBrowser->getScriptUrl();
266 }
267
268 /**
269 * @param string[] $fieldDefinitions Array of link attribute field definitions
270 * @return string[]
271 */
272 public function modifyLinkAttributes(array $fieldDefinitions)
273 {
274 $configuration = $this->linkBrowser->getConfiguration();
275 if (!empty($configuration['pageIdSelector.']['enabled'])) {
276 array_push($this->linkAttributes, 'pageIdSelector');
277 $fieldDefinitions['pageIdSelector'] = '
278 <tr>
279 <td>
280 <label>
281 ' . htmlspecialchars($this->getLanguageService()->getLL('page_id')) . ':
282 </label>
283 </td>
284 <td colspan="3">
285 <input type="text" size="6" name="luid" id="luid" /> <input class="btn btn-default t3js-pageLink" type="submit" value="'
286 . htmlspecialchars($this->getLanguageService()->getLL('setLink')) . '" />
287 </td>
288 </tr>';
289 }
290 return $fieldDefinitions;
291 }
292
293 /**
294 * @return DatabaseConnection
295 */
296 protected function getDatabaseConnection()
297 {
298 return $GLOBALS['TYPO3_DB'];
299 }
300 }