[TASK] Remove documentTemplate sections at ElementInformationController
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / ContentElement / ElementInformationController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller\ContentElement;
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 Psr\Http\Message\ResponseInterface;
19 use TYPO3\CMS\Backend\Utility\BackendUtility;
20 use TYPO3\CMS\Core\Imaging\Icon;
21 use TYPO3\CMS\Core\Imaging\IconFactory;
22 use TYPO3\CMS\Core\Resource\Folder;
23 use TYPO3\CMS\Core\Resource\ProcessedFile;
24 use TYPO3\CMS\Core\Resource\ResourceFactory;
25 use TYPO3\CMS\Core\Utility\GeneralUtility;
26 use TYPO3\CMS\Backend\Backend\Avatar\Avatar;
27
28 /**
29 * Script Class for showing information about an item.
30 */
31 class ElementInformationController
32 {
33 /**
34 * Record table name
35 *
36 * @var string
37 */
38 public $table;
39
40 /**
41 * Record uid
42 *
43 * @var int
44 */
45 public $uid;
46
47 /**
48 * @var string
49 */
50 protected $permsClause;
51
52 /**
53 * @var bool
54 */
55 public $access = false;
56
57 /**
58 * Which type of element:
59 * - "file"
60 * - "db"
61 *
62 * @var string
63 */
64 public $type = '';
65
66 /**
67 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
68 */
69 public $doc;
70
71 /**
72 * @var string
73 */
74 protected $content = '';
75
76 /**
77 * For type "db": Set to page record of the parent page of the item set
78 * (if type="db")
79 *
80 * @var array
81 */
82 public $pageInfo;
83
84 /**
85 * Database records identified by table/uid
86 *
87 * @var array
88 */
89 protected $row;
90
91 /**
92 * @var \TYPO3\CMS\Core\Resource\File
93 */
94 protected $fileObject;
95
96 /**
97 * @var Folder
98 */
99 protected $folderObject;
100
101 /**
102 * The HTML title tag
103 *
104 * @var string
105 */
106 protected $titleTag;
107
108 /**
109 * @var IconFactory
110 */
111 protected $iconFactory;
112
113 /**
114 * Constructor
115 */
116 public function __construct()
117 {
118 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
119 $GLOBALS['SOBE'] = $this;
120
121 $this->init();
122 }
123
124 /**
125 * Determines if table/uid point to database record or file and
126 * if user has access to view information
127 *
128 * @return void
129 */
130 public function init()
131 {
132 $this->table = GeneralUtility::_GET('table');
133 $this->uid = GeneralUtility::_GET('uid');
134
135 $this->permsClause = $this->getBackendUser()->getPagePermsClause(1);
136 $this->doc = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
137 $this->doc->divClass = 'container';
138
139 if (isset($GLOBALS['TCA'][$this->table])) {
140 $this->initDatabaseRecord();
141 } elseif ($this->table == '_FILE' || $this->table == '_FOLDER' || $this->table == 'sys_file') {
142 $this->initFileOrFolderRecord();
143 }
144 }
145
146 /**
147 * Init database records (table)
148 */
149 protected function initDatabaseRecord()
150 {
151 $this->type = 'db';
152 $this->uid = (int)$this->uid;
153
154 // Check permissions and uid value:
155 if ($this->uid && $this->getBackendUser()->check('tables_select', $this->table)) {
156 if ((string)$this->table == 'pages') {
157 $this->pageInfo = BackendUtility::readPageAccess($this->uid, $this->permsClause);
158 $this->access = is_array($this->pageInfo) ? 1 : 0;
159 $this->row = $this->pageInfo;
160 } else {
161 $this->row = BackendUtility::getRecordWSOL($this->table, $this->uid);
162 if ($this->row) {
163 $this->pageInfo = BackendUtility::readPageAccess($this->row['pid'], $this->permsClause);
164 $this->access = is_array($this->pageInfo) ? 1 : 0;
165 }
166 }
167 }
168 }
169
170 /**
171 * Init file/folder parameters
172 */
173 protected function initFileOrFolderRecord()
174 {
175 $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->uid);
176
177 if ($fileOrFolderObject instanceof Folder) {
178 $this->folderObject = $fileOrFolderObject;
179 $this->access = $this->folderObject->checkActionPermission('read');
180 $this->type = 'folder';
181 } else {
182 $this->fileObject = $fileOrFolderObject;
183 $this->access = $this->fileObject->checkActionPermission('read');
184 $this->type = 'file';
185 $this->table = 'sys_file';
186
187 try {
188 $this->row = BackendUtility::getRecordWSOL($this->table, $fileOrFolderObject->getUid());
189 } catch (\Exception $e) {
190 $this->row = array();
191 }
192 }
193 }
194
195 /**
196 * Injects the request object for the current request or subrequest
197 * As this controller goes only through the main() method, it is rather simple for now
198 *
199 * @param ServerRequestInterface $request the current request
200 * @param ResponseInterface $response
201 * @return ResponseInterface the response with the content
202 */
203 public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
204 {
205 $this->main();
206
207 $content = $this->doc->startPage($this->titleTag);
208 $content .= $this->doc->insertStylesAndJS($this->content);
209 $content .= $this->doc->endPage();
210
211 $response->getBody()->write($content);
212 return $response;
213 }
214
215 /**
216 * @return void
217 */
218 public function main()
219 {
220 if (!$this->access) {
221 return;
222 }
223
224 // render type by user func
225 $typeRendered = false;
226 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/show_item.php']['typeRendering'])) {
227 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/show_item.php']['typeRendering'] as $classRef) {
228 $typeRenderObj = GeneralUtility::getUserObj($classRef);
229 // @todo should have an interface
230 if (is_object($typeRenderObj) && method_exists($typeRenderObj, 'isValid') && method_exists($typeRenderObj, 'render')) {
231 if ($typeRenderObj->isValid($this->type, $this)) {
232 $this->content .= $typeRenderObj->render($this->type, $this);
233 $typeRendered = true;
234 break;
235 }
236 }
237 }
238 }
239
240 if (!$typeRendered) {
241 $this->content .= $this->renderPageTitle();
242 $this->content .= $this->renderPreview();
243 $this->content .= $this->renderPropertiesAsTable();
244 $this->content .= $this->renderReferences();
245 $this->content .= $this->renderBackButton();
246 }
247 }
248
249 /**
250 * Render page title with icon, table title and record title
251 *
252 * @return string
253 */
254 protected function renderPageTitle()
255 {
256 if ($this->type === 'folder') {
257 $table = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:folder');
258 $title = $this->doc->getResourceHeader($this->folderObject, array(' ', ''), false);
259 } elseif ($this->type === 'file') {
260 $table = $this->getLanguageService()->sL($GLOBALS['TCA'][$this->table]['ctrl']['title']);
261 $title = $this->doc->getResourceHeader($this->fileObject, array(' ', ''), false);
262 } else {
263 $table = $this->getLanguageService()->sL($GLOBALS['TCA'][$this->table]['ctrl']['title']);
264 $title = $this->doc->getHeader($this->table, $this->row, $this->pageInfo['_thePath'], 1, array(' ', ''), false);
265 }
266 // Set HTML title tag
267 $this->titleTag = $table . ': ' . strip_tags(BackendUtility::getRecordTitle($this->table, $this->row));
268 return '<h1>' .
269 ($table ? '<small>' . $table . '</small><br />' : '') .
270 $title .
271 '</h1>';
272 }
273
274 /**
275 * Render preview for current record
276 *
277 * @return string
278 */
279 protected function renderPreview()
280 {
281 // Perhaps @todo in future: Also display preview for records - without fileObject
282 if (!$this->fileObject) {
283 return '';
284 }
285
286 $previewTag = '';
287 $showLink = '';
288
289 // check if file is marked as missing
290 if ($this->fileObject->isMissing()) {
291 $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($this->fileObject);
292 $previewTag .= $flashMessage->render();
293 } else {
294
295 /** @var \TYPO3\CMS\Core\Resource\Rendering\RendererRegistry $rendererRegistry */
296 $rendererRegistry = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Rendering\RendererRegistry::class);
297 $fileRenderer = $rendererRegistry->getRenderer($this->fileObject);
298 $fileExtension = $this->fileObject->getExtension();
299 $url = $this->fileObject->getPublicUrl(true);
300
301 // Check if there is a FileRenderer
302 if ($fileRenderer !== null) {
303 $previewTag = $fileRenderer->render(
304 $this->fileObject,
305 '590m',
306 '400m',
307 array(),
308 true
309 );
310
311 // else check if we can create an Image preview
312 } elseif (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileExtension)) {
313 $processedFile = $this->fileObject->process(
314 ProcessedFile::CONTEXT_IMAGEPREVIEW,
315 array(
316 'width' => '590m',
317 'height' => '400m'
318 )
319 );
320 // Create thumbnail image?
321 if ($processedFile) {
322 $thumbUrl = $processedFile->getPublicUrl(true);
323 $previewTag .= '<img class="img-responsive img-thumbnail" src="' . $thumbUrl . '" ' .
324 'width="' . $processedFile->getProperty('width') . '" ' .
325 'height="' . $processedFile->getProperty('height') . '" ' .
326 'alt="' . htmlspecialchars(trim($this->fileObject->getName())) . '" ' .
327 'title="' . htmlspecialchars(trim($this->fileObject->getName())) . '" />';
328 }
329 }
330
331 // Show
332 if ($url) {
333 $showLink .= '
334 <a class="btn btn-primary" href="' . htmlspecialchars($url) . '" target="_blank">
335 ' . $this->iconFactory->getIcon('actions-document-view', Icon::SIZE_SMALL)->render() . '
336 ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.show', true) . '
337 </a>';
338 }
339 }
340
341 return ($previewTag ? '<p>' . $previewTag . '</p>' : '') .
342 ($showLink ? '<p>' . $showLink . '</p>' : '');
343 }
344
345 /**
346 * Render property array as html table
347 *
348 * @return string
349 */
350 protected function renderPropertiesAsTable()
351 {
352 $tableRows = array();
353 $extraFields = array();
354
355 $lang = $this->getLanguageService();
356 if (in_array($this->type, array('folder', 'file'), true)) {
357 if ($this->type === 'file') {
358 $extraFields['creation_date'] = $lang->sL('LLL:EXT:lang/locallang_general.xlf:LGL.creationDate', true);
359 $extraFields['modification_date'] = $lang->sL('LLL:EXT:lang/locallang_general.xlf:LGL.timestamp', true);
360 }
361 $extraFields['storage'] = $lang->sL('LLL:EXT:lang/locallang_tca.xlf:sys_file.storage', true);
362 $extraFields['folder'] = $lang->sL('LLL:EXT:lang/locallang_common.xlf:folder', true);
363 } else {
364 $extraFields['crdate'] = $lang->sL('LLL:EXT:lang/locallang_general.xlf:LGL.creationDate', true);
365 $extraFields['cruser_id'] = $lang->sL('LLL:EXT:lang/locallang_general.xlf:LGL.creationUserId', true);
366 $extraFields['tstamp'] = $lang->sL('LLL:EXT:lang/locallang_general.xlf:LGL.timestamp', true);
367
368 // check if the special fields are defined in the TCA ctrl section of the table
369 foreach ($extraFields as $fieldName => $fieldLabel) {
370 if (isset($GLOBALS['TCA'][$this->table]['ctrl'][$fieldName])) {
371 $extraFields[$GLOBALS['TCA'][$this->table]['ctrl'][$fieldName]] = $fieldLabel;
372 } else {
373 unset($extraFields[$fieldName]);
374 }
375 }
376 }
377
378 foreach ($extraFields as $name => $fieldLabel) {
379 $rowValue = '';
380 if (!isset($this->row[$name])) {
381 $resourceObject = $this->fileObject ?: $this->folderObject;
382 if ($name === 'storage') {
383 $rowValue = $resourceObject->getStorage()->getName();
384 } elseif ($name === 'folder') {
385 $rowValue = $resourceObject->getParentFolder()->getReadablePath();
386 }
387 } elseif (in_array($name, array('creation_date', 'modification_date'), true)) {
388 $rowValue = BackendUtility::datetime($this->row[$name]);
389 } else {
390 $rowValue = BackendUtility::getProcessedValueExtra($this->table, $name, $this->row[$name]);
391 }
392 // show the backend username who created the issue
393 if ($name === 'cruser_id' && $rowValue) {
394 $creatorRecord = BackendUtility::getRecord('be_users', $rowValue);
395 if ($creatorRecord) {
396 /** @var Avatar $avatar */
397 $avatar = GeneralUtility::makeInstance(Avatar::class);
398 $icon = $avatar->render($creatorRecord);
399 $rowValue = '
400 <div class="media">
401 <div class="media-left">
402 ' . $icon . '
403 </div>
404 <div class="media-body">
405 <strong>' . htmlspecialchars($GLOBALS['BE_USER']->user['username']) . '</strong><br>
406 ' . ($GLOBALS['BE_USER']->user['realName'] ? htmlspecialchars($GLOBALS['BE_USER']->user['realName']) : '') . '
407 </div>
408 </div>';
409 }
410 }
411
412 $tableRows[] = '
413 <tr>
414 <th class="col-nowrap">' . rtrim($fieldLabel, ':') . '</th>
415 <td>' . ($name === 'cruser_id' ? $rowValue : htmlspecialchars($rowValue)) . '</td>
416 </tr>';
417 }
418
419 // Traverse the list of fields to display for the record:
420 $fieldList = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$this->table]['interface']['showRecordFieldList'], true);
421 foreach ($fieldList as $name) {
422 $name = trim($name);
423 $uid = $this->row['uid'];
424
425 if (!isset($GLOBALS['TCA'][$this->table]['columns'][$name])) {
426 continue;
427 }
428
429 // Storage is already handled above
430 if ($this->type === 'file' && $name === 'storage') {
431 continue;
432 }
433
434 $isExcluded = !(!$GLOBALS['TCA'][$this->table]['columns'][$name]['exclude'] || $this->getBackendUser()->check('non_exclude_fields', $this->table . ':' . $name));
435 if ($isExcluded) {
436 continue;
437 }
438
439 $itemValue = BackendUtility::getProcessedValue($this->table, $name, $this->row[$name], 0, 0, false, $uid);
440 $itemLabel = $lang->sL(BackendUtility::getItemLabel($this->table, $name), true);
441 $tableRows[] = '
442 <tr>
443 <th class="col-nowrap">' . $itemLabel . '</th>
444 <td>' . htmlspecialchars($itemValue) . '</td>
445 </tr>';
446 }
447
448 return '
449 <div class="table-fit table-fit-wrap">
450 <table class="table table-striped table-hover">
451 ' . implode('', $tableRows) . '
452 </table>
453 </div>';
454 }
455
456 /**
457 * Render references section (references from and references to current record)
458 *
459 * @return string
460 */
461 protected function renderReferences()
462 {
463 $content = '';
464
465 switch ($this->type) {
466 case 'db': {
467 $references = $this->makeRef($this->table, $this->row['uid']);
468 if (!empty($references)) {
469 $content .= '<h3>' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.referencesToThisItem', true) . '</h3>';
470 $content .= $references;
471 }
472
473 $referencesFrom = $this->makeRefFrom($this->table, $this->row['uid']);
474 if (!empty($referencesFrom)) {
475 $content .= '<h3>' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.referencesFromThisItem', true) . '</h3>';
476 $content .= $referencesFrom;
477 }
478 break;
479 }
480
481 case 'file': {
482 if ($this->fileObject && $this->fileObject->isIndexed()) {
483 $references = $this->makeRef('_FILE', $this->fileObject);
484
485 if (!empty($references)) {
486 $content .= '<h3>' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.referencesToThisItem', true) . '</h3>';
487 $content .= $references;
488 }
489 }
490 break;
491 }
492 }
493
494 return $content;
495 }
496
497 /**
498 * Render a back button, if a returnUrl was provided
499 *
500 * @return string
501 */
502 protected function renderBackButton()
503 {
504 $backLink = '';
505 $returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GET('returnUrl'));
506 if ($returnUrl) {
507 $backLink .= '
508 <a class="btn btn-primary" href="' . htmlspecialchars($returnUrl) . '>
509 ' . $this->iconFactory->getIcon('actions-view-go-back', Icon::SIZE_SMALL)->render() . '
510 ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:back', true) . '
511 </a>';
512 }
513 return $backLink;
514 }
515
516 /**
517 * Renders file properties as html table
518 *
519 * @param array $fieldList
520 * @return string
521 */
522 protected function renderFileInformationAsTable($fieldList)
523 {
524 $tableRows = array();
525 foreach ($fieldList as $name) {
526 if (!isset($GLOBALS['TCA'][$this->table]['columns'][$name])) {
527 continue;
528 }
529 $isExcluded = !(!$GLOBALS['TCA'][$this->table]['columns'][$name]['exclude'] || $this->getBackendUser()->check('non_exclude_fields', $this->table . ':' . $name));
530 if ($isExcluded) {
531 continue;
532 }
533 $uid = $this->row['uid'];
534 $itemValue = BackendUtility::getProcessedValue($this->table, $name, $this->row[$name], 0, 0, false, $uid);
535 $itemLabel = $this->getLanguageService()->sL(BackendUtility::getItemLabel($this->table, $name), true);
536 $tableRows[] = '
537 <tr>
538 <th>' . $itemLabel . '</th>
539 <td>' . htmlspecialchars($itemValue) . '</td>
540 </tr>';
541 }
542
543 if (!$tableRows) {
544 return '';
545 }
546
547 return '
548 <div class="table-fit table-fit-wrap">
549 <table class="table table-striped table-hover">
550 ' . implode('', $tableRows) . '
551 </table>
552 </div>';
553 }
554
555 /**
556 * End page and print content
557 *
558 * @return void
559 * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8, use mainAction() instead
560 */
561 public function printContent()
562 {
563 GeneralUtility::logDeprecatedFunction();
564 echo $this->doc->startPage($this->titleTag) .
565 $this->doc->insertStylesAndJS($this->content) .
566 $this->doc->endPage();
567 }
568
569 /**
570 * Get field name for specified table/column name
571 *
572 * @param string $tableName Table name
573 * @param string $fieldName Column name
574 * @return string label
575 */
576 public function getLabelForTableColumn($tableName, $fieldName)
577 {
578 if ($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label'] !== null) {
579 $field = $this->getLanguageService()->sL($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label']);
580 if (trim($field) === '') {
581 $field = $fieldName;
582 }
583 } else {
584 $field = $fieldName;
585 }
586 return $field;
587 }
588
589 /**
590 * Returns the rendered record actions
591 *
592 * @param string $table
593 * @param int $uid
594 * @return string
595 */
596 protected function getRecordActions($table, $uid)
597 {
598 if ($table === '' || $uid < 0) {
599 return '';
600 }
601
602 // Edit button
603 $urlParameters = [
604 'edit' => [
605 $table => [
606 $uid => 'edit'
607 ]
608 ],
609 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
610 ];
611 $url = BackendUtility::getModuleUrl('record_edit', $urlParameters);
612 $pageActionIcons = '
613 <a class="btn btn-default btn-sm" href="' . htmlspecialchars($url) . '">
614 ' . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '
615 </a>';
616
617 // History button
618 $urlParameters = [
619 'element' => $table . ':' . $uid,
620 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
621 ];
622 $url = BackendUtility::getModuleUrl('record_history', $urlParameters);
623 $pageActionIcons .= '
624 <a class="btn btn-default btn-sm" href="' . htmlspecialchars($url) . '">
625 ' . $this->iconFactory->getIcon('actions-document-history-open', Icon::SIZE_SMALL)->render() . '
626 </a>';
627
628 if ($table === 'pages') {
629 // Recordlist button
630 $url = BackendUtility::getModuleUrl('web_list', array('id' => $uid, 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')));
631 $pageActionIcons .= '
632 <a class="btn btn-default btn-sm" href="' . htmlspecialchars($url) . '" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.showList') . '">
633 ' . $this->iconFactory->getIcon('actions-system-list-open', Icon::SIZE_SMALL)->render() . '
634 </a>';
635
636 // View page button
637 $viewOnClick = BackendUtility::viewOnClick($uid, '', BackendUtility::BEgetRootLine($uid));
638 $pageActionIcons .= '
639 <a class="btn btn-default btn-sm" href="#" onclick="' . htmlspecialchars($viewOnClick) . '" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.showPage', true) . '">
640 ' . $this->iconFactory->getIcon('actions-document-view', Icon::SIZE_SMALL)->render() . '
641 </a>';
642 }
643
644 return '
645 <div class="btn-group" role="group">
646 ' . $pageActionIcons . '
647 </div>';
648 }
649
650 /**
651 * Make reference display
652 *
653 * @param string $table Table name
654 * @param string|\TYPO3\CMS\Core\Resource\File $ref Filename or uid
655 * @return string HTML
656 */
657 protected function makeRef($table, $ref)
658 {
659 $lang = $this->getLanguageService();
660 // Files reside in sys_file table
661 if ($table === '_FILE') {
662 $selectTable = 'sys_file';
663 $selectUid = $ref->getUid();
664 } else {
665 $selectTable = $table;
666 $selectUid = $ref;
667 }
668 $rows = $this->getDatabaseConnection()->exec_SELECTgetRows(
669 '*',
670 'sys_refindex',
671 'ref_table=' . $this->getDatabaseConnection()->fullQuoteStr($selectTable, 'sys_refindex') . ' AND ref_uid=' . (int)$selectUid . ' AND deleted=0'
672 );
673
674 // Compile information for title tag:
675 $infoData = array();
676 $infoDataHeader = '';
677 if (!empty($rows)) {
678 $infoDataHeader = '
679 <tr>
680 <th class="col-icon"></th>
681 <th class="col-title">' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.title') . '</th>
682 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.table') . '</th>
683 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.uid') . '</th>
684 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.field') . '</th>
685 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.flexpointer') . '</th>
686 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.softrefKey') . '</th>
687 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.sorting') . '</th>
688 <th class="col-control"></th>
689 </tr>';
690 }
691 foreach ($rows as $row) {
692 if ($row['tablename'] === 'sys_file_reference') {
693 $row = $this->transformFileReferenceToRecordReference($row);
694 if ($row['tablename'] === null || $row['recuid'] === null) {
695 return '';
696 }
697 }
698 $record = BackendUtility::getRecord($row['tablename'], $row['recuid']);
699 if ($record) {
700 $parentRecord = BackendUtility::getRecord('pages', $record['pid']);
701 $parentRecordTitle = is_array($parentRecord)
702 ? BackendUtility::getRecordTitle('pages', $parentRecord)
703 : '';
704 $icon = $this->iconFactory->getIconForRecord($row['tablename'], $record, Icon::SIZE_SMALL)->render();
705 $actions = $this->getRecordActions($row['tablename'], $row['recuid']);
706 $urlParameters = [
707 'edit' => [
708 $row['tablename'] => [
709 $row['recuid'] => 'edit'
710 ]
711 ],
712 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
713 ];
714 $url = BackendUtility::getModuleUrl('record_edit', $urlParameters);
715 $infoData[] = '
716 <tr>
717 <td class="col-icon">
718 <a href="' . htmlspecialchars($url) . '" title="id=' . $record['uid'] . '">
719 ' . $icon . '
720 </a>
721 </td>
722 <td class="col-title">
723 <a href="' . htmlspecialchars($url) . '" title="id=' . $record['uid'] . '" >
724 ' . BackendUtility::getRecordTitle($row['tablename'], $record, true) . '
725 </a>
726 </td>
727 <td>' . $lang->sL($GLOBALS['TCA'][$row['tablename']]['ctrl']['title'], true) . '</td>
728 <td>
729 <span title="' . $lang->sL('LLL:EXT:lang/locallang_common.xlf:page') . ': '
730 . htmlspecialchars($parentRecordTitle) . ' (uid=' . $record['pid'] . ')">
731 ' . $record['uid'] . '
732 </span>
733 </td>
734 <td>' . htmlspecialchars($this->getLabelForTableColumn($row['tablename'], $row['field'])) . '</td>
735 <td>' . htmlspecialchars($row['flexpointer']) . '</td>
736 <td>' . htmlspecialchars($row['softref_key']) . '</td>
737 <td>' . htmlspecialchars($row['sorting']) . '</td>
738 <td class="col-control">' . $actions . '</td>
739 </tr>';
740 } else {
741 $infoData[] = '
742 <tr>
743 <td class="col-icon"></td>
744 <td class="col-title">' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.missing_record') . ' (uid=' . (int)$row['recuid'] . ')</td>
745 <td>' . htmlspecialchars($lang->sL($GLOBALS['TCA'][$row['tablename']]['ctrl']['title']) ?: $row['tablename']) . '</td>
746 <td></td>
747 <td>' . htmlspecialchars($this->getLabelForTableColumn($row['tablename'], $row['field'])) . '</td>
748 <td>' . htmlspecialchars($row['flexpointer']) . '</td>
749 <td>' . htmlspecialchars($row['softref_key']) . '</td>
750 <td>' . htmlspecialchars($row['sorting']) . '</td>
751 <td class="col-control"></td>
752 </tr>';
753 }
754 }
755 $referenceLine = '';
756 if (!empty($infoData)) {
757 $referenceLine = '
758 <div class="table-fit">
759 <table class="table table-striped table-hover">
760 <thead>' . $infoDataHeader . '</thead>
761 <tbody>' . implode('', $infoData) . '</tbody>
762 </table>
763 </div>';
764 }
765 return $referenceLine;
766 }
767
768 /**
769 * Make reference display (what this elements points to)
770 *
771 * @param string $table Table name
772 * @param string $ref Filename or uid
773 * @return string HTML
774 */
775 protected function makeRefFrom($table, $ref)
776 {
777 $lang = $this->getLanguageService();
778 $rows = $this->getDatabaseConnection()->exec_SELECTgetRows(
779 '*',
780 'sys_refindex',
781 'tablename=' . $this->getDatabaseConnection()->fullQuoteStr($table, 'sys_refindex') . ' AND recuid=' . (int)$ref
782 );
783
784 // Compile information for title tag:
785 $infoData = array();
786 $infoDataHeader = '';
787 if (!empty($rows)) {
788 $infoDataHeader = '
789 <tr>
790 <th class="col-icon"></th>
791 <th class="col-title">' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.title') . '</th>
792 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.table') . '</th>
793 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.uid') . '</th>
794 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.field') . '</th>
795 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.flexpointer') . '</th>
796 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.softrefKey') . '</th>
797 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.sorting') . '</th>
798 <th>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.refString') . '</th>
799 <th class="col-control"></th>
800 </tr>';
801 }
802 foreach ($rows as $row) {
803 $record = BackendUtility::getRecord($row['ref_table'], $row['ref_uid']);
804 if ($record) {
805 $icon = $this->iconFactory->getIconForRecord($row['tablename'], $record, Icon::SIZE_SMALL)->render();
806 $actions = $this->getRecordActions($row['ref_table'], $row['ref_uid']);
807
808 $urlParameters = [
809 'edit' => [
810 $row['ref_table'] => [
811 $row['ref_uid'] => 'edit'
812 ]
813 ],
814 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
815 ];
816 $url = BackendUtility::getModuleUrl('record_edit', $urlParameters);
817 $infoData[] = '
818 <tr>
819 <td class="col-icon">
820 <a href="' . htmlspecialchars($url) . '" title="id=' . $record['uid'] . '">
821 ' . $icon . '
822 </a>
823 </td>
824 <td class="col-title">
825 <a href="' . htmlspecialchars($url) . '" title="id=' . $record['uid'] . '" >
826 ' . BackendUtility::getRecordTitle($row['ref_table'], $record, true) . '
827 </a>
828 </td>
829 <td>' . $lang->sL($GLOBALS['TCA'][$row['ref_table']]['ctrl']['title'], true) . '</td>
830 <td>' . htmlspecialchars($row['ref_uid']) . '</td>
831 <td>' . htmlspecialchars($this->getLabelForTableColumn($table, $row['field'])) . '</td>
832 <td>' . htmlspecialchars($row['flexpointer']) . '</td>
833 <td>' . htmlspecialchars($row['softref_key']) . '</td>
834 <td>' . htmlspecialchars($row['sorting']) . '</td>
835 <td>' . htmlspecialchars($row['ref_string']) . '</td>
836 <td class="col-control">' . $actions . '</td>
837 </tr>';
838 } else {
839 $infoData[] = '
840 <tr>
841 <td class="col-icon"></td>
842 <td class="col-title">' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:show_item.php.missing_record') . ' (uid=' . (int)$row['recuid'] . ')</td>
843 <td>' . $lang->sL($GLOBALS['TCA'][$row['ref_table']]['ctrl']['title'], true) . '</td>
844 <td></td>
845 <td>' . htmlspecialchars($this->getLabelForTableColumn($table, $row['field'])) . '</td>
846 <td>' . htmlspecialchars($row['flexpointer']) . '</td>
847 <td>' . htmlspecialchars($row['softref_key']) . '</td>
848 <td>' . htmlspecialchars($row['sorting']) . '</td>
849 <td>' . htmlspecialchars($row['ref_string']) . '</td>
850 <td class="col-control"></td>
851 </tr>';
852 }
853 }
854
855 if (empty($infoData)) {
856 return '';
857 }
858
859 return '
860 <div class="table-fit">
861 <table class="table table-striped table-hover">
862 <thead>' . $infoDataHeader . '</thead>
863 <tbody>' . implode('', $infoData) . '</tbody>
864 </table>
865 </div>';
866 }
867
868 /**
869 * Convert FAL file reference (sys_file_reference) to reference index (sys_refindex) table format
870 *
871 * @param array $referenceRecord
872 * @return array
873 */
874 protected function transformFileReferenceToRecordReference(array $referenceRecord)
875 {
876 $fileReference = $this->getDatabaseConnection()->exec_SELECTgetSingleRow(
877 '*',
878 'sys_file_reference',
879 'uid=' . (int)$referenceRecord['recuid']
880 );
881 return array(
882 'recuid' => $fileReference['uid_foreign'],
883 'tablename' => $fileReference['tablenames'],
884 'field' => $fileReference['fieldname'],
885 'flexpointer' => '',
886 'softref_key' => '',
887 'sorting' => $fileReference['sorting_foreign']
888 );
889 }
890
891 /**
892 * Returns LanguageService
893 *
894 * @return \TYPO3\CMS\Lang\LanguageService
895 */
896 protected function getLanguageService()
897 {
898 return $GLOBALS['LANG'];
899 }
900
901 /**
902 * Returns the current BE user.
903 *
904 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
905 */
906 protected function getBackendUser()
907 {
908 return $GLOBALS['BE_USER'];
909 }
910
911 /**
912 * Returns the database connection
913 *
914 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
915 */
916 protected function getDatabaseConnection()
917 {
918 return $GLOBALS['TYPO3_DB'];
919 }
920 }