f56c23de3c5bf628caca2b21b340b3e329d7aa9f
[Packages/TYPO3.CMS.git] / typo3 / sysext / recordlist / Classes / Browser / DatabaseBrowser.php
1 <?php
2 namespace TYPO3\CMS\Recordlist\Browser;
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\Backend\RecordList\ElementBrowserRecordList;
18 use TYPO3\CMS\Backend\Utility\BackendUtility;
19 use TYPO3\CMS\Core\Imaging\Icon;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Core\Utility\MathUtility;
22 use TYPO3\CMS\Recordlist\Tree\View\ElementBrowserPageTreeView;
23 use TYPO3\CMS\Recordlist\Tree\View\LinkParameterProviderInterface;
24
25 /**
26 * Showing a page tree and allows you to browse for records
27 */
28 class DatabaseBrowser extends AbstractElementBrowser implements ElementBrowserInterface, LinkParameterProviderInterface
29 {
30 /**
31 * When you click a page title/expand icon to see the content of a certain page, this
32 * value will contain the ID of the expanded page.
33 * If the value is NOT set by GET parameter, then it will be restored from the module session data.
34 *
35 * @var NULL|int
36 */
37 protected $expandPage;
38
39 /**
40 */
41 protected function initialize()
42 {
43 parent::initialize();
44 $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/BrowseDatabase');
45 }
46
47 /**
48 */
49 protected function initVariables()
50 {
51 parent::initVariables();
52 $this->expandPage = GeneralUtility::_GP('expandPage');
53 }
54
55 /**
56 * Session data for this class can be set from outside with this method.
57 *
58 * @param mixed[] $data Session data array
59 * @return array[] Session data and boolean which indicates that data needs to be stored in session because it's changed
60 */
61 public function processSessionData($data)
62 {
63 if ($this->expandPage !== null) {
64 $data['expandPage'] = $this->expandPage;
65 $store = true;
66 } else {
67 $this->expandPage = (int)$data['expandPage'];
68 $store = false;
69 }
70 return [$data, $store];
71 }
72
73 /**
74 * @return string HTML content
75 */
76 public function render()
77 {
78 $this->setTemporaryDbMounts();
79
80 list(, , , $allowedTables) = explode('|', $this->bparams);
81 $backendUser = $this->getBackendUser();
82
83 // Making the browsable pagetree:
84 /** @var ElementBrowserPageTreeView $pageTree */
85 $pageTree = GeneralUtility::makeInstance(ElementBrowserPageTreeView::class);
86 $pageTree->setLinkParameterProvider($this);
87 $pageTree->ext_pArrPages = $allowedTables === 'pages';
88 $pageTree->ext_showNavTitle = (bool)$backendUser->getTSConfigVal('options.pageTree.showNavTitle');
89 $pageTree->ext_showPageId = (bool)$backendUser->getTSConfigVal('options.pageTree.showPageIdWithTitle');
90 $pageTree->ext_showPathAboveMounts = (bool)$backendUser->getTSConfigVal('options.pageTree.showPathAboveMounts');
91 $pageTree->addField('nav_title');
92 $tree = $pageTree->getBrowsableTree();
93
94 $withTree = true;
95 if ($allowedTables !== '' && $allowedTables !== '*') {
96 $tablesArr = GeneralUtility::trimExplode(',', $allowedTables, true);
97 $onlyRootLevel = true;
98 foreach ($tablesArr as $currentTable) {
99 if (isset($GLOBALS['TCA'][$currentTable])) {
100 if (!isset($GLOBALS['TCA'][$currentTable]['ctrl']['rootLevel']) || (int)$GLOBALS['TCA'][$currentTable]['ctrl']['rootLevel'] !== 1) {
101 $onlyRootLevel = false;
102 }
103 }
104 }
105 if ($onlyRootLevel) {
106 $withTree = false;
107 // page to work on is root
108 $this->expandPage = 0;
109 }
110 }
111
112 $renderedRecordList = $this->renderTableRecords($allowedTables);
113
114 $this->initDocumentTemplate();
115 $content = $this->doc->startPage(htmlspecialchars($this->getLanguageService()->getLL('recordSelector')));
116
117 // Putting the parts together, side by side:
118 $markup = [];
119 $markup[] = '<!-- Wrapper table for folder tree / filelist: -->';
120 $markup[] = '<div class="element-browser">';
121 $markup[] = ' <div class="element-browser-panel element-browser-main">';
122 if ($withTree) {
123 $markup[] = ' <div class="element-browser-main-sidebar">';
124 $markup[] = ' <div class="element-browser-body">';
125 $markup[] = ' <h3>' . htmlspecialchars($this->getLanguageService()->getLL('pageTree')) . ':</h3>';
126 $markup[] = ' ' . $this->getTemporaryTreeMountCancelNotice();
127 $markup[] = ' ' . $tree;
128 $markup[] = ' </div>';
129 $markup[] = ' </div>';
130 }
131 $markup[] = ' <div class="element-browser-main-content">';
132 $markup[] = ' <div class="element-browser-body">';
133 $markup[] = ' ' . $this->doc->getFlashMessages();
134 $markup[] = ' ' . $renderedRecordList;
135 $markup[] = ' </div>';
136 $markup[] = ' </div>';
137 $markup[] = ' </div>';
138 $markup[] = '</div>';
139 $content .= implode('', $markup);
140
141 // Ending page, returning content:
142 $content .= $this->doc->endPage();
143 return $this->doc->insertStylesAndJS($content);
144 }
145
146 /**
147 * Check if a temporary tree mount is set and return a cancel button
148 *
149 * @return string HTML code
150 */
151 protected function getTemporaryTreeMountCancelNotice()
152 {
153 if ((int)$this->getBackendUser()->getSessionData('pageTree_temporaryMountPoint') === 0) {
154 return '';
155 }
156 $link = '<p><a href="' . htmlspecialchars(GeneralUtility::linkThisScript(['setTempDBmount' => 0])) . '" class="btn btn-primary">'
157 . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.temporaryDBmount')) . '</a></p>';
158
159 return $link;
160 }
161
162 /**
163 * If the current Backend User has set a temporary DB mount, it is stored to her/his UC.
164 */
165 protected function setTemporaryDbMounts()
166 {
167 $backendUser = $this->getBackendUser();
168
169 // Clear temporary DB mounts
170 $tmpMount = GeneralUtility::_GET('setTempDBmount');
171 if (isset($tmpMount)) {
172 $backendUser->setAndSaveSessionData('pageTree_temporaryMountPoint', (int)$tmpMount);
173 }
174 // Set temporary DB mounts
175 $alternativeWebmountPoint = (int)$backendUser->getSessionData('pageTree_temporaryMountPoint');
176 if ($alternativeWebmountPoint) {
177 $alternativeWebmountPoint = GeneralUtility::intExplode(',', $alternativeWebmountPoint);
178 $backendUser->setWebmounts($alternativeWebmountPoint);
179 } else {
180 // Setting alternative browsing mounts (ONLY local to browse_links.php this script so they stay "read-only")
181 $alternativeWebmountPoints = trim($backendUser->getTSConfigVal('options.pageTree.altElementBrowserMountPoints'));
182 $appendAlternativeWebmountPoints = $backendUser->getTSConfigVal('options.pageTree.altElementBrowserMountPoints.append');
183 if ($alternativeWebmountPoints) {
184 $alternativeWebmountPoints = GeneralUtility::intExplode(',', $alternativeWebmountPoints);
185 $this->getBackendUser()->setWebmounts($alternativeWebmountPoints, $appendAlternativeWebmountPoints);
186 }
187 }
188 }
189
190 /**
191 * This lists all content elements for the given list of tables
192 *
193 * @param string $tables Comma separated list of tables. Set to "*" if you want all tables.
194 * @return string HTML code
195 */
196 protected function renderTableRecords($tables)
197 {
198 $backendUser = $this->getBackendUser();
199 if ($this->expandPage === null || $this->expandPage < 0 || !$backendUser->isInWebMount($this->expandPage)) {
200 return '';
201 }
202 // Set array with table names to list:
203 if (trim($tables) === '*') {
204 $tablesArr = array_keys($GLOBALS['TCA']);
205 } else {
206 $tablesArr = GeneralUtility::trimExplode(',', $tables, true);
207 }
208
209 $out = '<h3>' . htmlspecialchars($this->getLanguageService()->getLL('selectRecords')) . ':</h3>';
210 // Create the header, showing the current page for which the listing is.
211 // Includes link to the page itself, if pages are amount allowed tables.
212 $titleLen = (int)$backendUser->uc['titleLen'];
213 $mainPageRecord = BackendUtility::getRecordWSOL('pages', $this->expandPage);
214 if (is_array($mainPageRecord)) {
215 $pText = htmlspecialchars(GeneralUtility::fixed_lgd_cs($mainPageRecord['title'], $titleLen));
216
217 $out .= $this->iconFactory->getIconForRecord('pages', $mainPageRecord, Icon::SIZE_SMALL)->render();
218 if (in_array('pages', $tablesArr, true)) {
219 $out .= '<span data-uid="' . htmlspecialchars($mainPageRecord['uid']) . '" data-table="pages" data-title="' . htmlspecialchars($mainPageRecord['title']) . '" data-icon="">';
220 $out .= '<a href="#" data-close="0">'
221 . $this->iconFactory->getIcon('actions-edit-add', Icon::SIZE_SMALL)->render()
222 . '</a>'
223 . '<a href="#" data-close="1">'
224 . $pText
225 . '</a>';
226 $out .= '</span>';
227 } else {
228 $out .= $pText;
229 }
230 $out .= '<br />';
231 }
232
233 $permsClause = $backendUser->getPagePermsClause(1);
234 $pageInfo = BackendUtility::readPageAccess($this->expandPage, $permsClause);
235
236 /** @var ElementBrowserRecordList $dbList */
237 $dbList = GeneralUtility::makeInstance(ElementBrowserRecordList::class);
238 $dbList->setOverrideUrlParameters($this->getUrlParameters([]));
239 $dbList->thisScript = $this->thisScript;
240 $dbList->thumbs = false;
241 $dbList->localizationView = true;
242 $dbList->setIsEditable(false);
243 $dbList->calcPerms = $backendUser->calcPerms($pageInfo);
244 $dbList->noControlPanels = true;
245 $dbList->clickMenuEnabled = false;
246 $dbList->tableList = implode(',', $tablesArr);
247
248 // a string like "data[pages][79][storage_pid]"
249 list($fieldPointerString) = explode('|', $this->bparams);
250 // parts like: data, pages], 79], storage_pid]
251 $fieldPointerParts = explode('[', $fieldPointerString);
252 $relatingTableName = substr($fieldPointerParts[1], 0, -1);
253 $relatingFieldName = substr($fieldPointerParts[3], 0, -1);
254 if ($relatingTableName && $relatingFieldName) {
255 $dbList->setRelatingTableAndField($relatingTableName, $relatingFieldName);
256 }
257
258 $dbList->start(
259 $this->expandPage,
260 GeneralUtility::_GP('table'),
261 MathUtility::forceIntegerInRange(GeneralUtility::_GP('pointer'), 0, 100000),
262 GeneralUtility::_GP('search_field'),
263 GeneralUtility::_GP('search_levels'),
264 GeneralUtility::_GP('showLimit')
265 );
266
267 $dbList->setDispFields();
268 $dbList->generateList();
269
270 $out .= $dbList->getSearchBox();
271
272 // Add the HTML for the record list to output variable:
273 $out .= $dbList->HTMLcode;
274
275 // Add support for fieldselectbox in singleTableMode
276 if ($dbList->table) {
277 $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/FieldSelectBox');
278 $out .= $dbList->fieldSelectBox($dbList->table);
279 }
280
281 return $out;
282 }
283
284 /**
285 * @return string[] Array of body-tag attributes
286 */
287 protected function getBodyTagAttributes()
288 {
289 return [
290 'data-mode' => 'db'
291 ];
292 }
293
294 /**
295 * @param array $values Array of values to include into the parameters
296 * @return string[] Array of parameters which have to be added to URLs
297 */
298 public function getUrlParameters(array $values)
299 {
300 $pid = isset($values['pid']) ? $values['pid'] : $this->expandPage;
301 return [
302 'mode' => 'db',
303 'expandPage' => $pid,
304 'bparams' => $this->bparams
305 ];
306 }
307
308 /**
309 * @param array $values Values to be checked
310 * @return bool Returns TRUE if the given values match the currently selected item
311 */
312 public function isCurrentlySelectedItem(array $values)
313 {
314 return false;
315 }
316
317 /**
318 * Returns the URL of the current script
319 *
320 * @return string
321 */
322 public function getScriptUrl()
323 {
324 return $this->thisScript;
325 }
326 }