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