7c3537a8b28a10982e8bd8ec2e4770cecdf1055f
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / ContentElement / ElementInformationController.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Backend\Controller\ContentElement;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
20 use TYPO3\CMS\Backend\Backend\Avatar\Avatar;
21 use TYPO3\CMS\Backend\Template\ModuleTemplate;
22 use TYPO3\CMS\Backend\Utility\BackendUtility;
23 use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
24 use TYPO3\CMS\Core\Database\ConnectionPool;
25 use TYPO3\CMS\Core\Http\HtmlResponse;
26 use TYPO3\CMS\Core\Imaging\Icon;
27 use TYPO3\CMS\Core\Imaging\IconFactory;
28 use TYPO3\CMS\Core\Resource\AbstractFile;
29 use TYPO3\CMS\Core\Resource\File;
30 use TYPO3\CMS\Core\Resource\Folder;
31 use TYPO3\CMS\Core\Resource\ResourceFactory;
32 use TYPO3\CMS\Core\Type\Bitmask\Permission;
33 use TYPO3\CMS\Core\Utility\GeneralUtility;
34 use TYPO3\CMS\Fluid\View\StandaloneView;
35
36 /**
37 * Script Class for showing information about an item.
38 */
39 class ElementInformationController
40 {
41 use PublicPropertyDeprecationTrait;
42
43 /**
44 * Properties which have been moved to protected status from public
45 *
46 * @var array
47 */
48 protected $deprecatedPublicProperties = [
49 'table' => 'Using $table of class ElementInformationController from the outside is discouraged, as this variable is only used for internal storage.',
50 'uid' => 'Using $uid of class ElementInformationController from the outside is discouraged, as this variable is only used for internal storage.',
51 'access' => 'Using $access of class ElementInformationController from the outside is discouraged, as this variable is only used for internal storage.',
52 'type' => 'Using $type of class ElementInformationController from the outside is discouraged, as this variable is only used for internal storage.',
53 'pageInfo' => 'Using $pageInfo of class ElementInformationController from the outside is discouraged, as this variable is only used for internal storage.',
54 ];
55
56 /**
57 * Record table name
58 *
59 * @var string
60 */
61 protected $table;
62
63 /**
64 * Record uid
65 *
66 * @var int
67 */
68 protected $uid;
69
70 /**
71 * @var string
72 */
73 protected $permsClause;
74
75 /**
76 * @var bool
77 */
78 protected $access = false;
79
80 /**
81 * Which type of element:
82 * - "file"
83 * - "db"
84 *
85 * @var string
86 */
87 protected $type = '';
88
89 /**
90 * @var ModuleTemplate
91 */
92 protected $moduleTemplate;
93
94 /**
95 * For type "db": Set to page record of the parent page of the item set
96 * (if type="db")
97 *
98 * @var array
99 */
100 protected $pageInfo;
101
102 /**
103 * Database records identified by table/uid
104 *
105 * @var array
106 */
107 protected $row;
108
109 /**
110 * @var \TYPO3\CMS\Core\Resource\File
111 */
112 protected $fileObject;
113
114 /**
115 * @var Folder
116 */
117 protected $folderObject;
118
119 /**
120 * @var IconFactory
121 */
122 protected $iconFactory;
123
124 /**
125 * Constructor
126 */
127 public function __construct()
128 {
129 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
130 $GLOBALS['SOBE'] = $this;
131
132 // @deprecated since v9, will be obsolete in v10 with removal of init()
133 $request = $GLOBALS['TYPO3_REQUEST'];
134 // @deprecated since v9, will be moved out of __construct() in v10
135 $this->init($request);
136 }
137
138 /**
139 * Injects the request object for the current request or subrequest
140 * As this controller goes only through the main() method, it is rather simple for now
141 *
142 * @param ServerRequestInterface $request the current request
143 * @return ResponseInterface the response with the content
144 */
145 public function mainAction(ServerRequestInterface $request): ResponseInterface
146 {
147 $this->main($request);
148 return new HtmlResponse($this->moduleTemplate->renderContent());
149 }
150
151 /**
152 * Determines if table/uid point to database record or file and
153 * if user has access to view information
154 *
155 * @param ServerRequestInterface|null $request
156 */
157 public function init(ServerRequestInterface $request = null): void
158 {
159 if ($request === null) {
160 // Missing argument? This method must have been called from outside.
161 // Method will be protected and $request mandatory in v10, giving core freedom to move stuff around
162 // New v10 signature: "protected function init(ServerRequestInterface $request): void"
163 // @deprecated since TYPO3 v9, method argument $request will be set to mandatory
164 trigger_error('Method init() will be set to protected in v10. Do not call from other extension', E_USER_DEPRECATED);
165 $request = $GLOBALS['TYPO3_REQUEST'];
166 }
167
168 $queryParams = $request->getQueryParams();
169
170 $this->table = $queryParams['table'] ?? null;
171 $this->uid = $queryParams['uid'] ?? null;
172
173 $this->permsClause = $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW);
174 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
175 $this->moduleTemplate->getDocHeaderComponent()->disable();
176
177 if (isset($GLOBALS['TCA'][$this->table])) {
178 $this->initDatabaseRecord();
179 } elseif ($this->table === '_FILE' || $this->table === '_FOLDER' || $this->table === 'sys_file') {
180 $this->initFileOrFolderRecord();
181 }
182 }
183
184 /**
185 * Init database records (table)
186 */
187 protected function initDatabaseRecord()
188 {
189 $this->type = 'db';
190 $this->uid = (int)$this->uid;
191
192 // Check permissions and uid value:
193 if ($this->uid && $this->getBackendUser()->check('tables_select', $this->table)) {
194 if ((string)$this->table === 'pages') {
195 $this->pageInfo = BackendUtility::readPageAccess($this->uid, $this->permsClause);
196 $this->access = is_array($this->pageInfo);
197 $this->row = $this->pageInfo;
198 } else {
199 $this->row = BackendUtility::getRecordWSOL($this->table, $this->uid);
200 if ($this->row) {
201 $this->pageInfo = BackendUtility::readPageAccess($this->row['pid'], $this->permsClause);
202 $this->access = is_array($this->pageInfo);
203 }
204 }
205 }
206 }
207
208 /**
209 * Init file/folder parameters
210 */
211 protected function initFileOrFolderRecord()
212 {
213 $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->uid);
214
215 if ($fileOrFolderObject instanceof Folder) {
216 $this->folderObject = $fileOrFolderObject;
217 $this->access = $this->folderObject->checkActionPermission('read');
218 $this->type = 'folder';
219 } elseif ($fileOrFolderObject instanceof File) {
220 $this->fileObject = $fileOrFolderObject;
221 $this->access = $this->fileObject->checkActionPermission('read');
222 $this->type = 'file';
223 $this->table = 'sys_file';
224
225 try {
226 $this->row = BackendUtility::getRecordWSOL($this->table, $fileOrFolderObject->getUid());
227 } catch (\Exception $e) {
228 $this->row = [];
229 }
230 }
231 }
232
233 /**
234 * Compiles the whole content to be outputted, which is then set as content to the moduleTemplate
235 * There is a hook to do a custom rendering of a record.
236 *
237 * @param ServerRequestInterface $request
238 */
239 public function main(ServerRequestInterface $request = null): void
240 {
241 if ($request === null) {
242 // Missing argument? This method must have been called from outside.
243 // @deprecated since TYPO3 v9, method argument $request will be set to mandatory
244 trigger_error('Method main() will be set to protected in v10. Do not call from other extension', E_USER_DEPRECATED);
245 $request = $GLOBALS['TYPO3_REQUEST'];
246 }
247
248 $content = '';
249
250 // Rendering of the output via fluid
251 $view = GeneralUtility::makeInstance(StandaloneView::class);
252 $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates')]);
253 $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Partials')]);
254 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
255 'EXT:backend/Resources/Private/Templates/ContentElement/ElementInformation.html'
256 ));
257
258 if ($this->access) {
259 // render type by user func
260 $typeRendered = false;
261 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/show_item.php']['typeRendering'] ?? [] as $className) {
262 $typeRenderObj = GeneralUtility::makeInstance($className);
263 if (is_object($typeRenderObj) && method_exists($typeRenderObj, 'isValid') && method_exists($typeRenderObj, 'render')) {
264 if ($typeRenderObj->isValid($this->type, $this)) {
265 $content .= $typeRenderObj->render($this->type, $this);
266 $typeRendered = true;
267 break;
268 }
269 }
270 }
271
272 if (!$typeRendered) {
273 $view->assign('accessAllowed', true);
274 $view->assignMultiple($this->getPageTitle());
275 $view->assignMultiple($this->getPreview());
276 $view->assignMultiple($this->getPropertiesForTable());
277 $view->assignMultiple($this->getReferences($request));
278 $view->assign('returnUrl', GeneralUtility::sanitizeLocalUrl($request->getQueryParams()['returnUrl']));
279 $view->assign('maxTitleLength', $this->getBackendUser()->uc['titleLen'] ?? 20);
280 $content .= $view->render();
281 }
282 } else {
283 $content .= $view->render();
284 }
285
286 $this->moduleTemplate->setContent($content);
287 }
288
289 /**
290 * Get page title with icon, table title and record title
291 *
292 * @return array
293 */
294 protected function getPageTitle(): array
295 {
296 $pageTitle = [
297 'title' => BackendUtility::getRecordTitle($this->table, $this->row, false)
298 ];
299 if ($this->type === 'folder') {
300 $pageTitle['table'] = $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:folder');
301 $pageTitle['icon'] = $this->iconFactory->getIconForResource($this->folderObject, Icon::SIZE_SMALL)->render();
302 } elseif ($this->type === 'file') {
303 $pageTitle['table'] = $this->getLanguageService()->sL($GLOBALS['TCA'][$this->table]['ctrl']['title']);
304 $pageTitle['icon'] = $this->iconFactory->getIconForResource($this->fileObject, Icon::SIZE_SMALL)->render();
305 } else {
306 $pageTitle['table'] = $this->getLanguageService()->sL($GLOBALS['TCA'][$this->table]['ctrl']['title']);
307 $pageTitle['icon'] = $this->iconFactory->getIconForRecord($this->table, $this->row, Icon::SIZE_SMALL);
308 }
309 $this->moduleTemplate->setTitle($pageTitle['table'] . ': ' . $pageTitle['title']);
310 return $pageTitle;
311 }
312
313 /**
314 * Get preview for current record
315 *
316 * @return array
317 */
318 protected function getPreview(): array
319 {
320 $preview = [];
321 // Perhaps @todo in future: Also display preview for records - without fileObject
322 if (!$this->fileObject) {
323 return $preview;
324 }
325
326 // check if file is marked as missing
327 if ($this->fileObject->isMissing()) {
328 $preview['missingFile'] = $this->fileObject->getName();
329 } else {
330 /** @var \TYPO3\CMS\Core\Resource\Rendering\RendererRegistry $rendererRegistry */
331 $rendererRegistry = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Rendering\RendererRegistry::class);
332 $fileRenderer = $rendererRegistry->getRenderer($this->fileObject);
333 $fileExtension = $this->fileObject->getExtension();
334 $preview['url'] = $this->fileObject->getPublicUrl(true);
335
336 $width = '590m';
337 $heigth = '400m';
338
339 // Check if there is a FileRenderer
340 if ($fileRenderer !== null) {
341 $preview['fileRenderer'] = $fileRenderer->render(
342 $this->fileObject,
343 $width,
344 $heigth,
345 [],
346 true
347 );
348
349 // else check if we can create an Image preview
350 } elseif (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileExtension)) {
351 $preview['fileObject'] = $this->fileObject;
352 $preview['width'] = $width;
353 $preview['heigth'] = $heigth;
354 }
355 }
356 return $preview;
357 }
358
359 /**
360 * Get property array for html table
361 *
362 * @return array
363 */
364 protected function getPropertiesForTable(): array
365 {
366 $propertiesForTable = [];
367 $lang = $this->getLanguageService();
368
369 $extraFields = [
370 'uid' => htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:show_item.php.uid'))
371 ];
372
373 if (in_array($this->type, ['folder', 'file'], true)) {
374 if ($this->type === 'file') {
375 $extraFields['creation_date'] = htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.creationDate'));
376 $extraFields['modification_date'] = htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.timestamp'));
377 if ($this->fileObject->getType() === AbstractFile::FILETYPE_IMAGE) {
378 $extraFields['width'] = htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.width'));
379 $extraFields['height'] = htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.height'));
380 }
381 }
382 $extraFields['storage'] = htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file.storage'));
383 $extraFields['folder'] = htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:folder'));
384 } else {
385 $extraFields['crdate'] = htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.creationDate'));
386 $extraFields['cruser_id'] = htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.creationUserId'));
387 $extraFields['tstamp'] = htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.timestamp'));
388
389 // check if the special fields are defined in the TCA ctrl section of the table
390 foreach ($extraFields as $fieldName => $fieldLabel) {
391 if (isset($GLOBALS['TCA'][$this->table]['ctrl'][$fieldName])) {
392 $extraFields[$GLOBALS['TCA'][$this->table]['ctrl'][$fieldName]] = $fieldLabel;
393 } elseif ($fieldName !== 'uid') {
394 unset($extraFields[$fieldName]);
395 }
396 }
397 }
398
399 foreach ($extraFields as $name => $fieldLabel) {
400 $rowValue = '';
401 $thisRow = [];
402 if (!isset($this->row[$name])) {
403 $resourceObject = $this->fileObject ?: $this->folderObject;
404 if ($name === 'storage') {
405 $rowValue = $resourceObject->getStorage()->getName();
406 } elseif ($name === 'folder') {
407 $rowValue = $resourceObject->getParentFolder()->getReadablePath();
408 } elseif ($name === 'width') {
409 $rowValue = $this->fileObject->getProperty('width') . 'px';
410 } elseif ($name === 'height') {
411 $rowValue = $this->fileObject->getProperty('height') . 'px';
412 }
413 } elseif ($name === 'creation_date' || $name === 'modification_date' || $name === 'tstamp' || $name === 'crdate') {
414 $rowValue = BackendUtility::datetime($this->row[$name]);
415 } else {
416 $rowValue = BackendUtility::getProcessedValueExtra($this->table, $name, $this->row[$name]);
417 }
418 $thisRow['value'] = $rowValue;
419 $thisRow['fieldLabel'] = rtrim($fieldLabel, ':');
420 // show the backend username who created the issue
421 if ($name === 'cruser_id' && $rowValue) {
422 $creatorRecord = BackendUtility::getRecord('be_users', $rowValue);
423 if ($creatorRecord) {
424 /** @var Avatar $avatar */
425 $avatar = GeneralUtility::makeInstance(Avatar::class);
426 $creatorRecord['icon'] = $avatar->render($creatorRecord);
427 $thisRow['creatorRecord'] = $creatorRecord;
428 $thisRow['value'] = '';
429 }
430 }
431 $propertiesForTable['extraFields'][] = $thisRow;
432 }
433
434 // Traverse the list of fields to display for the record:
435 $fieldList = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$this->table]['interface']['showRecordFieldList'], true);
436 foreach ($fieldList as $name) {
437 $thisRow = [];
438 $name = trim($name);
439 $uid = $this->row['uid'];
440
441 if (!isset($GLOBALS['TCA'][$this->table]['columns'][$name])) {
442 continue;
443 }
444
445 // Storage is already handled above
446 if ($this->type === 'file' && $name === 'storage') {
447 continue;
448 }
449
450 // format file size as bytes/kilobytes/megabytes
451 if ($this->type === 'file' && $name === 'size') {
452 $this->row[$name] = GeneralUtility::formatSize($this->row[$name], htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:byteSizeUnits')));
453 }
454
455 $isExcluded = !(!$GLOBALS['TCA'][$this->table]['columns'][$name]['exclude'] || $this->getBackendUser()->check('non_exclude_fields', $this->table . ':' . $name));
456 if ($isExcluded) {
457 continue;
458 }
459
460 $thisRow['fieldValue'] = BackendUtility::getProcessedValue($this->table, $name, $this->row[$name], 0, 0, false, $uid);
461 $thisRow['fieldLabel'] = htmlspecialchars($lang->sL(BackendUtility::getItemLabel($this->table, $name)));
462 $propertiesForTable['fields'][] = $thisRow;
463 }
464 return $propertiesForTable;
465 }
466
467 /**
468 * Get references section (references from and references to current record)
469 *
470 * @param ServerRequestInterface $request
471 * @return array
472 */
473 protected function getReferences(ServerRequestInterface $request): array
474 {
475 $references = [];
476 switch ($this->type) {
477 case 'db': {
478 $references['refLines'] = $this->makeRef($this->table, $this->row['uid'], $request);
479 $references['refFromLines'] = $this->makeRefFrom($this->table, $this->row['uid'], $request);
480 break;
481 }
482
483 case 'file': {
484 if ($this->fileObject && $this->fileObject->isIndexed()) {
485 $references['refLines'] = $this->makeRef('_FILE', $this->fileObject, $request);
486 }
487 break;
488 }
489 }
490 return $references;
491 }
492
493 /**
494 * Get field name for specified table/column name
495 *
496 * @param string $tableName Table name
497 * @param string $fieldName Column name
498 * @return string label
499 */
500 public function getLabelForTableColumn($tableName, $fieldName)
501 {
502 // Foreign class call? Method will be protected in v10, giving core freedom to move stuff around
503 $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
504 if (end($backtrace)['class'] !== __CLASS__) {
505 // @deprecated since TYPO3 v9, this method will be set to protected in v10
506 trigger_error('Method getLabelForTableColumn() will be set to protected in v10. Do not call from other extension', E_USER_DEPRECATED);
507 }
508
509 if ($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label'] !== null) {
510 $field = $this->getLanguageService()->sL($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label']);
511 if (trim($field) === '') {
512 $field = $fieldName;
513 }
514 } else {
515 $field = $fieldName;
516 }
517 return $field;
518 }
519
520 /**
521 * Returns the record actions
522 *
523 * @param string $table
524 * @param int $uid
525 * @param ServerRequestInterface $request
526 * @return array
527 */
528 protected function getRecordActions($table, $uid, ServerRequestInterface $request): array
529 {
530 if ($table === '' || $uid < 0) {
531 return [];
532 }
533
534 $actions = [];
535 // Edit button
536 $urlParameters = [
537 'edit' => [
538 $table => [
539 $uid => 'edit'
540 ]
541 ],
542 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri()
543 ];
544 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
545 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
546 $actions['recordEditUrl'] = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
547
548 // History button
549 $urlParameters = [
550 'element' => $table . ':' . $uid,
551 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri()
552 ];
553 $actions['recordHistoryUrl'] = (string)$uriBuilder->buildUriFromRoute('record_history', $urlParameters);
554
555 if ($table === 'pages') {
556 // Recordlist button
557 $actions['webListUrl'] = (string)$uriBuilder->buildUriFromRoute('web_list', ['id' => $uid, 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri()]);
558
559 // View page button
560 $actions['viewOnClick'] = BackendUtility::viewOnClick($uid, '', BackendUtility::BEgetRootLine($uid));
561 }
562
563 return $actions;
564 }
565
566 /**
567 * Make reference display
568 *
569 * @param string $table Table name
570 * @param string|\TYPO3\CMS\Core\Resource\File $ref Filename or uid
571 * @param ServerRequestInterface $request
572 * @return array
573 */
574 protected function makeRef($table, $ref, ServerRequestInterface $request)
575 {
576 $refLines = [];
577 $lang = $this->getLanguageService();
578 // Files reside in sys_file table
579 if ($table === '_FILE') {
580 $selectTable = 'sys_file';
581 $selectUid = $ref->getUid();
582 } else {
583 $selectTable = $table;
584 $selectUid = $ref;
585 }
586 /** @var $queryBuilder \TYPO3\CMS\Core\Database\Query\QueryBuilder */
587 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
588 ->getQueryBuilderForTable('sys_refindex');
589 $rows = $queryBuilder
590 ->select('*')
591 ->from('sys_refindex')
592 ->where(
593 $queryBuilder->expr()->eq(
594 'ref_table',
595 $queryBuilder->createNamedParameter($selectTable, \PDO::PARAM_STR)
596 ),
597 $queryBuilder->expr()->eq(
598 'ref_uid',
599 $queryBuilder->createNamedParameter($selectUid, \PDO::PARAM_INT)
600 ),
601 $queryBuilder->expr()->eq(
602 'deleted',
603 $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
604 )
605 )
606 ->execute()
607 ->fetchAll();
608
609 // Compile information for title tag:
610 foreach ($rows as $row) {
611 if ($row['tablename'] === 'sys_file_reference') {
612 $row = $this->transformFileReferenceToRecordReference($row);
613 if ($row['tablename'] === null || $row['recuid'] === null) {
614 return;
615 }
616 }
617 $line = [];
618 $record = BackendUtility::getRecord($row['tablename'], $row['recuid']);
619 if ($record) {
620 $parentRecord = BackendUtility::getRecord('pages', $record['pid']);
621 $parentRecordTitle = is_array($parentRecord)
622 ? BackendUtility::getRecordTitle('pages', $parentRecord)
623 : '';
624 $urlParameters = [
625 'edit' => [
626 $row['tablename'] => [
627 $row['recuid'] => 'edit'
628 ]
629 ],
630 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri()
631 ];
632 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
633 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
634 $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
635 $line['url'] = $url;
636 $line['icon'] = $this->iconFactory->getIconForRecord($row['tablename'], $record, Icon::SIZE_SMALL)->render();
637 $line['row'] = $row;
638 $line['record'] = $record;
639 $line['recordTitle'] = BackendUtility::getRecordTitle($row['tablename'], $record, false, true);
640 $line['parentRecordTitle'] = $parentRecordTitle;
641 $line['title'] = $lang->sL($GLOBALS['TCA'][$row['tablename']]['ctrl']['title']);
642 $line['labelForTableColumn'] = $this->getLabelForTableColumn($row['tablename'], $row['field']);
643 $line['actions'] = $this->getRecordActions($row['tablename'], $row['recuid'], $request);
644 } else {
645 $line['row'] = $row;
646 $line['title'] = $lang->sL($GLOBALS['TCA'][$row['tablename']]['ctrl']['title']) ?: $row['tablename'];
647 $line['labelForTableColumn'] = $this->getLabelForTableColumn($row['tablename'], $row['field']);
648 }
649 $refLines[] = $line;
650 }
651 return $refLines;
652 }
653
654 /**
655 * Make reference display (what this elements points to)
656 *
657 * @param string $table Table name
658 * @param string $ref Filename or uid
659 * @param ServerRequestInterface $request
660 * @return array
661 */
662 protected function makeRefFrom($table, $ref, ServerRequestInterface $request): array
663 {
664 $refFromLines = [];
665 $lang = $this->getLanguageService();
666
667 /** @var $queryBuilder \TYPO3\CMS\Core\Database\Query\QueryBuilder */
668 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
669 ->getQueryBuilderForTable('sys_refindex');
670 $rows = $queryBuilder
671 ->select('*')
672 ->from('sys_refindex')
673 ->where(
674 $queryBuilder->expr()->eq(
675 'tablename',
676 $queryBuilder->createNamedParameter($table, \PDO::PARAM_STR)
677 ),
678 $queryBuilder->expr()->eq(
679 'recuid',
680 $queryBuilder->createNamedParameter($ref, \PDO::PARAM_INT)
681 )
682 )
683 ->execute()
684 ->fetchAll();
685
686 // Compile information for title tag:
687 foreach ($rows as $row) {
688 $line = [];
689 $record = BackendUtility::getRecord($row['ref_table'], $row['ref_uid']);
690 if ($record) {
691 $urlParameters = [
692 'edit' => [
693 $row['ref_table'] => [
694 $row['ref_uid'] => 'edit'
695 ]
696 ],
697 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri()
698 ];
699 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
700 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
701 $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
702 $line['url'] = $url;
703 $line['icon'] = $this->iconFactory->getIconForRecord($row['tablename'], $record, Icon::SIZE_SMALL)->render();
704 $line['row'] = $row;
705 $line['record'] = $record;
706 $line['recordTitle'] = BackendUtility::getRecordTitle($row['ref_table'], $record, false, true);
707 $line['title'] = $lang->sL($GLOBALS['TCA'][$row['ref_table']]['ctrl']['title']);
708 $line['labelForTableColumn'] = $this->getLabelForTableColumn($table, $row['field']);
709 $line['actions'] = $this->getRecordActions($row['ref_table'], $row['ref_uid'], $request);
710 } else {
711 $line['row'] = $row;
712 $line['title'] = $lang->sL($GLOBALS['TCA'][$row['ref_table']]['ctrl']['title']);
713 $line['labelForTableColumn'] = $this->getLabelForTableColumn($table, $row['field']);
714 }
715 $refFromLines[] = $line;
716 }
717 return $refFromLines;
718 }
719
720 /**
721 * Convert FAL file reference (sys_file_reference) to reference index (sys_refindex) table format
722 *
723 * @param array $referenceRecord
724 * @return array
725 */
726 protected function transformFileReferenceToRecordReference(array $referenceRecord)
727 {
728 /** @var $queryBuilder \TYPO3\CMS\Core\Database\Query\QueryBuilder */
729 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
730 ->getQueryBuilderForTable('sys_file_reference');
731 $queryBuilder->getRestrictions()->removeAll();
732 $fileReference = $queryBuilder
733 ->select('*')
734 ->from('sys_file_reference')
735 ->where(
736 $queryBuilder->expr()->eq(
737 'uid',
738 $queryBuilder->createNamedParameter($referenceRecord['recuid'], \PDO::PARAM_INT)
739 )
740 )
741 ->execute()
742 ->fetch();
743
744 return [
745 'recuid' => $fileReference['uid_foreign'],
746 'tablename' => $fileReference['tablenames'],
747 'field' => $fileReference['fieldname'],
748 'flexpointer' => '',
749 'softref_key' => '',
750 'sorting' => $fileReference['sorting_foreign']
751 ];
752 }
753
754 /**
755 * Returns LanguageService
756 *
757 * @return \TYPO3\CMS\Core\Localization\LanguageService
758 */
759 protected function getLanguageService()
760 {
761 return $GLOBALS['LANG'];
762 }
763
764 /**
765 * Returns the current BE user.
766 *
767 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
768 */
769 protected function getBackendUser()
770 {
771 return $GLOBALS['BE_USER'];
772 }
773 }