[TASK] Use strict comparison for strings
[Packages/TYPO3.CMS.git] / typo3 / sysext / version / Classes / Controller / VersionModuleController.php
1 <?php
2 namespace TYPO3\CMS\Version\Controller;
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\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Template\ModuleTemplate;
20 use TYPO3\CMS\Backend\Utility\BackendUtility;
21 use TYPO3\CMS\Core\Database\ConnectionPool;
22 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
23 use TYPO3\CMS\Core\Imaging\Icon;
24 use TYPO3\CMS\Core\Utility\ArrayUtility;
25 use TYPO3\CMS\Core\Utility\DiffUtility;
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27 use TYPO3\CMS\Lang\LanguageService;
28
29 /**
30 * Versioning module, including workspace management
31 */
32 class VersionModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClass
33 {
34 /**
35 * Module configuration
36 *
37 * @var array
38 */
39 public $MCONF = [];
40
41 /**
42 * Module menu items
43 *
44 * @var array
45 */
46 public $MOD_MENU = [];
47
48 /**
49 * Module session settings
50 *
51 * @var array
52 */
53 public $MOD_SETTINGS = [];
54
55 /**
56 * document template object
57 *
58 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
59 */
60 public $doc;
61
62 /**
63 * @var string
64 */
65 public $content;
66
67 /**
68 * Accumulated content
69 *
70 * @var int
71 */
72 public $showWorkspaceCol = 0;
73
74 /**
75 * @var array
76 */
77 public $formatWorkspace_cache = [];
78
79 /**
80 * @var array
81 */
82 public $formatCount_cache = [];
83
84 /**
85 * @var array
86 */
87 public $targets = [];
88
89 /**
90 * Accumulation of online targets.
91 *
92 * @var string
93 */
94 public $pageModule = '';
95
96 /**
97 * Name of page module
98 *
99 * @var bool
100 */
101 public $publishAccess = false;
102
103 /**
104 * @var array
105 */
106 public $stageIndex = [];
107
108 /**
109 * @var array
110 */
111 public $recIndex = [];
112
113 /**
114 * The name of the module
115 *
116 * @var string
117 */
118 protected $moduleName = 'web_txversionM1';
119
120 /**
121 * ModuleTemplate object
122 *
123 * @var ModuleTemplate
124 */
125 protected $moduleTemplate;
126
127 /**
128 * Initialize language files
129 */
130 public function __construct()
131 {
132 $GLOBALS['SOBE'] = $this;
133 $this->getLanguageService()->includeLLFile('EXT:version/Resources/Private/Language/locallang.xlf');
134 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
135 }
136
137 /**
138 * Initialize menu configuration
139 *
140 * @return void
141 */
142 public function menuConfig()
143 {
144 // CLEANSE SETTINGS
145 $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), $this->moduleName, 'ses');
146 }
147
148 /**
149 * Main function of the module. Write the content to $this->content
150 *
151 * @return void
152 */
153 public function main()
154 {
155 // Template markers
156 $markers = [
157 'CSH' => '',
158 'FUNC_MENU' => '',
159 'WS_MENU' => '',
160 'CONTENT' => ''
161 ];
162 // Setting module configuration:
163 $this->MCONF['name'] = $this->moduleName;
164 $this->REQUEST_URI = str_replace('&sendToReview=1', '', GeneralUtility::getIndpEnv('REQUEST_URI'));
165 // Draw the header.
166 $this->doc = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
167 $this->doc->setModuleTemplate('EXT:version/Resources/Private/Templates/version.html');
168
169 // Setting up the context sensitive menu:
170 $this->getPageRenderer()->loadJquery();
171 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ClickMenu');
172 // Getting input data:
173 $this->id = (int)GeneralUtility::_GP('id');
174
175 // Record uid. Goes with table name to indicate specific record
176 $this->uid = (int)GeneralUtility::_GP('uid');
177 // // Record table. Goes with uid to indicate specific record
178 $this->table = GeneralUtility::_GP('table');
179
180 $this->details = GeneralUtility::_GP('details');
181 // Page id. If set, indicates activation from Web>Versioning module
182 $this->diffOnly = GeneralUtility::_GP('diffOnly');
183 // Flag. If set, shows only the offline version and with diff-view
184 // Force this setting:
185 $this->MOD_SETTINGS['expandSubElements'] = true;
186 $this->MOD_SETTINGS['diff'] = $this->details || $this->MOD_SETTINGS['diff'] ? 1 : 0;
187 // Reading the record:
188 $record = BackendUtility::getRecord($this->table, $this->uid);
189 if ($record['pid'] == -1) {
190 $record = BackendUtility::getRecord($this->table, $record['t3ver_oid']);
191 }
192 $this->recordFound = is_array($record);
193 $pidValue = $this->table === 'pages' ? $this->uid : $record['pid'];
194 // Checking access etc.
195 if ($this->recordFound && $GLOBALS['TCA'][$this->table]['ctrl']['versioningWS'] && !$this->id) {
196 $this->uid = $record['uid'];
197 // Might have changed if new live record was found!
198 // Access check!
199 // The page will show only if there is a valid page and if this page may be viewed by the user
200 $this->pageinfo = BackendUtility::readPageAccess($pidValue, $this->perms_clause);
201 $access = is_array($this->pageinfo) ? 1 : 0;
202 if ($pidValue && $access || $GLOBALS['BE_USER']->user['admin'] && !$pidValue) {
203 // If another page module was specified, replace the default Page module with the new one
204 $newPageModule = trim($GLOBALS['BE_USER']->getTSConfigVal('options.overridePageModule'));
205 $this->pageModule = BackendUtility::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
206 // Setting publish access permission for workspace:
207 $this->publishAccess = $GLOBALS['BE_USER']->workspacePublishAccess($GLOBALS['BE_USER']->workspace);
208 $this->versioningMgm();
209 }
210 // Setting up the buttons and markers for docheader
211 $docHeaderButtons = $this->getButtons();
212 $markers['CSH'] = $docHeaderButtons['csh'];
213 $markers['FUNC_MENU'] = BackendUtility::getFuncMenu($this->id, 'SET[function]', $this->MOD_SETTINGS['function'], $this->MOD_MENU['function']);
214 $markers['CONTENT'] = $this->content;
215 } else {
216 // If no access or id value, create empty document
217 $this->content = '<h2>' . htmlspecialchars($this->getLanguageService()->getLL('clickAPage_header')) . '</h2><div>' . $this->getLanguageService()->getLL('clickAPage_content') . '</div>';
218 // Setting up the buttons and markers for docheader
219 $docHeaderButtons = $this->getButtons();
220 $markers['CONTENT'] = $this->content;
221 }
222 // Build the <body> for the module
223 $this->content = $this->doc->startPage($this->getLanguageService()->getLL('title'));
224 $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
225 $this->content .= $this->doc->endPage();
226 $this->content = $this->doc->insertStylesAndJS($this->content);
227 }
228
229 /**
230 * Create the panel of buttons for submitting the form or otherwise perform operations.
231 *
232 * @return array All available buttons as an assoc. array
233 */
234 protected function getButtons()
235 {
236 $buttons = [
237 'csh' => '',
238 'view' => '',
239 'record_list' => '',
240 'shortcut' => ''
241 ];
242 // CSH
243 if ($this->recordFound && $GLOBALS['TCA'][$this->table]['ctrl']['versioningWS']) {
244 // View page
245 $buttons['view'] = '
246 <a href="#" onclick="' . htmlspecialchars(BackendUtility::viewOnClick($this->pageinfo['uid'], '', BackendUtility::BEgetRootLine($this->pageinfo['uid']))) . '" title="' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.showPage')) . '">
247 ' . $this->moduleTemplate->getIconFactory()->getIcon('actions-document-view', Icon::SIZE_SMALL)->render() . '
248 </a>';
249 // Shortcut
250 if ($GLOBALS['BE_USER']->mayMakeShortcut()) {
251 $buttons['shortcut'] = $this->doc->makeShortcutIcon('id, edit_record, pointer, new_unique_uid, search_field, search_levels, showLimit', implode(',', array_keys($this->MOD_MENU)), $this->moduleName);
252 }
253 // If access to Web>List for user, then link to that module.
254 $buttons['record_list'] = '<a href="' . htmlspecialchars(BackendUtility::getModuleUrl(
255 'web_list',
256 [
257 'id' => $this->pageinfo['uid'],
258 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
259 ]
260 )) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-system-list-open', Icon::SIZE_SMALL)->render() . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.showList')) . '</a>';
261 }
262 return $buttons;
263 }
264
265 /******************************
266 *
267 * Versioning management
268 *
269 ******************************/
270 /**
271 * Management of versions for record
272 *
273 * @return void
274 */
275 public function versioningMgm()
276 {
277 $lang = $this->getLanguageService();
278 // Diffing:
279 $diff_1 = GeneralUtility::_POST('diff_1');
280 $diff_2 = GeneralUtility::_POST('diff_2');
281 if (GeneralUtility::_POST('do_diff')) {
282 $content = '';
283 $content .= '<div class="panel panel-space panel-default">';
284 $content .= '<div class="panel-heading">' . $lang->getLL('diffing') . '</div>';
285 if ($diff_1 && $diff_2) {
286 $diff_1_record = BackendUtility::getRecord($this->table, $diff_1);
287 $diff_2_record = BackendUtility::getRecord($this->table, $diff_2);
288 if (is_array($diff_1_record) && is_array($diff_2_record)) {
289 $diffUtility = GeneralUtility::makeInstance(DiffUtility::class);
290 $diffUtility->stripTags = false;
291 $rows = [];
292 $rows[] = '
293 <tr>
294 <th>' . $lang->getLL('fieldname') . '</th>
295 <th width="98%">' . $lang->getLL('coloredDiffView') . ':</th>
296 </tr>
297 ';
298 foreach ($diff_1_record as $fN => $fV) {
299 if ($GLOBALS['TCA'][$this->table]['columns'][$fN] && $GLOBALS['TCA'][$this->table]['columns'][$fN]['config']['type'] !== 'passthrough' && $fN !== 't3ver_label') {
300 if ((string)$diff_1_record[$fN] !== (string)$diff_2_record[$fN]) {
301 $diffres = $diffUtility->makeDiffDisplay(
302 BackendUtility::getProcessedValue($this->table, $fN, $diff_2_record[$fN], 0, 1),
303 BackendUtility::getProcessedValue($this->table, $fN, $diff_1_record[$fN], 0, 1)
304 );
305 $rows[] = '
306 <tr>
307 <td>' . $fN . '</td>
308 <td width="98%">' . $diffres . '</td>
309 </tr>
310 ';
311 }
312 }
313 }
314 if (count($rows) > 1) {
315 $content .= '<div class="table-fit"><table class="table">' . implode('', $rows) . '</table></div>';
316 } else {
317 $content .= '<div class="panel-body">' . $lang->getLL('recordsMatchesCompletely') . '</div>';
318 }
319 } else {
320 $content .= '<div class="panel-body">' . $lang->getLL('errorRecordsNotFound') . '</div>';
321 }
322 } else {
323 $content .= '<div class="panel-body">' . $lang->getLL('errorDiffSources') . '</div>';
324 }
325 $content .= '</div>';
326 }
327 // Element:
328 $record = BackendUtility::getRecord($this->table, $this->uid);
329 $recTitle = BackendUtility::getRecordTitle($this->table, $record, true);
330 // Display versions:
331 $content .= '
332 <form name="theform" action="' . str_replace('&sendToReview=1', '', $this->REQUEST_URI) . '" method="post">
333 <div class="panel panel-space panel-default">
334 <div class="panel-heading">' . $recTitle . '</div>
335 <div class="table-fit">
336 <table class="table">
337 <thead>
338 <tr>
339 <th colspan="2" class="col-icon"></th>
340 <th title="' . $lang->getLL('tblHeaderDesc_title') . '">' . $lang->getLL('tblHeader_title') . '</th>
341 <th title="' . $lang->getLL('tblHeaderDesc_uid') . '"><i>' . $lang->getLL('tblHeader_uid') . '</i></th>
342 <th title="' . $lang->getLL('tblHeaderDesc_t3ver_oid') . '"><i>' . $lang->getLL('tblHeader_t3ver_oid') . '</i></th>
343 <th title="' . $lang->getLL('tblHeaderDesc_t3ver_id') . '"><i>' . $lang->getLL('tblHeader_t3ver_id') . '</i></th>
344 <th title="' . $lang->getLL('tblHeaderDesc_t3ver_wsid') . '"><i>' . $lang->getLL('tblHeader_t3ver_wsid') . '</i></th>
345 <th title="' . htmlspecialchars($lang->getLL('tblHeaderDesc_t3ver_state')) . '"><i>' . $lang->getLL('tblHeader_t3ver_state') . '</i></th>
346 <th title="' . $lang->getLL('tblHeaderDesc_t3ver_stage') . '"><i>' . $lang->getLL('tblHeader_t3ver_stage') . '</i></th>
347 <th title="' . $lang->getLL('tblHeaderDesc_t3ver_count') . '"><i>' . $lang->getLL('tblHeader_t3ver_count') . '</i></th>
348 <th title="' . $lang->getLL('tblHeaderDesc_pid') . '"><i>' . $lang->getLL('tblHeader_pid') . '</i></th>
349 <th title="' . $lang->getLL('tblHeaderDesc_t3ver_label') . '"><i>' . $lang->getLL('tblHeader_t3ver_label') . '</i></th>
350 <th></th>
351 <th colspan="2">
352 <button class="btn btn-default btn-sm" type="submit" name="do_diff" value="true">
353 ' . $lang->getLL('diff') . '
354 </button>
355 </th>
356 </tr>
357 </thead>
358 <tbody>
359 ';
360 $versions = BackendUtility::selectVersionsOfRecord($this->table, $this->uid, '*', $GLOBALS['BE_USER']->workspace);
361 foreach ($versions as $row) {
362 $adminLinks = $this->adminLinks($this->table, $row);
363
364 $editUrl = BackendUtility::getModuleUrl('record_edit', [
365 'edit' => [
366 $this->table => [
367 $row['uid'] => 'edit'
368 ]
369 ],
370 'columnsOnly' => 't3ver_label',
371 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
372 ]);
373 $content .= '
374 <tr' . ($row['uid'] != $this->uid ? '' : ' class="active"') . '>
375 <td class="col-icon">' .
376 ($row['uid'] != $this->uid ?
377 '<a href="' . BackendUtility::getLinkToDataHandlerAction('&cmd[' . $this->table . '][' . $this->uid . '][version][swapWith]=' . $row['uid'] . '&cmd[' . $this->table . '][' . $this->uid . '][version][action]=swap') . '" title="' . htmlspecialchars($lang->getLL('swapWithCurrent')) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-version-swap-version', Icon::SIZE_SMALL)->render() . '</a>' :
378 '<span title="' . htmlspecialchars($lang->getLL('currentOnlineVersion')) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('status-status-current', Icon::SIZE_SMALL)->render() . '</span>'
379 ) . '
380 </td>
381 <td class="col-icon">' . $this->moduleTemplate->getIconFactory()->getIconForRecord($this->table, $row, Icon::SIZE_SMALL)->render() . '</td>
382 <td>' . BackendUtility::getRecordTitle($this->table, $row, true) . '</td>
383 <td>' . $row['uid'] . '</td>
384 <td>' . $row['t3ver_oid'] . '</td>
385 <td>' . $row['t3ver_id'] . '</td>
386 <td>' . $row['t3ver_wsid'] . '</td>
387 <td>' . $row['t3ver_state'] . '</td>
388 <td>' . $row['t3ver_stage'] . '</td>
389 <td>' . $row['t3ver_count'] . '</td>
390 <td>' . $row['pid'] . '</td>
391 <td>
392 <a href="' . htmlspecialchars($editUrl) . '" title="' . htmlspecialchars($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.edit')) . '">
393 ' . $this->moduleTemplate->getIconFactory()->getIcon('actions-open', Icon::SIZE_SMALL)->render() . '
394 </a>' . htmlspecialchars($row['t3ver_label']) . '
395 </td>
396 <td class="col-control">' . $adminLinks . '</td>
397 <td class="text-center success"><input type="radio" name="diff_1" value="' . $row['uid'] . '"' . ($diff_1 == $row['uid'] ? ' checked="checked"' : '') . '/></td>
398 <td class="text-center danger"><input type="radio" name="diff_2" value="' . $row['uid'] . '"' . ($diff_2 == $row['uid'] ? ' checked="checked"' : '') . '/></td>
399 </tr>';
400 // Show sub-content if the table is pages AND it is not the online branch (because that will mostly render the WHOLE tree below - not smart;)
401 if ($this->table === 'pages' && $row['uid'] != $this->uid) {
402 $sub = $this->pageSubContent($row['uid']);
403 if ($sub) {
404 $content .= '
405 <tr>
406 <td colspan="2"></td>
407 <td colspan="11">' . $sub . '</td>
408 <td class="success"></td>
409 <td class="danger"></td>
410 </tr>';
411 }
412 }
413 }
414 $content .= '
415 </tbody>
416 </table>
417 </div>
418 </div>
419 </form>';
420 $this->content .= '<h2>' . htmlspecialchars($lang->getLL('title')) . '</h2><div>' . $content . '</div>';
421 // Create new:
422 $content = '
423 <form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_db')) . '" method="post">
424 <div class="row">
425 <div class="col-sm-6 col-md-4 col-lg-3">
426 <div class="form-group">
427 <label for="typo3-new-version-label">' . $lang->getLL('tblHeader_t3ver_label') . '</label>
428 <input id="typo3-new-version-label" class="form-control" type="text" name="cmd[' . $this->table . '][' . $this->uid . '][version][label]" />
429 </div>
430 <div class="form-group">
431 <input type="hidden" name="cmd[' . $this->table . '][' . $this->uid . '][version][action]" value="new" />
432 <input type="hidden" name="prErr" value="1" />
433 <input type="hidden" name="redirect" value="' . htmlspecialchars($this->REQUEST_URI) . '" />
434 <input class="btn btn-default" type="submit" name="_" value="' . $lang->getLL('createNewVersion') . '" />
435 </div>
436 </div>
437 </div>
438 </form>
439
440 ';
441 $this->content .= '<h2>' . htmlspecialchars($lang->getLL('createNewVersion')) . '</h2><div>' . $content . '</div>';
442 }
443
444 /**
445 * Recursively look for children for page version with $pid
446 *
447 * @param int $pid UID of page record for which to look up sub-elements following that version
448 * @param int $c Counter, do not set (limits to 100 levels)
449 * @return string Table with content if any
450 */
451 public function pageSubContent($pid, $c = 0)
452 {
453 $tableNames = ArrayUtility::removeArrayEntryByValue(array_keys($GLOBALS['TCA']), 'pages');
454 $tableNames[] = 'pages';
455 $content = '';
456 foreach ($tableNames as $table) {
457 // Basically list ALL tables - not only those being copied might be found!
458 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
459 ->getQueryBuilderForTable($table);
460 $queryBuilder->getRestrictions()
461 ->removeAll()
462 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
463
464 $queryBuilder
465 ->select('*')
466 ->from($table)
467 ->where(
468 $queryBuilder->expr()->eq(
469 'pid',
470 $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT)
471 )
472 );
473
474 if (!empty($GLOBALS['TCA'][$table]['ctrl']['sortby'])) {
475 $queryBuilder->orderBy($GLOBALS['TCA'][$table]['ctrl']['sortby']);
476 }
477
478 $result = $queryBuilder->execute();
479 if ($result->rowCount()) {
480 $content .= '
481 <table class="table">
482 <tr>
483 <th class="col-icon">' . $this->moduleTemplate->getIconFactory()->getIconForRecord($table, [], Icon::SIZE_SMALL)->render() . '</th>
484 <th class="col-title">' . htmlspecialchars($this->getLanguageService()->sL($GLOBALS['TCA'][$table]['ctrl']['title'])) . '</th>
485 <th></th>
486 <th></th>
487 </tr>';
488 while ($subrow = $result->fetch()) {
489 $ownVer = $this->lookForOwnVersions($table, $subrow['uid']);
490 $content .= '
491 <tr>
492 <td class="col-icon">' . $this->moduleTemplate->getIconFactory()->getIconForRecord($table, $subrow, Icon::SIZE_SMALL)->render() . '</td>
493 <td class="col-title">' . BackendUtility::getRecordTitle($table, $subrow, true) . '</td>
494 <td>' . ($ownVer > 1 ? '<a href="' . htmlspecialchars(BackendUtility::getModuleUrl('web_txversionM1', ['table' => $table, 'uid' => $subrow['uid']])) . '">' . ($ownVer - 1) . '</a>' : '') . '</td>
495 <td class="col-control">' . $this->adminLinks($table, $subrow) . '</td>
496 </tr>';
497 if ($table === 'pages' && $c < 100) {
498 $sub = $this->pageSubContent($subrow['uid'], $c + 1);
499 if ($sub) {
500 $content .= '
501 <tr>
502 <td></td>
503 <td></td>
504 <td></td>
505 <td width="98%">' . $sub . '</td>
506 </tr>';
507 }
508 }
509 }
510 $content .= '</table>';
511 }
512 }
513 return $content;
514 }
515
516 /**
517 * Look for number of versions of a record
518 *
519 * @param string $table Table name
520 * @param int $uid Record uid
521 * @return int Number of versions for record, FALSE if none.
522 */
523 public function lookForOwnVersions($table, $uid)
524 {
525 $versions = BackendUtility::selectVersionsOfRecord($table, $uid, 'uid', null);
526 if (is_array($versions)) {
527 return count($versions);
528 }
529 return false;
530 }
531
532 /**
533 * Administrative links for a table / record
534 *
535 * @param string $table Table name
536 * @param array $row Record for which administrative links are generated.
537 * @return string HTML link tags.
538 */
539 public function adminLinks($table, $row)
540 {
541 // Edit link:
542 $editUrl = BackendUtility::getModuleUrl('record_edit', [
543 'edit' => [
544 $table => [
545 $row['uid'] => 'edit'
546 ]
547 ],
548 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
549 ]);
550 $adminLink = '<div class="btn-group btn-group-sm" role="group">';
551 $adminLink .= '<a class="btn btn-default" href="' . htmlspecialchars($editUrl) . '" title="' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.edit')) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-open', Icon::SIZE_SMALL)->render() . '</a>';
552 // Delete link:
553 $adminLink .= '<a class="btn btn-default" href="' . htmlspecialchars(BackendUtility::getLinkToDataHandlerAction('&cmd[' . $table . '][' . $row['uid'] . '][delete]=1')) . '" title="' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.delete')) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render() . '</a>';
554 $adminLink .= '</div>';
555 if ($table === 'pages') {
556 // If another page module was specified, replace the default Page module with the new one
557 $newPageModule = trim($GLOBALS['BE_USER']->getTSConfigVal('options.overridePageModule'));
558 $pageModule = BackendUtility::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
559 $adminLink .= '<div class="btn-group btn-group-sm">';
560 $adminLink .= '<a class="btn btn-default" href="#" onclick="top.loadEditId(' . $row['uid'] . ');top.goToModule(' . GeneralUtility::quoteJSvalue($pageModule) . '); return false;">'
561 . $this->moduleTemplate->getIconFactory()->getIcon('actions-page-open', Icon::SIZE_SMALL)->render()
562 . '</a>';
563 $adminLink .= '<a class="btn btn-default" href="#" onclick="top.loadEditId(' . $row['uid'] . ');top.goToModule(\'web_list\'); return false;">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-system-list-open', Icon::SIZE_SMALL)->render() . '</a>';
564 // "View page" icon is added:
565 $adminLink .= '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars(BackendUtility::viewOnClick($row['uid'], '', BackendUtility::BEgetRootLine($row['uid']))) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-document-view', Icon::SIZE_SMALL)->render() . '</a>';
566 $adminLink .= '</div>';
567 } else {
568 if ($row['pid'] == -1) {
569 $getVars = '&ADMCMD_vPrev[' . rawurlencode(($table . ':' . $row['t3ver_oid'])) . ']=' . $row['uid'];
570 // "View page" icon is added:
571 $adminLink .= '<div class="btn-group btn-group-sm" role="group"><a class="btn btn-default" href="#" onclick="' . htmlspecialchars(BackendUtility::viewOnClick($row['_REAL_PID'], '', BackendUtility::BEgetRootLine($row['_REAL_PID']), '', '', $getVars)) . '">' . $this->moduleTemplate->getIconFactory()->getIcon('actions-document-view', Icon::SIZE_SMALL)->render() . '</a></div>';
572 }
573 }
574 return $adminLink;
575 }
576
577 /**
578 * Injects the request object for the current request and gathers all data.
579 *
580 * @param ServerRequestInterface $request the current request
581 * @param ResponseInterface $response the prepared response
582 * @return ResponseInterface the response with the content
583 */
584 public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
585 {
586 $this->init();
587 $this->main();
588
589 $response->getBody()->write($this->content);
590 return $response;
591 }
592
593 /**
594 * @return LanguageService
595 */
596 protected function getLanguageService()
597 {
598 return $GLOBALS['LANG'];
599 }
600 }