‪TYPO3CMS  9.5
BackendUtility.php
Go to the documentation of this file.
1 <?php
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\Log\LoggerInterface;
62 
72 {
80  protected static ‪$tcaTableTypeConfigurationCache = [];
81 
82  /*******************************************
83  *
84  * SQL-related, selecting records, searching
85  *
86  *******************************************/
102  public static function ‪deleteClause($table, $tableAlias = '')
103  {
104  trigger_error('BackendUtility::deleteClause() will be removed in TYPO3 v10.0. Add the delete statement directly in your SQL statement via the DeletedRestriction.', E_USER_DEPRECATED);
105  if (empty(‪$GLOBALS['TCA'][$table]['ctrl']['delete'])) {
106  return '';
107  }
108  $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
109  ->getQueryBuilderForTable($table)
110  ->expr();
111  return ' AND ' . $expressionBuilder->eq(
112  ($tableAlias ?: $table) . '.' . ‪$GLOBALS['TCA'][$table]['ctrl']['delete'],
113  0
114  );
115  }
116 
131  public static function ‪getRecord($table, $uid, ‪$fields = '*', $where = '', $useDeleteClause = true)
132  {
133  // Ensure we have a valid uid (not 0 and not NEWxxxx) and a valid TCA
134  if ((int)$uid && !empty(‪$GLOBALS['TCA'][$table])) {
135  $queryBuilder = static::getQueryBuilderForTable($table);
136 
137  // do not use enabled fields here
138  $queryBuilder->getRestrictions()->removeAll();
139 
140  // should the delete clause be used
141  if ($useDeleteClause) {
142  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
143  }
144 
145  // set table and where clause
146  $queryBuilder
147  ->select(...GeneralUtility::trimExplode(',', ‪$fields, true))
148  ->from($table)
149  ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter((int)$uid, \PDO::PARAM_INT)));
150 
151  // add custom where clause
152  if ($where) {
153  $queryBuilder->andWhere(‪QueryHelper::stripLogicalOperatorPrefix($where));
154  }
155 
156  $row = $queryBuilder->execute()->fetch();
157  if ($row) {
158  return $row;
159  }
160  }
161  return null;
162  }
163 
175  public static function ‪getRecordWSOL(
176  $table,
177  $uid,
178  ‪$fields = '*',
179  $where = '',
180  $useDeleteClause = true,
181  $unsetMovePointers = false
182  ) {
183  if (‪$fields !== '*') {
184  $internalFields = GeneralUtility::uniqueList(‪$fields . ',uid,pid');
185  $row = ‪self::getRecord($table, $uid, $internalFields, $where, $useDeleteClause);
186  ‪self::workspaceOL($table, $row, -99, $unsetMovePointers);
187  if (is_array($row)) {
188  foreach ($row as $key => $_) {
189  if (!GeneralUtility::inList(‪$fields, $key) && $key[0] !== '_') {
190  unset($row[$key]);
191  }
192  }
193  }
194  } else {
195  $row = ‪self::getRecord($table, $uid, ‪$fields, $where, $useDeleteClause);
196  ‪self::workspaceOL($table, $row, -99, $unsetMovePointers);
197  }
198  return $row;
199  }
200 
207  public static function ‪purgeComputedPropertiesFromRecord(array $record): array
208  {
209  return array_filter(
210  $record,
211  function (string $propertyName): bool {
212  return $propertyName[0] !== '_';
213  },
214  ARRAY_FILTER_USE_KEY
215  );
216  }
217 
224  public static function ‪purgeComputedPropertyNames(array $propertyNames): array
225  {
226  return array_filter(
227  $propertyNames,
228  function (string $propertyName): bool {
229  return $propertyName[0] !== '_';
230  }
231  );
232  }
233 
241  public static function ‪splitTable_Uid($str)
242  {
243  list($uid, $table) = explode('_', strrev($str), 2);
244  return [strrev($table), strrev($uid)];
245  }
246 
257  public static function ‪BEenableFields($table, $inv = false)
258  {
259  $ctrl = ‪$GLOBALS['TCA'][$table]['ctrl'];
260  $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
261  ->getConnectionForTable($table)
262  ->getExpressionBuilder();
263  $query = $expressionBuilder->andX();
264  $invQuery = $expressionBuilder->orX();
265 
266  if (is_array($ctrl)) {
267  if (is_array($ctrl['enablecolumns'])) {
268  if ($ctrl['enablecolumns']['disabled'] ?? false) {
269  $field = $table . '.' . $ctrl['enablecolumns']['disabled'];
270  $query->add($expressionBuilder->eq($field, 0));
271  $invQuery->add($expressionBuilder->neq($field, 0));
272  }
273  if ($ctrl['enablecolumns']['starttime'] ?? false) {
274  $field = $table . '.' . $ctrl['enablecolumns']['starttime'];
275  $query->add($expressionBuilder->lte($field, (int)‪$GLOBALS['SIM_ACCESS_TIME']));
276  $invQuery->add(
277  $expressionBuilder->andX(
278  $expressionBuilder->neq($field, 0),
279  $expressionBuilder->gt($field, (int)‪$GLOBALS['SIM_ACCESS_TIME'])
280  )
281  );
282  }
283  if ($ctrl['enablecolumns']['endtime'] ?? false) {
284  $field = $table . '.' . $ctrl['enablecolumns']['endtime'];
285  $query->add(
286  $expressionBuilder->orX(
287  $expressionBuilder->eq($field, 0),
288  $expressionBuilder->gt($field, (int)‪$GLOBALS['SIM_ACCESS_TIME'])
289  )
290  );
291  $invQuery->add(
292  $expressionBuilder->andX(
293  $expressionBuilder->neq($field, 0),
294  $expressionBuilder->lte($field, (int)‪$GLOBALS['SIM_ACCESS_TIME'])
295  )
296  );
297  }
298  }
299  }
300 
301  if ($query->count() === 0) {
302  return '';
303  }
304 
305  return ' AND ' . ($inv ? $invQuery : $query);
306  }
307 
317  public static function ‪getRecordLocalization($table, $uid, $language, $andWhereClause = '')
318  {
319  $recordLocalization = false;
320 
321  if (self::isTableLocalizable($table)) {
322  $tcaCtrl = ‪$GLOBALS['TCA'][$table]['ctrl'];
323 
324  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
325  ->getQueryBuilderForTable($table);
326  $queryBuilder->getRestrictions()
327  ->removeAll()
328  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
329  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
330 
331  $queryBuilder->select('*')
332  ->from($table)
333  ->where(
334  $queryBuilder->expr()->eq(
335  $tcaCtrl['translationSource'] ?? $tcaCtrl['transOrigPointerField'],
336  $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
337  ),
338  $queryBuilder->expr()->eq(
339  $tcaCtrl['languageField'],
340  $queryBuilder->createNamedParameter((int)$language, \PDO::PARAM_INT)
341  )
342  )
343  ->setMaxResults(1);
344 
345  if ($andWhereClause) {
346  $queryBuilder->andWhere(‪QueryHelper::stripLogicalOperatorPrefix($andWhereClause));
347  }
348 
349  $recordLocalization = $queryBuilder->execute()->fetchAll();
350  }
351 
352  return $recordLocalization;
353  }
354 
355  /*******************************************
356  *
357  * Page tree, TCA related
358  *
359  *******************************************/
375  public static function ‪BEgetRootLine($uid, $clause = '', $workspaceOL = false, array $additionalFields = [])
376  {
377  $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
378  $beGetRootLineCache = $runtimeCache->get('backendUtilityBeGetRootLine') ?: [];
379  ‪$output = [];
380  $pid = $uid;
381  $ident = $pid . '-' . $clause . '-' . $workspaceOL . ($additionalFields ? '-' . md5(implode(',', $additionalFields)) : '');
382  if (is_array($beGetRootLineCache[$ident] ?? false)) {
383  ‪$output = $beGetRootLineCache[$ident];
384  } else {
385  $loopCheck = 100;
386  $theRowArray = [];
387  while ($uid != 0 && $loopCheck) {
388  $loopCheck--;
389  $row = ‪self::getPageForRootline($uid, $clause, $workspaceOL, $additionalFields);
390  if (is_array($row)) {
391  $uid = $row['pid'];
392  $theRowArray[] = $row;
393  } else {
394  break;
395  }
396  }
397  ‪$fields = [
398  'uid',
399  'pid',
400  'title',
401  'doktype',
402  'slug',
403  'tsconfig_includes',
404  'TSconfig',
405  'is_siteroot',
406  't3ver_oid',
407  't3ver_wsid',
408  't3ver_state',
409  't3ver_stage',
410  'backend_layout_next_level',
411  'hidden',
412  'starttime',
413  'endtime',
414  'fe_group',
415  'nav_hide',
416  'content_from_pid',
417  'module',
418  'extendToSubpages'
419  ];
420  ‪$fields = array_merge(‪$fields, $additionalFields);
421  $rootPage = array_fill_keys(‪$fields, null);
422  if ($uid == 0) {
423  $rootPage['uid'] = 0;
424  $theRowArray[] = $rootPage;
425  }
426  $c = count($theRowArray);
427  foreach ($theRowArray as $val) {
428  $c--;
429  ‪$output[$c] = array_intersect_key($val, $rootPage);
430  if (isset($val['_ORIG_pid'])) {
431  ‪$output[$c]['_ORIG_pid'] = $val['_ORIG_pid'];
432  }
433  }
434  $beGetRootLineCache[$ident] = ‪$output;
435  $runtimeCache->set('backendUtilityBeGetRootLine', $beGetRootLineCache);
436  }
437  return ‪$output;
438  }
439 
450  protected static function ‪getPageForRootline($uid, $clause, $workspaceOL, array $additionalFields = [])
451  {
452  $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
453  $pageForRootlineCache = $runtimeCache->get('backendUtilityPageForRootLine') ?: [];
454  $statementCacheIdent = md5($clause . ($additionalFields ? '-' . implode(',', $additionalFields) : ''));
455  $ident = $uid . '-' . $workspaceOL . '-' . $statementCacheIdent;
456  if (is_array($pageForRootlineCache[$ident] ?? false)) {
457  $row = $pageForRootlineCache[$ident];
458  } else {
459  $statement = $runtimeCache->get('getPageForRootlineStatement-' . $statementCacheIdent);
460  if (!$statement) {
461  $queryBuilder = static::getQueryBuilderForTable('pages');
462  $queryBuilder->getRestrictions()
463  ->removeAll()
464  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
465 
466  $queryBuilder
467  ->select(
468  'pid',
469  'uid',
470  'title',
471  'doktype',
472  'slug',
473  'tsconfig_includes',
474  'TSconfig',
475  'is_siteroot',
476  't3ver_oid',
477  't3ver_wsid',
478  't3ver_state',
479  't3ver_stage',
480  'backend_layout_next_level',
481  'hidden',
482  'starttime',
483  'endtime',
484  'fe_group',
485  'nav_hide',
486  'content_from_pid',
487  'module',
488  'extendToSubpages',
489  ...$additionalFields
490  )
491  ->from('pages')
492  ->where(
493  $queryBuilder->expr()->eq('uid', $queryBuilder->createPositionalParameter($uid, \PDO::PARAM_INT)),
495  );
496  $statement = $queryBuilder->execute();
497  $runtimeCache->set('getPageForRootlineStatement-' . $statementCacheIdent, $statement);
498  } else {
499  $statement->bindValue(1, (int)$uid);
500  $statement->execute();
501  }
502  $row = $statement->fetch();
503  $statement->closeCursor();
504 
505  if ($row) {
506  $newLocation = false;
507  if ($workspaceOL) {
508  ‪self::workspaceOL('pages', $row);
509  if (is_array($row) && (int)$row['t3ver_state'] === ‪VersionState::MOVE_POINTER) {
510  $newLocation = ‪self::getMovePlaceholder('pages', $row['uid'], 'pid');
511  }
512  }
513  if (is_array($row)) {
514  if ($newLocation !== false) {
515  $row['pid'] = $newLocation['pid'];
516  } else {
517  ‪self::fixVersioningPid('pages', $row);
518  }
519  $pageForRootlineCache[$ident] = $row;
520  $runtimeCache->set('backendUtilityPageForRootLine', $pageForRootlineCache);
521  }
522  }
523  }
524  return $row;
525  }
526 
533  public static function ‪openPageTree($pid, $clearExpansion)
534  {
535  $beUser = static::getBackendUserAuthentication();
536  // Get current expansion data:
537  if ($clearExpansion) {
538  $expandedPages = [];
539  } else {
540  $expandedPages = unserialize($beUser->uc['browseTrees']['browsePages'], ['allowed_classes' => false]);
541  }
542  // Get rootline:
543  $rL = ‪self::BEgetRootLine($pid);
544  // First, find out what mount index to use (if more than one DB mount exists):
545  $mountIndex = 0;
546  $mountKeys = array_flip($beUser->returnWebmounts());
547  foreach ($rL as $rLDat) {
548  if (isset($mountKeys[$rLDat['uid']])) {
549  $mountIndex = $mountKeys[$rLDat['uid']];
550  break;
551  }
552  }
553  // Traverse rootline and open paths:
554  foreach ($rL as $rLDat) {
555  $expandedPages[$mountIndex][$rLDat['uid']] = 1;
556  }
557  // Write back:
558  $beUser->uc['browseTrees']['browsePages'] = serialize($expandedPages);
559  $beUser->writeUC();
560  }
561 
573  public static function ‪getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit = 0)
574  {
575  if (!$titleLimit) {
576  $titleLimit = 1000;
577  }
578  ‪$output = $fullOutput = '/';
579  $clause = trim($clause);
580  if ($clause !== '' && strpos($clause, 'AND') !== 0) {
581  $clause = 'AND ' . $clause;
582  }
583  $data = ‪self::BEgetRootLine($uid, $clause, true);
584  foreach ($data as $record) {
585  if ($record['uid'] === 0) {
586  continue;
587  }
588  ‪$output = '/' . GeneralUtility::fixed_lgd_cs(strip_tags($record['title']), $titleLimit) . ‪$output;
589  if ($fullTitleLimit) {
590  $fullOutput = '/' . GeneralUtility::fixed_lgd_cs(strip_tags($record['title']), $fullTitleLimit) . $fullOutput;
591  }
592  }
593  if ($fullTitleLimit) {
594  return [‪$output, $fullOutput];
595  }
596  return ‪$output;
597  }
598 
605  public static function ‪getOriginalTranslationTable($table)
606  {
607  trigger_error('Starting with TYPO3 v9, the translation table is always the same as the original table, because pages_language_overlay has been migrated into pages table.', E_USER_DEPRECATED);
608  return $table;
609  }
610 
617  public static function ‪isTableLocalizable($table)
618  {
619  $isLocalizable = false;
620  if (isset(‪$GLOBALS['TCA'][$table]['ctrl']) && is_array(‪$GLOBALS['TCA'][$table]['ctrl'])) {
621  $tcaCtrl = ‪$GLOBALS['TCA'][$table]['ctrl'];
622  $isLocalizable = isset($tcaCtrl['languageField']) && $tcaCtrl['languageField'] && isset($tcaCtrl['transOrigPointerField']) && $tcaCtrl['transOrigPointerField'];
623  }
624  return $isLocalizable;
625  }
626 
636  public static function ‪readPageAccess($id, $perms_clause)
637  {
638  if ((string)$id !== '') {
639  $id = (int)$id;
640  if (!$id) {
641  if (static::getBackendUserAuthentication()->isAdmin()) {
642  return ['_thePath' => '/'];
643  }
644  } else {
645  $pageinfo = ‪self::getRecord('pages', $id, '*', $perms_clause);
646  if ($pageinfo['uid'] && static::getBackendUserAuthentication()->isInWebMount($pageinfo, $perms_clause)) {
647  ‪self::workspaceOL('pages', $pageinfo);
648  if (is_array($pageinfo)) {
649  ‪self::fixVersioningPid('pages', $pageinfo);
650  list($pageinfo['_thePath'], $pageinfo['_thePathFull']) = ‪self::getRecordPath((int)$pageinfo['uid'], $perms_clause, 15, 1000);
651  return $pageinfo;
652  }
653  }
654  }
655  }
656  return false;
657  }
658 
668  public static function ‪getTCAtypes($table, $rec, $useFieldNameAsKey = false)
669  {
670  trigger_error('BackendUtility::getTCAtypes() will be removed in TYPO3 v10.0. The method is not in use anymore.', E_USER_DEPRECATED);
671  if (isset(‪$GLOBALS['TCA'][$table])) {
672  // Get type value:
673  $fieldValue = ‪self::getTCAtypeValue($table, $rec);
674  $cacheIdentifier = $table . '-type-' . $fieldValue . '-fnk-' . $useFieldNameAsKey;
675 
676  // Fetch from first-level-cache if available
677  if (isset(self::$tcaTableTypeConfigurationCache[$cacheIdentifier])) {
678  return self::$tcaTableTypeConfigurationCache[$cacheIdentifier];
679  }
680 
681  // Get typesConf
682  $typesConf = ‪$GLOBALS['TCA'][$table]['types'][$fieldValue] ?? null;
683  // Get fields list and traverse it
684  $fieldList = explode(',', $typesConf['showitem']);
685 
686  // Add subtype fields e.g. for a valid RTE transformation
687  // The RTE runs the DB -> RTE transformation only, if the RTE field is part of the getTCAtypes array
688  if (isset($typesConf['subtype_value_field'])) {
689  $subType = $rec[$typesConf['subtype_value_field']];
690  if (isset($typesConf['subtypes_addlist'][$subType])) {
691  $subFields = GeneralUtility::trimExplode(',', $typesConf['subtypes_addlist'][$subType], true);
692  $fieldList = array_merge($fieldList, $subFields);
693  }
694  }
695 
696  // Add palette fields e.g. for a valid RTE transformation
697  $paletteFieldList = [];
698  foreach ($fieldList as $fieldData) {
699  $fieldDataArray = GeneralUtility::trimExplode(';', $fieldData);
700  // first two entries would be fieldname and altTitle, they are not used here.
701  $pPalette = $fieldDataArray[2] ?? null;
702  if ($pPalette
703  && isset(‪$GLOBALS['TCA'][$table]['palettes'][$pPalette])
704  && is_array(‪$GLOBALS['TCA'][$table]['palettes'][$pPalette])
705  && isset(‪$GLOBALS['TCA'][$table]['palettes'][$pPalette]['showitem'])
706  ) {
707  $paletteFields = GeneralUtility::trimExplode(',', ‪$GLOBALS['TCA'][$table]['palettes'][$pPalette]['showitem'], true);
708  foreach ($paletteFields as $paletteField) {
709  if ($paletteField !== '--linebreak--') {
710  $paletteFieldList[] = $paletteField;
711  }
712  }
713  }
714  }
715  $fieldList = array_merge($fieldList, $paletteFieldList);
716  $altFieldList = [];
717  // Traverse fields in types config and parse the configuration into a nice array:
718  foreach ($fieldList as $k => $v) {
719  $vArray = GeneralUtility::trimExplode(';', $v);
720  $fieldList[$k] = [
721  'field' => $vArray[0],
722  'title' => $vArray[1] ?? null,
723  'palette' => $vArray[2] ?? null,
724  'spec' => [],
725  'origString' => $v
726  ];
727  if ($useFieldNameAsKey) {
728  $altFieldList[$fieldList[$k]['field']] = $fieldList[$k];
729  }
730  }
731  if ($useFieldNameAsKey) {
732  $fieldList = $altFieldList;
733  }
734 
735  // Add to first-level-cache
736  self::$tcaTableTypeConfigurationCache[$cacheIdentifier] = $fieldList;
737 
738  // Return array:
739  return $fieldList;
740  }
741  return null;
742  }
743 
760  public static function ‪getTCAtypeValue($table, $row)
761  {
762  $typeNum = 0;
763  if (‪$GLOBALS['TCA'][$table]) {
764  $field = ‪$GLOBALS['TCA'][$table]['ctrl']['type'];
765  if (strpos($field, ':') !== false) {
766  list($pointerField, $foreignTableTypeField) = explode(':', $field);
767  // Get field value from database if field is not in the $row array
768  if (!isset($row[$pointerField])) {
769  $localRow = ‪self::getRecord($table, $row['uid'], $pointerField);
770  $foreignUid = $localRow[$pointerField];
771  } else {
772  $foreignUid = $row[$pointerField];
773  }
774  if ($foreignUid) {
775  $fieldConfig = ‪$GLOBALS['TCA'][$table]['columns'][$pointerField]['config'];
776  $relationType = $fieldConfig['type'];
777  if ($relationType === 'select') {
778  $foreignTable = $fieldConfig['foreign_table'];
779  } elseif ($relationType === 'group') {
780  $allowedTables = explode(',', $fieldConfig['allowed']);
781  $foreignTable = $allowedTables[0];
782  } else {
783  throw new \RuntimeException(
784  'TCA foreign field pointer fields are only allowed to be used with group or select field types.',
785  1325862240
786  );
787  }
788  $foreignRow = ‪self::getRecord($foreignTable, $foreignUid, $foreignTableTypeField);
789  if ($foreignRow[$foreignTableTypeField]) {
790  $typeNum = $foreignRow[$foreignTableTypeField];
791  }
792  }
793  } else {
794  $typeNum = $row[$field];
795  }
796  // If that value is an empty string, set it to "0" (zero)
797  if (empty($typeNum)) {
798  $typeNum = 0;
799  }
800  }
801  // If current typeNum doesn't exist, set it to 0 (or to 1 for historical reasons, if 0 doesn't exist)
802  if (!isset(‪$GLOBALS['TCA'][$table]['types'][$typeNum]) || !‪$GLOBALS['TCA'][$table]['types'][$typeNum]) {
803  $typeNum = isset(‪$GLOBALS['TCA'][$table]['types']['0']) ? 0 : 1;
804  }
805  // Force to string. Necessary for eg '-1' to be recognized as a type value.
806  $typeNum = (string)$typeNum;
807  return $typeNum;
808  }
809 
810  /*******************************************
811  *
812  * Caching related
813  *
814  *******************************************/
824  public static function ‪storeHash($hash, $data, $ident)
825  {
826  trigger_error('BackendUtility::storeHash() will be removed in TYPO3 v10.0, use the Caching Framework directly.', E_USER_DEPRECATED);
827  $cacheManager = GeneralUtility::makeInstance(\‪TYPO3\CMS\Core\Cache\CacheManager::class);
828  $cacheManager->getCache('cache_hash')->set($hash, $data, ['ident_' . $ident], 0);
829  }
830 
839  public static function ‪getHash($hash)
840  {
841  trigger_error('BackendUtility::getHash() will be removed in TYPO3 v10.0, use the Caching Framework directly.', E_USER_DEPRECATED);
842  $cacheManager = GeneralUtility::makeInstance(\‪TYPO3\CMS\Core\Cache\CacheManager::class);
843  $cacheEntry = $cacheManager->getCache('cache_hash')->get($hash);
844  $hashContent = null;
845  if ($cacheEntry) {
846  $hashContent = $cacheEntry;
847  }
848  return $hashContent;
849  }
850 
851  /*******************************************
852  *
853  * TypoScript related
854  *
855  *******************************************/
865  public static function ‪getPagesTSconfig($id, $rootLine = null, $returnPartArray = false)
866  {
867  $id = (int)$id;
868 
869  $cache = ‪self::getRuntimeCache();
870  if ($returnPartArray === false
871  && $rootLine === null
872  && $cache->has('pagesTsConfigIdToHash' . $id)
873  ) {
874  return $cache->get('pagesTsConfigHashToContent' . $cache->get('pagesTsConfigIdToHash' . $id));
875  }
876  $tsConfig = [];
877  // No custom rootline, so the results can be cached
878  if (!is_array($rootLine)) {
879  $rootLine = ‪self::BEgetRootLine($id, '', true);
880  $useCacheForCurrentPageId = true;
881  } else {
882  trigger_error('Calling BackendUtility::getPagesTSconfig() with a custom rootline handed over as second argument will be removed in TYPO3 v10.0. Use TYPO3\CMS\Backend\Utility\BackendUtility::getRawPagesTSconfig() instead and parse PageTS yourself.', E_USER_DEPRECATED);
883  $useCacheForCurrentPageId = false;
884  }
885 
886  $TSdataArray = static::getRawPagesTSconfig($id, $rootLine);
887  if ($returnPartArray) {
888  trigger_error('Calling BackendUtility::getPagesTSconfig() with a third parameter to return the unparsed array directly will be removed in TYPO3 v10.0. Use TYPO3\CMS\Backend\Utility\BackendUtility::getRawPagesTSconfig() instead.', E_USER_DEPRECATED);
889  return $TSdataArray;
890  }
891  // Parsing the page TS-Config
892  $pageTs = implode(LF . '[GLOBAL]' . LF, $TSdataArray);
893  /* @var \TYPO3\CMS\Backend\Configuration\TsConfigParser $parseObj */
894  $parseObj = GeneralUtility::makeInstance(\‪TYPO3\CMS\Backend\Configuration\TsConfigParser::class);
895  $res = $parseObj->parseTSconfig($pageTs, 'PAGES', $id, $rootLine);
896  if ($res) {
897  $tsConfig = $res['TSconfig'];
898  }
899  $cacheHash = $res['hash'];
900  // Get User TSconfig overlay, if no backend user is logged-in, this needs to be checked as well
901  if (static::getBackendUserAuthentication()) {
902  $userTSconfig = static::getBackendUserAuthentication()->getTSConfig() ?? [];
903  } else {
904  $userTSconfig = [];
905  }
906  $isCacheHashExtendedWithUserUid = false;
907  if (is_array($userTSconfig['page.'] ?? null)) {
908  ‪ArrayUtility::mergeRecursiveWithOverrule($tsConfig, $userTSconfig['page.']);
909  $isCacheHashExtendedWithUserUid = true;
910  $cacheHash .= '_user' . static::getBackendUserAuthentication()->user['uid'];
911  }
912 
913  // Overlay page "mod." ts with user ts in a special and deprecated way
914  if (is_array($userTSconfig['mod.'] ?? null)) {
915  // @deprecated This entire "if" and variable $isCacheHashExtendedWithUserUid can be deleted in TYPO3 v10.0
916  trigger_error(
917  'Overriding page TSconfig "mod." with user TSconfig "mod." is deprecated. Use user TSconfig "page.mod." instead.',
918  E_USER_DEPRECATED
919  );
920  if (!is_array($tsConfig['mod.'])) {
921  $tsConfig['mod.'] = [];
922  }
923  ‪ArrayUtility::mergeRecursiveWithOverrule($tsConfig['mod.'], $userTSconfig['mod.']);
924  if (!$isCacheHashExtendedWithUserUid) {
925  $cacheHash .= '_user' . static::getBackendUserAuthentication()->user['uid'];
926  }
927  }
928 
929  if ($useCacheForCurrentPageId) {
930  // Many pages end up with the same ts config. To reduce memory usage, the cache
931  // entries are a linked list: One or more pids point to content hashes which then
932  // contain the cached content.
933  $cache->set('pagesTsConfigHashToContent' . $cacheHash, $tsConfig, ['pagesTsConfig']);
934  $cache->set('pagesTsConfigIdToHash' . $id, $cacheHash, ['pagesTsConfig']);
935  }
936 
937  return $tsConfig;
938  }
939 
947  public static function ‪getRawPagesTSconfig($id, array $rootLine = null)
948  {
949  if (!is_array($rootLine)) {
950  $rootLine = ‪self::BEgetRootLine($id, '', true);
951  }
952 
953  // Order correctly
954  ksort($rootLine);
955  $tsDataArray = [];
956  // Setting default configuration
957  $tsDataArray['defaultPageTSconfig'] = ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'];
958  foreach ($rootLine as $k => $v) {
959  if (trim($v['tsconfig_includes'])) {
960  $includeTsConfigFileList = GeneralUtility::trimExplode(',', $v['tsconfig_includes'], true);
961  // Traversing list
962  foreach ($includeTsConfigFileList as $key => $includeTsConfigFile) {
963  if (strpos($includeTsConfigFile, 'EXT:') === 0) {
964  list($includeTsConfigFileExtensionKey, $includeTsConfigFilename) = explode(
965  '/',
966  substr($includeTsConfigFile, 4),
967  2
968  );
969  if ((string)$includeTsConfigFileExtensionKey !== ''
970  && ‪ExtensionManagementUtility::isLoaded($includeTsConfigFileExtensionKey)
971  && (string)$includeTsConfigFilename !== ''
972  ) {
973  $extensionPath = ‪ExtensionManagementUtility::extPath($includeTsConfigFileExtensionKey);
974  $includeTsConfigFileAndPath = ‪PathUtility::getCanonicalPath($extensionPath . $includeTsConfigFilename);
975  if (strpos($includeTsConfigFileAndPath, $extensionPath) === 0 && file_exists($includeTsConfigFileAndPath)) {
976  $tsDataArray['uid_' . $v['uid'] . '_static_' . $key] = file_get_contents($includeTsConfigFileAndPath);
977  }
978  }
979  }
980  }
981  }
982  $tsDataArray['uid_' . $v['uid']] = $v['TSconfig'];
983  }
984 
985  $tsDataArray = static::emitGetPagesTSconfigPreIncludeSignal($tsDataArray, $id, $rootLine);
986  $tsDataArray = ‪TypoScriptParser::checkIncludeLines_array($tsDataArray);
987 
988  return $tsDataArray;
989  }
990 
991  /*******************************************
992  *
993  * Users / Groups related
994  *
995  *******************************************/
1004  public static function ‪getUserNames(‪$fields = 'username,usergroup,usergroup_cached_list,uid', $where = '')
1005  {
1007  GeneralUtility::trimExplode(',', ‪$fields, true),
1008  'be_users',
1009  'username',
1010  'AND pid=0 ' . $where
1011  );
1012  }
1013 
1021  public static function ‪getGroupNames(‪$fields = 'title,uid', $where = '')
1022  {
1024  GeneralUtility::trimExplode(',', ‪$fields, true),
1025  'be_groups',
1026  'title',
1027  'AND pid=0 ' . $where
1028  );
1029  }
1030 
1042  protected static function ‪getRecordsSortedByTitle(array ‪$fields, $table, $titleField, $where = '')
1043  {
1044  $fieldsIndex = array_flip(‪$fields);
1045  // Make sure the titleField is amongst the fields when getting sorted
1046  $fieldsIndex[$titleField] = 1;
1047 
1048  $result = [];
1049 
1050  $queryBuilder = static::getQueryBuilderForTable($table);
1051  $queryBuilder->getRestrictions()
1052  ->removeAll()
1053  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1054 
1055  $res = $queryBuilder
1056  ->select('*')
1057  ->from($table)
1059  ->execute();
1060 
1061  while ($record = $res->fetch()) {
1062  // store the uid, because it might be unset if it's not among the requested $fields
1063  $recordId = $record['uid'];
1064  $record[$titleField] = ‪self::getRecordTitle($table, $record);
1065 
1066  // include only the requested fields in the result
1067  $result[$recordId] = array_intersect_key($record, $fieldsIndex);
1068  }
1069 
1070  // sort records by $sortField. This is not done in the query because the title might have been overwritten by
1071  // self::getRecordTitle();
1072  return ‪ArrayUtility::sortArraysByKey($result, $titleField);
1073  }
1074 
1083  public static function ‪getListGroupNames(‪$fields = 'title, uid')
1084  {
1085  trigger_error('BackendUtility::getListGroupNames() will be removed in TYPO3 v10.0, you should generate the list of backend user groups by yourself.', E_USER_DEPRECATED);
1086  $beUser = static::getBackendUserAuthentication();
1087  $exQ = '';
1088  if (!$beUser->isAdmin()) {
1089  $exQ = ' AND uid IN (' . ($beUser->user['usergroup_cached_list'] ?: 0) . ')';
1090  }
1091  return ‪self::getGroupNames(‪$fields, $exQ);
1092  }
1093 
1104  public static function ‪blindUserNames($usernames, $groupArray, $excludeBlindedFlag = false)
1105  {
1106  if (is_array($usernames) && is_array($groupArray)) {
1107  foreach ($usernames as $uid => $row) {
1108  $userN = $uid;
1109  $set = 0;
1110  if ($row['uid'] != static::getBackendUserAuthentication()->user['uid']) {
1111  foreach ($groupArray as $v) {
1112  if ($v && GeneralUtility::inList($row['usergroup_cached_list'], $v)) {
1113  $userN = $row['username'];
1114  $set = 1;
1115  }
1116  }
1117  } else {
1118  $userN = $row['username'];
1119  $set = 1;
1120  }
1121  $usernames[$uid]['username'] = $userN;
1122  if ($excludeBlindedFlag && !$set) {
1123  unset($usernames[$uid]);
1124  }
1125  }
1126  }
1127  return $usernames;
1128  }
1129 
1138  public static function ‪blindGroupNames($groups, $groupArray, $excludeBlindedFlag = false)
1139  {
1140  if (is_array($groups) && is_array($groupArray)) {
1141  foreach ($groups as $uid => $row) {
1142  $groupN = $uid;
1143  $set = 0;
1144  if (in_array($uid, $groupArray, false)) {
1145  $groupN = $row['title'];
1146  $set = 1;
1147  }
1148  $groups[$uid]['title'] = $groupN;
1149  if ($excludeBlindedFlag && !$set) {
1150  unset($groups[$uid]);
1151  }
1152  }
1153  }
1154  return $groups;
1155  }
1156 
1157  /*******************************************
1158  *
1159  * Output related
1160  *
1161  *******************************************/
1168  public static function ‪daysUntil($tstamp)
1169  {
1170  $delta_t = $tstamp - ‪$GLOBALS['EXEC_TIME'];
1171  return ceil($delta_t / (3600 * 24));
1172  }
1173 
1180  public static function ‪date($tstamp)
1181  {
1182  return ‪date(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], (int)$tstamp);
1183  }
1184 
1191  public static function ‪datetime($value)
1192  {
1193  return ‪date(
1194  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' ' . ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'],
1195  $value
1196  );
1197  }
1198 
1207  public static function ‪time($value, $withSeconds = true)
1208  {
1209  return gmdate('H:i' . ($withSeconds ? ':s' : ''), (int)$value);
1210  }
1211 
1219  public static function ‪calcAge($seconds, $labels = 'min|hrs|days|yrs|min|hour|day|year')
1220  {
1221  $labelArr = GeneralUtility::trimExplode('|', $labels, true);
1222  $absSeconds = abs($seconds);
1223  $sign = $seconds < 0 ? -1 : 1;
1224  if ($absSeconds < 3600) {
1225  $val = round($absSeconds / 60);
1226  $seconds = $sign * $val . ' ' . ($val == 1 ? $labelArr[4] : $labelArr[0]);
1227  } elseif ($absSeconds < 24 * 3600) {
1228  $val = round($absSeconds / 3600);
1229  $seconds = $sign * $val . ' ' . ($val == 1 ? $labelArr[5] : $labelArr[1]);
1230  } elseif ($absSeconds < 365 * 24 * 3600) {
1231  $val = round($absSeconds / (24 * 3600));
1232  $seconds = $sign * $val . ' ' . ($val == 1 ? $labelArr[6] : $labelArr[2]);
1233  } else {
1234  $val = round($absSeconds / (365 * 24 * 3600));
1235  $seconds = $sign * $val . ' ' . ($val == 1 ? $labelArr[7] : $labelArr[3]);
1236  }
1237  return $seconds;
1238  }
1239 
1249  public static function ‪dateTimeAge($tstamp, $prefix = 1, $date = '')
1250  {
1251  if (!$tstamp) {
1252  return '';
1253  }
1254  $label = static::getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.minutesHoursDaysYears');
1255  $age = ' (' . ‪self::calcAge($prefix * (‪$GLOBALS['EXEC_TIME'] - $tstamp), $label) . ')';
1256  return ($date === 'date' ? self::date($tstamp) : self::datetime($tstamp)) . $age;
1257  }
1258 
1268  public static function ‪resolveFileReferences($tableName, $fieldName, $element, $workspaceId = null)
1269  {
1270  if (empty(‪$GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config'])) {
1271  return null;
1272  }
1273  $configuration = ‪$GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config'];
1274  if (empty($configuration['type']) || $configuration['type'] !== 'inline'
1275  || empty($configuration['foreign_table']) || $configuration['foreign_table'] !== 'sys_file_reference'
1276  ) {
1277  return null;
1278  }
1279 
1280  $fileReferences = [];
1282  $relationHandler = GeneralUtility::makeInstance(RelationHandler::class);
1283  if ($workspaceId !== null) {
1284  $relationHandler->setWorkspaceId($workspaceId);
1285  }
1286  $relationHandler->start(
1287  $element[$fieldName],
1288  $configuration['foreign_table'],
1289  $configuration['MM'] ?? '',
1290  $element['uid'],
1291  $tableName,
1292  $configuration
1293  );
1294  $relationHandler->processDeletePlaceholder();
1295  $referenceUids = $relationHandler->tableArray[$configuration['foreign_table']];
1296 
1297  foreach ($referenceUids as $referenceUid) {
1298  try {
1300  $referenceUid,
1301  [],
1302  $workspaceId === 0
1303  );
1304  $fileReferences[$fileReference->getUid()] = $fileReference;
1305  } catch (\‪TYPO3\CMS\Core\Resource\‪Exception\FileDoesNotExistException $e) {
1310  } catch (\InvalidArgumentException $e) {
1315  ‪self::getLogger()->error($e->getMessage(), ['table' => $tableName, 'fieldName' => $fieldName, 'referenceUid' => $referenceUid, 'exception' => $e]);
1316  }
1317  }
1318 
1319  return $fileReferences;
1320  }
1321 
1339  public static function ‪thumbCode(
1340  $row,
1341  $table,
1342  $field,
1343  $backPath = '',
1344  $thumbScript = '',
1345  $uploaddir = null,
1346  $abs = 0,
1347  $tparams = '',
1348  $size = '',
1349  $linkInfoPopup = true
1350  ) {
1351  // Check and parse the size parameter
1352  $size = trim($size);
1353  $sizeParts = [64, 64];
1354  if ($size) {
1355  $sizeParts = explode('x', $size . 'x' . $size);
1356  }
1357  $thumbData = '';
1358  $fileReferences = static::resolveFileReferences($table, $field, $row);
1359  // FAL references
1360  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
1361  if ($fileReferences !== null) {
1362  foreach ($fileReferences as $fileReferenceObject) {
1363  // Do not show previews of hidden references
1364  if ($fileReferenceObject->getProperty('hidden')) {
1365  continue;
1366  }
1367  $fileObject = $fileReferenceObject->getOriginalFile();
1368 
1369  if ($fileObject->isMissing()) {
1370  $thumbData .= '<span class="label label-danger">'
1371  . htmlspecialchars(
1372  static::getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.file_missing')
1373  )
1374  . '</span>&nbsp;' . htmlspecialchars($fileObject->getName()) . '<br />';
1375  continue;
1376  }
1377 
1378  // Preview web image or media elements
1379  if (‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails']
1380  && GeneralUtility::inList(
1381  ‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'],
1382  $fileReferenceObject->getExtension()
1383  )
1384  ) {
1385  $cropVariantCollection = ‪CropVariantCollection::create((string)$fileReferenceObject->getProperty('crop'));
1386  $cropArea = $cropVariantCollection->getCropArea();
1387  $parameters = json_encode([
1388  'fileId' => $fileObject->getUid(),
1389  'configuration' => [
1390  'width' => $sizeParts[0],
1391  'height' => $sizeParts[1] . 'c',
1392  'crop' => $cropArea->isEmpty() ? null : $cropArea->makeAbsoluteBasedOnFile($fileReferenceObject),
1393  ]
1394  ]);
1395  $uriParameters = [
1396  'parameters' => $parameters,
1397  'hmac' => GeneralUtility::hmac(
1398  $parameters,
1399  \‪TYPO3\CMS\Backend\Controller\‪File\ThumbnailController::class
1400  ),
1401  ];
1402  $imageUrl = (string)GeneralUtility::makeInstance(UriBuilder::class)
1403  ->buildUriFromRoute('thumbnails', $uriParameters);
1404  $attributes = [
1405  'src' => $imageUrl,
1406  'width' => (int)$sizeParts[0],
1407  'height' => (int)$sizeParts[1],
1408  'alt' => $fileReferenceObject->getName(),
1409  ];
1410  $imgTag = '<img ' . GeneralUtility::implodeAttributes($attributes, true) . $tparams . '/>';
1411  } else {
1412  // Icon
1413  $imgTag = '<span title="' . htmlspecialchars($fileObject->getName()) . '">'
1414  . $iconFactory->getIconForResource($fileObject, ‪Icon::SIZE_SMALL)->render()
1415  . '</span>';
1416  }
1417  if ($linkInfoPopup) {
1418  $onClick = 'top.TYPO3.InfoWindow.showItem(\'_FILE\',\'' . (int)$fileObject->getUid() . '\'); return false;';
1419  $thumbData .= '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $imgTag . '</a> ';
1420  } else {
1421  $thumbData .= $imgTag;
1422  }
1423  }
1424  } else {
1425  // Find uploaddir automatically
1426  if ($uploaddir === null) {
1427  $uploaddir = $GLOBALS['TCA'][$table]['columns'][$field]['config']['uploadfolder'];
1428  }
1429  $uploaddir = rtrim($uploaddir, '/');
1430  // Traverse files:
1431  $thumbs = GeneralUtility::trimExplode(',', $row[$field], true);
1432  $thumbData = '';
1433  foreach ($thumbs as $theFile) {
1434  if ($theFile) {
1435  $fileName = trim($uploaddir . '/' . $theFile, '/');
1436  try {
1438  $fileObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($fileName);
1439  // Skip the resource if it's not of type ‪AbstractFile. One case where this can happen if the
1440  // storage has been externally modified and the field value now points to a folder
1441  // instead of a file.
1442  if (!$fileObject instanceof ‪AbstractFile) {
1443  continue;
1444  }
1445  if ($fileObject->isMissing()) {
1446  $thumbData .= '<span class="label label-danger">'
1447  . htmlspecialchars(static::getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.file_missing'))
1448  . '</span>&nbsp;' . htmlspecialchars($fileObject->getName()) . '<br />';
1449  continue;
1450  }
1451  } catch (‪ResourceDoesNotExistException $exception) {
1452  $thumbData .= '<span class="label label-danger">'
1453  . htmlspecialchars(static::getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.file_missing'))
1454  . '</span>&nbsp;' . htmlspecialchars($fileName) . '<br />';
1455  continue;
1456  }
1457 
1458  $fileExtension = $fileObject->‪getExtension();
1459  if ($fileExtension === 'ttf'
1460  || GeneralUtility::inList(‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileExtension)
1461  ) {
1462  $imageUrl = $fileObject->process(
1464  [
1465  'width' => $sizeParts[0],
1466  'height' => $sizeParts[1]
1467  ]
1468  )->getPublicUrl(true);
1469 
1470  $image = '<img src="' . htmlspecialchars($imageUrl) . '" hspace="2" border="0" title="' . htmlspecialchars($fileObject->getName()) . '"' . $tparams . ' alt="" />';
1471  if ($linkInfoPopup) {
1472  $onClick = 'top.TYPO3.InfoWindow.showItem(\'_FILE\', ' . GeneralUtility::quoteJSvalue($fileName) . ',\'\');return false;';
1473  $thumbData .= '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $image . '</a> ';
1474  } else {
1475  $thumbData .= $image;
1476  }
1477  } else {
1478  // Gets the icon
1479  $fileIcon = '<span title="' . htmlspecialchars($fileObject->getName()) . '">'
1480  . $iconFactory->getIconForResource($fileObject, ‪Icon::SIZE_SMALL)->render()
1481  . '</span>';
1482  if ($linkInfoPopup) {
1483  $onClick = 'top.TYPO3.InfoWindow.showItem(\'_FILE\', ' . GeneralUtility::quoteJSvalue($fileName) . ',\'\'); return false;';
1484  $thumbData .= '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $fileIcon . '</a> ';
1485  } else {
1486  $thumbData .= $fileIcon;
1487  }
1488  }
1489  }
1490  }
1491  }
1492  return $thumbData;
1493  }
1494 
1503  public static function titleAttribForPages($row, $perms_clause = '', $includeAttrib = true)
1504  {
1505  $lang = static::getLanguageService();
1506  $parts = [];
1507  $parts[] = 'id=' . $row['uid'];
1508  if ($row['uid'] === 0) {
1509  $out = htmlspecialchars($parts[0]);
1510  return $includeAttrib ? 'title="' . $out . '"' : $out;
1511  }
1512  if ($row['alias']) {
1513  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['alias']['label']) . ' ' . $row['alias'];
1514  }
1515  if ($row['pid'] < 0) {
1516  $parts[] = 'v#1.' . $row['t3ver_id'];
1517  }
1518  switch (‪VersionState::cast($row['t3ver_state'])) {
1519  case new VersionState(‪VersionState::NEW_PLACEHOLDER):
1520  $parts[] = 'PLH WSID#' . $row['t3ver_wsid'];
1521  break;
1522  case new VersionState(‪VersionState::DELETE_PLACEHOLDER):
1523  $parts[] = 'Deleted element!';
1524  break;
1525  case new VersionState(‪VersionState::MOVE_PLACEHOLDER):
1526  $parts[] = 'OLD LOCATION (Move Placeholder) WSID#' . $row['t3ver_wsid'];
1527  break;
1528  case new VersionState(‪VersionState::MOVE_POINTER):
1529  $parts[] = 'NEW LOCATION (Move-to Pointer) WSID#' . $row['t3ver_wsid'];
1530  break;
1531  case new VersionState(‪VersionState::NEW_PLACEHOLDER_VERSION):
1532  $parts[] = 'New element!';
1533  break;
1534  }
1535  if ($row['doktype'] == ‪PageRepository::DOKTYPE_LINK) {
1536  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['url']['label']) . ' ' . $row['url'];
1537  } elseif ($row['doktype'] == ‪PageRepository::DOKTYPE_SHORTCUT) {
1538  if ($perms_clause) {
1539  $label = self::getRecordPath((int)$row['shortcut'], $perms_clause, 20);
1540  } else {
1541  $row['shortcut'] = (int)$row['shortcut'];
1542  $lRec = self::getRecordWSOL('pages', $row['shortcut'], 'title');
1543  $label = $lRec['title'] . ' (id=' . $row['shortcut'] . ')';
1544  }
1545  if ($row['shortcut_mode'] != ‪PageRepository::SHORTCUT_MODE_NONE) {
1546  $label .= ', ' . $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['shortcut_mode']['label']) . ' '
1547  . $lang->sL(self::getLabelFromItemlist('pages', 'shortcut_mode', $row['shortcut_mode']));
1548  }
1549  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['shortcut']['label']) . ' ' . $label;
1550  } elseif ($row['doktype'] == ‪PageRepository::DOKTYPE_MOUNTPOINT) {
1551  if ((int)$row['mount_pid'] > 0) {
1552  if ($perms_clause) {
1553  $label = self::getRecordPath((int)$row['mount_pid'], $perms_clause, 20);
1554  } else {
1555  $lRec = self::getRecordWSOL('pages', (int)$row['mount_pid'], 'title');
1556  $label = $lRec['title'] . ' (id=' . $row['mount_pid'] . ')';
1557  }
1558  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['mount_pid']['label']) . ' ' . $label;
1559  if ($row['mount_pid_ol']) {
1560  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['mount_pid_ol']['label']);
1561  }
1562  } else {
1563  $parts[] = $lang->sl('LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:no_mount_pid');
1564  }
1565  }
1566  if ($row['nav_hide']) {
1567  $parts[] = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.nav_hide');
1568  }
1569  if ($row['hidden']) {
1570  $parts[] = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.hidden');
1571  }
1572  if ($row['starttime']) {
1573  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['starttime']['label'])
1574  . ' ' . self::dateTimeAge($row['starttime'], -1, 'date');
1575  }
1576  if ($row['endtime']) {
1577  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['endtime']['label']) . ' '
1578  . self::dateTimeAge($row['endtime'], -1, 'date');
1579  }
1580  if ($row['fe_group']) {
1581  $fe_groups = [];
1582  foreach (GeneralUtility::intExplode(',', $row['fe_group']) as $fe_group) {
1583  if ($fe_group < 0) {
1584  $fe_groups[] = $lang->sL(self::getLabelFromItemlist('pages', 'fe_group', $fe_group));
1585  } else {
1586  $lRec = self::getRecordWSOL('fe_groups', $fe_group, 'title');
1587  $fe_groups[] = $lRec['title'];
1588  }
1589  }
1590  $label = implode(', ', $fe_groups);
1591  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['fe_group']['label']) . ' ' . $label;
1592  }
1593  $out = htmlspecialchars(implode(' - ', $parts));
1594  return $includeAttrib ? 'title="' . $out . '"' : $out;
1595  }
1596 
1604  public static function getRecordToolTip(array $row, $table = 'pages')
1605  {
1606  $toolTipText = self::getRecordIconAltText($row, $table);
1607  $toolTipCode = 'data-toggle="tooltip" data-title=" '
1608  . str_replace(' - ', '<br>', $toolTipText)
1609  . '" data-html="true" data-placement="right"';
1610  return $toolTipCode;
1611  }
1612 
1622  public static function getRecordIconAltText($row, $table = 'pages')
1623  {
1624  if ($table === 'pages') {
1625  $out = self::titleAttribForPages($row, '', 0);
1626  } else {
1627  $out = !empty(trim(‪$GLOBALS['TCA'][$table]['ctrl']['descriptionColumn'])) ? $row[‪$GLOBALS['TCA'][$table]['ctrl']['descriptionColumn']] . ' ' : '';
1628  $ctrl = ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
1629  // Uid is added
1630  $out .= 'id=' . $row['uid'];
1631  if ($table === 'pages' && $row['alias']) {
1632  $out .= ' / ' . $row['alias'];
1633  }
1634  if (static::isTableWorkspaceEnabled($table) && $row['pid'] < 0) {
1635  $out .= ' - v#1.' . $row['t3ver_id'];
1636  }
1637  if (static::isTableWorkspaceEnabled($table)) {
1638  switch (‪VersionState::cast($row['t3ver_state'])) {
1639  case new VersionState(‪VersionState::NEW_PLACEHOLDER):
1640  $out .= ' - PLH WSID#' . $row['t3ver_wsid'];
1641  break;
1642  case new VersionState(‪VersionState::DELETE_PLACEHOLDER):
1643  $out .= ' - Deleted element!';
1644  break;
1645  case new VersionState(‪VersionState::MOVE_PLACEHOLDER):
1646  $out .= ' - OLD LOCATION (Move Placeholder) WSID#' . $row['t3ver_wsid'];
1647  break;
1648  case new VersionState(‪VersionState::MOVE_POINTER):
1649  $out .= ' - NEW LOCATION (Move-to Pointer) WSID#' . $row['t3ver_wsid'];
1650  break;
1651  case new VersionState(‪VersionState::NEW_PLACEHOLDER_VERSION):
1652  $out .= ' - New element!';
1653  break;
1654  }
1655  }
1656  // Hidden
1657  $lang = static::getLanguageService();
1658  if ($ctrl['disabled']) {
1659  $out .= $row[$ctrl['disabled']] ? ' - ' . $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.hidden') : '';
1660  }
1661  if ($ctrl['starttime']) {
1662  if ($row[$ctrl['starttime']] > ‪$GLOBALS['EXEC_TIME']) {
1663  $out .= ' - ' . $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.starttime') . ':' . self::date($row[$ctrl['starttime']]) . ' (' . self::daysUntil($row[$ctrl['starttime']]) . ' ' . $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.days') . ')';
1664  }
1665  }
1666  if ($row[$ctrl['endtime']]) {
1667  $out .= ' - ' . $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.endtime') . ': ' . self::date($row[$ctrl['endtime']]) . ' (' . self::daysUntil($row[$ctrl['endtime']]) . ' ' . $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.days') . ')';
1668  }
1669  }
1670  return htmlspecialchars($out);
1671  }
1672 
1681  public static function getLabelFromItemlist($table, $col, $key)
1682  {
1683  // Check, if there is an "items" array:
1684  if (is_array(‪$GLOBALS['TCA'][$table]['columns'][$col]['config']['items'] ?? false)) {
1685  // Traverse the items-array...
1686  foreach (‪$GLOBALS['TCA'][$table]['columns'][$col]['config']['items'] as $v) {
1687  // ... and return the first found label where the value was equal to $key
1688  if ((string)$v[1] === (string)$key) {
1689  return $v[0];
1690  }
1691  }
1692  }
1693  return '';
1694  }
1695 
1705  public static function getLabelFromItemListMerged($pageId, $table, $column, $key)
1706  {
1707  $pageTsConfig = static::getPagesTSconfig($pageId);
1708  $label = '';
1709  if (isset($pageTsConfig['TCEFORM.'])
1710  && \is_array($pageTsConfig['TCEFORM.'])
1711  && \is_array($pageTsConfig['TCEFORM.'][$table . '.'])
1712  && \is_array($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.'])
1713  ) {
1714  if (\is_array($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['addItems.'])
1715  && isset($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['addItems.'][$key])
1716  ) {
1717  $label = $pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['addItems.'][$key];
1718  } elseif (\is_array($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['altLabels.'])
1719  && isset($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['altLabels.'][$key])
1720  ) {
1721  $label = $pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['altLabels.'][$key];
1722  }
1723  }
1724  if (empty($label)) {
1725  $tcaValue = self::getLabelFromItemlist($table, $column, $key);
1726  if (!empty($tcaValue)) {
1727  $label = $tcaValue;
1728  }
1729  }
1730  return $label;
1731  }
1732 
1743  public static function getLabelsFromItemsList($table, $column, $keyList, array $columnTsConfig = [])
1744  {
1745  // Check if there is an "items" array
1746  if (
1747  !isset(‪$GLOBALS['TCA'][$table]['columns'][$column]['config']['items'])
1748  || !is_array(‪$GLOBALS['TCA'][$table]['columns'][$column]['config']['items'])
1749  || $keyList === ''
1750  ) {
1751  return '';
1752  }
1753 
1754  $keys = GeneralUtility::trimExplode(',', $keyList, true);
1755  $labels = [];
1756  // Loop on all selected values
1757  foreach ($keys as $key) {
1758  $label = null;
1759  if ($columnTsConfig) {
1760  // Check if label has been defined or redefined via pageTsConfig
1761  if (isset($columnTsConfig['addItems.'][$key])) {
1762  $label = $columnTsConfig['addItems.'][$key];
1763  } elseif (isset($columnTsConfig['altLabels.'][$key])) {
1764  $label = $columnTsConfig['altLabels.'][$key];
1765  }
1766  }
1767  if ($label === null) {
1768  // Otherwise lookup the label in TCA items list
1769  foreach (‪$GLOBALS['TCA'][$table]['columns'][$column]['config']['items'] as $itemConfiguration) {
1770  list($currentLabel, $currentKey) = $itemConfiguration;
1771  if ((string)$key === (string)$currentKey) {
1772  $label = $currentLabel;
1773  break;
1774  }
1775  }
1776  }
1777  if ($label !== null) {
1778  $labels[] = static::getLanguageService()->sL($label);
1779  }
1780  }
1781  return implode(', ', $labels);
1782  }
1783 
1792  public static function getItemLabel($table, $col)
1793  {
1794  // Check if column exists
1795  if (is_array(‪$GLOBALS['TCA'][$table]) && is_array(‪$GLOBALS['TCA'][$table]['columns'][$col])) {
1796  return ‪$GLOBALS['TCA'][$table]['columns'][$col]['label'];
1797  }
1798 
1799  return null;
1800  }
1801 
1812  public static function getRecordTitle($table, $row, $prep = false, $forceResult = true)
1813  {
1814  $recordTitle = '';
1815  if (isset(‪$GLOBALS['TCA'][$table]) && is_array(‪$GLOBALS['TCA'][$table])) {
1816  // If configured, call userFunc
1817  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['label_userFunc'])) {
1818  $params['table'] = $table;
1819  $params['row'] = $row;
1820  $params['title'] = '';
1821  $params['options'] = ‪$GLOBALS['TCA'][$table]['ctrl']['label_userFunc_options'] ?? [];
1822 
1823  // Create NULL-reference
1824  $null = null;
1825  GeneralUtility::callUserFunction(‪$GLOBALS['TCA'][$table]['ctrl']['label_userFunc'], $params, $null);
1826  $recordTitle = $params['title'];
1827  } else {
1828  // No userFunc: Build label
1829  $recordTitle = self::getProcessedValue(
1830  $table,
1831  ‪$GLOBALS['TCA'][$table]['ctrl']['label'],
1832  $row[‪$GLOBALS['TCA'][$table]['ctrl']['label']],
1833  0,
1834  0,
1835  false,
1836  $row['uid'],
1837  $forceResult
1838  );
1839  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['label_alt'])
1840  && (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['label_alt_force']) || (string)$recordTitle === '')
1841  ) {
1842  $altFields = GeneralUtility::trimExplode(',', ‪$GLOBALS['TCA'][$table]['ctrl']['label_alt'], true);
1843  $tA = [];
1844  if (!empty($recordTitle)) {
1845  $tA[] = $recordTitle;
1846  }
1847  foreach ($altFields as $fN) {
1848  $recordTitle = trim(strip_tags($row[$fN]));
1849  if ((string)$recordTitle !== '') {
1850  $recordTitle = self::getProcessedValue($table, $fN, $recordTitle, 0, 0, false, $row['uid']);
1851  if (!‪$GLOBALS['TCA'][$table]['ctrl']['label_alt_force']) {
1852  break;
1853  }
1854  $tA[] = $recordTitle;
1855  }
1856  }
1857  if (‪$GLOBALS['TCA'][$table]['ctrl']['label_alt_force']) {
1858  $recordTitle = implode(', ', $tA);
1859  }
1860  }
1861  }
1862  // If the current result is empty, set it to '[No title]' (localized) and prepare for output if requested
1863  if ($prep || $forceResult) {
1864  if ($prep) {
1865  $recordTitle = self::getRecordTitlePrep($recordTitle);
1866  }
1867  if (trim($recordTitle) === '') {
1868  $recordTitle = self::getNoRecordTitle($prep);
1869  }
1870  }
1871  }
1872 
1873  return $recordTitle;
1874  }
1875 
1884  public static function getRecordTitlePrep($title, $titleLength = 0)
1885  {
1886  // If $titleLength is not a valid positive integer, use BE_USER->uc['titleLen']:
1887  if (!$titleLength || !‪MathUtility::canBeInterpretedAsInteger($titleLength) || $titleLength < 0) {
1888  $titleLength = static::getBackendUserAuthentication()->uc['titleLen'];
1889  }
1890  $titleOrig = htmlspecialchars($title);
1891  $title = htmlspecialchars(GeneralUtility::fixed_lgd_cs($title, $titleLength));
1892  // If title was cropped, offer a tooltip:
1893  if ($titleOrig != $title) {
1894  $title = '<span title="' . $titleOrig . '">' . $title . '</span>';
1895  }
1896  return $title;
1897  }
1898 
1905  public static function getNoRecordTitle($prep = false)
1906  {
1907  $noTitle = '[' .
1908  htmlspecialchars(static::getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title'))
1909  . ']';
1910  if ($prep) {
1911  $noTitle = '<em>' . $noTitle . '</em>';
1912  }
1913  return $noTitle;
1914  }
1915 
1934  public static function getProcessedValue(
1935  $table,
1936  $col,
1937  $value,
1938  $fixed_lgd_chars = 0,
1939  $defaultPassthrough = false,
1940  $noRecordLookup = false,
1941  $uid = 0,
1942  $forceResult = true,
1943  $pid = 0
1944  ) {
1945  if ($col === 'uid') {
1946  // uid is not in TCA-array
1947  return $value;
1948  }
1949  // Check if table and field is configured
1950  if (!isset(‪$GLOBALS['TCA'][$table]['columns'][$col]) || !is_array(‪$GLOBALS['TCA'][$table]['columns'][$col])) {
1951  return null;
1952  }
1953  // Depending on the fields configuration, make a meaningful output value.
1954  $theColConf = ‪$GLOBALS['TCA'][$table]['columns'][$col]['config'] ?? [];
1955  /*****************
1956  *HOOK: pre-processing the human readable output from a record
1957  ****************/
1958  $null = null;
1959  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['preProcessValue'] ?? [] as $_funcRef) {
1960  GeneralUtility::callUserFunction($_funcRef, $theColConf, $null);
1961  }
1962 
1963  $l = '';
1964  $lang = static::getLanguageService();
1965  switch ((string)($theColConf['type'] ?? '')) {
1966  case 'radio':
1967  $l = self::getLabelFromItemlist($table, $col, $value);
1968  $l = $lang->sL($l);
1969  break;
1970  case 'inline':
1971  case 'select':
1972  if (!empty($theColConf['MM'])) {
1973  if ($uid) {
1974  // Display the title of MM related records in lists
1975  if ($noRecordLookup) {
1976  $MMfields = [];
1977  $MMfields[] = $theColConf['foreign_table'] . '.uid';
1978  } else {
1979  $MMfields = [$theColConf['foreign_table'] . '.' . ‪$GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label']];
1980  if (isset(‪$GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label_alt'])) {
1981  foreach (GeneralUtility::trimExplode(
1982  ',',
1983  ‪$GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label_alt'],
1984  true
1985  ) as $f) {
1986  $MMfields[] = $theColConf['foreign_table'] . '.' . $f;
1987  }
1988  }
1989  }
1991  $dbGroup = GeneralUtility::makeInstance(RelationHandler::class);
1992  $dbGroup->start(
1993  $value,
1994  $theColConf['foreign_table'],
1995  $theColConf['MM'],
1996  $uid,
1997  $table,
1998  $theColConf
1999  );
2000  $selectUids = $dbGroup->tableArray[$theColConf['foreign_table']];
2001  if (is_array($selectUids) && !empty($selectUids)) {
2002  $queryBuilder = static::getQueryBuilderForTable($theColConf['foreign_table']);
2003  $queryBuilder->getRestrictions()
2004  ->removeAll()
2005  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
2006 
2007  $result = $queryBuilder
2008  ->select('uid', ...$MMfields)
2009  ->from($theColConf['foreign_table'])
2010  ->where(
2011  $queryBuilder->expr()->in(
2012  'uid',
2013  $queryBuilder->createNamedParameter($selectUids, Connection::PARAM_INT_ARRAY)
2014  )
2015  )
2016  ->execute();
2017 
2018  $mmlA = [];
2019  while ($MMrow = $result->fetch()) {
2020  // Keep sorting of $selectUids
2021  $selectedUid = array_search($MMrow['uid'], $selectUids);
2022  $mmlA[$selectedUid] = $MMrow['uid'];
2023  if (!$noRecordLookup) {
2024  $mmlA[$selectedUid] = static::getRecordTitle(
2025  $theColConf['foreign_table'],
2026  $MMrow,
2027  false,
2028  $forceResult
2029  );
2030  }
2031  }
2032 
2033  if (!empty($mmlA)) {
2034  ksort($mmlA);
2035  $l = implode('; ', $mmlA);
2036  } else {
2037  $l = 'N/A';
2038  }
2039  } else {
2040  $l = 'N/A';
2041  }
2042  } else {
2043  $l = 'N/A';
2044  }
2045  } else {
2046  $columnTsConfig = [];
2047  if ($pid) {
2048  $pageTsConfig = self::getPagesTSconfig($pid);
2049  if (isset($pageTsConfig['TCEFORM.'][$table . '.'][$col . '.']) && is_array($pageTsConfig['TCEFORM.'][$table . '.'][$col . '.'])) {
2050  $columnTsConfig = $pageTsConfig['TCEFORM.'][$table . '.'][$col . '.'];
2051  }
2052  }
2053  $l = self::getLabelsFromItemsList($table, $col, $value, $columnTsConfig);
2054  if (!empty($theColConf['foreign_table']) && !$l && !empty(‪$GLOBALS['TCA'][$theColConf['foreign_table']])) {
2055  if ($noRecordLookup) {
2056  $l = $value;
2057  } else {
2058  $rParts = [];
2059  if ($uid && isset($theColConf['foreign_field']) && $theColConf['foreign_field'] !== '') {
2060  $queryBuilder = static::getQueryBuilderForTable($theColConf['foreign_table']);
2061  $queryBuilder->getRestrictions()
2062  ->removeAll()
2063  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2064  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
2065  $constraints = [
2066  $queryBuilder->expr()->eq(
2067  $theColConf['foreign_field'],
2068  $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
2069  )
2070  ];
2071 
2072  if (!empty($theColConf['foreign_table_field'])) {
2073  $constraints[] = $queryBuilder->expr()->eq(
2074  $theColConf['foreign_table_field'],
2075  $queryBuilder->createNamedParameter($table, \PDO::PARAM_STR)
2076  );
2077  }
2078 
2079  // Add additional where clause if foreign_match_fields are defined
2080  $foreignMatchFields = [];
2081  if (is_array($theColConf['foreign_match_fields'])) {
2082  $foreignMatchFields = $theColConf['foreign_match_fields'];
2083  }
2084 
2085  foreach ($foreignMatchFields as $matchField => $matchValue) {
2086  $constraints[] = $queryBuilder->expr()->eq(
2087  $matchField,
2088  $queryBuilder->createNamedParameter($matchValue)
2089  );
2090  }
2091 
2092  $result = $queryBuilder
2093  ->select('*')
2094  ->from($theColConf['foreign_table'])
2095  ->where(...$constraints)
2096  ->execute();
2097 
2098  while ($record = $result->fetch()) {
2099  $rParts[] = $record['uid'];
2100  }
2101  }
2102  if (empty($rParts)) {
2103  $rParts = GeneralUtility::trimExplode(',', $value, true);
2104  }
2105  $lA = [];
2106  foreach ($rParts as $rVal) {
2107  $rVal = (int)$rVal;
2108  $r = self::getRecordWSOL($theColConf['foreign_table'], $rVal);
2109  if (is_array($r)) {
2110  $lA[] = $lang->sL($theColConf['foreign_table_prefix'])
2111  . self::getRecordTitle($theColConf['foreign_table'], $r, false, $forceResult);
2112  } else {
2113  $lA[] = $rVal ? '[' . $rVal . '!]' : '';
2114  }
2115  }
2116  $l = implode(', ', $lA);
2117  }
2118  }
2119  if (empty($l) && !empty($value)) {
2120  // Use plain database value when label is empty
2121  $l = $value;
2122  }
2123  }
2124  break;
2125  case 'group':
2126  // resolve the titles for DB records
2127  if (isset($theColConf['internal_type']) && $theColConf['internal_type'] === 'db') {
2128  if (isset($theColConf['MM']) && $theColConf['MM']) {
2129  if ($uid) {
2130  // Display the title of MM related records in lists
2131  if ($noRecordLookup) {
2132  $MMfields = [];
2133  $MMfields[] = $theColConf['foreign_table'] . '.uid';
2134  } else {
2135  $MMfields = [$theColConf['foreign_table'] . '.' . ‪$GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label']];
2136  $altLabelFields = explode(
2137  ',',
2138  ‪$GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label_alt']
2139  );
2140  foreach ($altLabelFields as $f) {
2141  $f = trim($f);
2142  if ($f !== '') {
2143  $MMfields[] = $theColConf['foreign_table'] . '.' . $f;
2144  }
2145  }
2146  }
2148  $dbGroup = GeneralUtility::makeInstance(RelationHandler::class);
2149  $dbGroup->start(
2150  $value,
2151  $theColConf['foreign_table'],
2152  $theColConf['MM'],
2153  $uid,
2154  $table,
2155  $theColConf
2156  );
2157  $selectUids = $dbGroup->tableArray[$theColConf['foreign_table']];
2158  if (!empty($selectUids) && is_array($selectUids)) {
2159  $queryBuilder = static::getQueryBuilderForTable($theColConf['foreign_table']);
2160  $queryBuilder->getRestrictions()
2161  ->removeAll()
2162  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
2163 
2164  $result = $queryBuilder
2165  ->select('uid', ...$MMfields)
2166  ->from($theColConf['foreign_table'])
2167  ->where(
2168  $queryBuilder->expr()->in(
2169  'uid',
2170  $queryBuilder->createNamedParameter(
2171  $selectUids,
2172  Connection::PARAM_INT_ARRAY
2173  )
2174  )
2175  )
2176  ->execute();
2177 
2178  $mmlA = [];
2179  while ($MMrow = $result->fetch()) {
2180  // Keep sorting of $selectUids
2181  $selectedUid = array_search($MMrow['uid'], $selectUids);
2182  $mmlA[$selectedUid] = $MMrow['uid'];
2183  if (!$noRecordLookup) {
2184  $mmlA[$selectedUid] = static::getRecordTitle(
2185  $theColConf['foreign_table'],
2186  $MMrow,
2187  false,
2188  $forceResult
2189  );
2190  }
2191  }
2192 
2193  if (!empty($mmlA)) {
2194  ksort($mmlA);
2195  $l = implode('; ', $mmlA);
2196  } else {
2197  $l = 'N/A';
2198  }
2199  } else {
2200  $l = 'N/A';
2201  }
2202  } else {
2203  $l = 'N/A';
2204  }
2205  } else {
2206  $finalValues = [];
2207  $relationTableName = $theColConf['allowed'];
2208  $explodedValues = GeneralUtility::trimExplode(',', $value, true);
2209 
2210  foreach ($explodedValues as $explodedValue) {
2211  if (‪MathUtility::canBeInterpretedAsInteger($explodedValue)) {
2212  $relationTableNameForField = $relationTableName;
2213  } else {
2214  list($relationTableNameForField, $explodedValue) = self::splitTable_Uid($explodedValue);
2215  }
2216 
2217  $relationRecord = static::getRecordWSOL($relationTableNameForField, $explodedValue);
2218  $finalValues[] = static::getRecordTitle($relationTableNameForField, $relationRecord);
2219  }
2220  $l = implode(', ', $finalValues);
2221  }
2222  } else {
2223  $l = implode(', ', GeneralUtility::trimExplode(',', $value, true));
2224  }
2225  break;
2226  case 'check':
2227  if (!is_array($theColConf['items'])) {
2228  $l = $value ? $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:yes') : $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:no');
2229  } elseif (count($theColConf['items']) === 1) {
2230  reset($theColConf['items']);
2231  $invertStateDisplay = current($theColConf['items'])['invertStateDisplay'] ?? false;
2232  if ($invertStateDisplay) {
2233  $value = !$value;
2234  }
2235  $l = $value ? $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:yes') : $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:no');
2236  } else {
2237  $lA = [];
2238  foreach ($theColConf['items'] as $key => $val) {
2239  if ($value & pow(2, $key)) {
2240  $lA[] = $lang->sL($val[0]);
2241  }
2242  }
2243  $l = implode(', ', $lA);
2244  }
2245  break;
2246  case 'input':
2247  // Hide value 0 for dates, but show it for everything else
2248  if (isset($value)) {
2249  $dateTimeFormats = ‪QueryHelper::getDateTimeFormats();
2250 
2251  if (GeneralUtility::inList($theColConf['eval'] ?? '', 'date')) {
2252  // Handle native date field
2253  if (isset($theColConf['dbType']) && $theColConf['dbType'] === 'date') {
2254  $value = $value === $dateTimeFormats['date']['empty'] ? 0 : (int)strtotime($value);
2255  } else {
2256  $value = (int)$value;
2257  }
2258  if (!empty($value)) {
2259  $ageSuffix = '';
2260  $dateColumnConfiguration = ‪$GLOBALS['TCA'][$table]['columns'][$col]['config'];
2261  $ageDisplayKey = 'disableAgeDisplay';
2262 
2263  // generate age suffix as long as not explicitly suppressed
2264  if (!isset($dateColumnConfiguration[$ageDisplayKey])
2265  // non typesafe comparison on intention
2266  || $dateColumnConfiguration[$ageDisplayKey] == false
2267  ) {
2268  $ageSuffix = ' (' . (‪$GLOBALS['EXEC_TIME'] - $value > 0 ? '-' : '')
2269  . self::calcAge(
2270  abs(‪$GLOBALS['EXEC_TIME'] - $value),
2271  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.minutesHoursDaysYears')
2272  )
2273  . ')';
2274  }
2275 
2276  $l = self::date($value) . $ageSuffix;
2277  }
2278  } elseif (GeneralUtility::inList($theColConf['eval'] ?? '', 'time')) {
2279  // Handle native time field
2280  if (isset($theColConf['dbType']) && $theColConf['dbType'] === 'time') {
2281  $value = $value === $dateTimeFormats['time']['empty'] ? 0 : (int)strtotime('1970-01-01 ' . $value);
2282  } else {
2283  $value = (int)$value;
2284  }
2285  if (!empty($value)) {
2286  $l = gmdate('H:i', (int)$value);
2287  }
2288  } elseif (GeneralUtility::inList($theColConf['eval'] ?? '', 'timesec')) {
2289  // Handle native time field
2290  if (isset($theColConf['dbType']) && $theColConf['dbType'] === 'time') {
2291  $value = $value === $dateTimeFormats['time']['empty'] ? 0 : (int)strtotime('1970-01-01 ' . $value);
2292  } else {
2293  $value = (int)$value;
2294  }
2295  if (!empty($value)) {
2296  $l = gmdate('H:i:s', (int)$value);
2297  }
2298  } elseif (GeneralUtility::inList($theColConf['eval'] ?? '', 'datetime')) {
2299  // Handle native datetime field
2300  if (isset($theColConf['dbType']) && $theColConf['dbType'] === 'datetime') {
2301  $value = $value === $dateTimeFormats['datetime']['empty'] ? 0 : (int)strtotime($value);
2302  } else {
2303  $value = (int)$value;
2304  }
2305  if (!empty($value)) {
2306  $l = self::datetime($value);
2307  }
2308  } else {
2309  $l = $value;
2310  }
2311  }
2312  break;
2313  case 'flex':
2314  $l = strip_tags($value);
2315  break;
2316  default:
2317  if ($defaultPassthrough) {
2318  $l = $value;
2319  } elseif (isset($theColConf['MM'])) {
2320  $l = 'N/A';
2321  } elseif ($value) {
2322  $l = GeneralUtility::fixed_lgd_cs(strip_tags($value), 200);
2323  }
2324  }
2325  // If this field is a password field, then hide the password by changing it to a random number of asterisk (*)
2326  if (!empty($theColConf['eval']) && stristr($theColConf['eval'], 'password')) {
2327  $l = '';
2328  $randomNumber = rand(5, 12);
2329  for ($i = 0; $i < $randomNumber; $i++) {
2330  $l .= '*';
2331  }
2332  }
2333  /*****************
2334  *HOOK: post-processing the human readable output from a record
2335  ****************/
2336  $null = null;
2337  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['postProcessValue'] ?? [] as $_funcRef) {
2338  $params = [
2339  'value' => $l,
2340  'colConf' => $theColConf
2341  ];
2342  $l = GeneralUtility::callUserFunction($_funcRef, $params, $null);
2343  }
2344  if ($fixed_lgd_chars) {
2345  return GeneralUtility::fixed_lgd_cs($l, $fixed_lgd_chars);
2346  }
2347  return $l;
2348  }
2349 
2363  public static function getProcessedValueExtra(
2364  $table,
2365  $fN,
2366  $fV,
2367  $fixed_lgd_chars = 0,
2368  $uid = 0,
2369  $forceResult = true,
2370  $pid = 0
2371  ) {
2372  $fVnew = self::getProcessedValue($table, $fN, $fV, $fixed_lgd_chars, 1, 0, $uid, $forceResult, $pid);
2373  if (!isset($fVnew)) {
2374  if (is_array(‪$GLOBALS['TCA'][$table])) {
2375  if ($fN == ‪$GLOBALS['TCA'][$table]['ctrl']['tstamp'] || $fN == ‪$GLOBALS['TCA'][$table]['ctrl']['crdate']) {
2376  $fVnew = self::datetime($fV);
2377  } elseif ($fN === 'pid') {
2378  // Fetches the path with no regard to the users permissions to select pages.
2379  $fVnew = self::getRecordPath($fV, '1=1', 20);
2380  } else {
2381  $fVnew = $fV;
2382  }
2383  }
2384  }
2385  return $fVnew;
2386  }
2387 
2398  public static function getCommonSelectFields($table, $prefix = '', ‪$fields = [])
2399  {
2400  ‪$fields[] = $prefix . 'uid';
2401  if (isset(‪$GLOBALS['TCA'][$table]['ctrl']['label']) && ‪$GLOBALS['TCA'][$table]['ctrl']['label'] != '') {
2402  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['label'];
2403  }
2404  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['label_alt'])) {
2405  $secondFields = GeneralUtility::trimExplode(',', ‪$GLOBALS['TCA'][$table]['ctrl']['label_alt'], true);
2406  foreach ($secondFields as $fieldN) {
2407  ‪$fields[] = $prefix . $fieldN;
2408  }
2409  }
2410  if (static::isTableWorkspaceEnabled($table)) {
2411  ‪$fields[] = $prefix . 't3ver_id';
2412  ‪$fields[] = $prefix . 't3ver_state';
2413  ‪$fields[] = $prefix . 't3ver_wsid';
2414  ‪$fields[] = $prefix . 't3ver_count';
2415  }
2416  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['selicon_field'])) {
2417  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['selicon_field'];
2418  }
2419  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['typeicon_column'])) {
2420  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['typeicon_column'];
2421  }
2422  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'])) {
2423  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'];
2424  }
2425  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['starttime'])) {
2426  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['starttime'];
2427  }
2428  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime'])) {
2429  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime'];
2430  }
2431  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['fe_group'])) {
2432  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['fe_group'];
2433  }
2434  return implode(',', array_unique(‪$fields));
2435  }
2436 
2437  /*******************************************
2438  *
2439  * Backend Modules API functions
2440  *
2441  *******************************************/
2442 
2450  public static function helpTextArray($table, $field)
2451  {
2452  if (!isset(‪$GLOBALS['TCA_DESCR'][$table]['columns'])) {
2453  static::getLanguageService()->loadSingleTableDescription($table);
2454  }
2455  ‪$output = [
2456  'description' => null,
2457  'title' => null,
2458  'moreInfo' => false
2459  ];
2460  if (isset(‪$GLOBALS['TCA_DESCR'][$table]['columns'][$field]) && is_array(‪$GLOBALS['TCA_DESCR'][$table]['columns'][$field])) {
2461  $data = ‪$GLOBALS['TCA_DESCR'][$table]['columns'][$field];
2462  // Add alternative title, if defined
2463  if ($data['alttitle']) {
2464  ‪$output['title'] = $data['alttitle'];
2465  }
2466  // If we have more information to show and access to the cshmanual
2467  if (($data['image_descr'] || $data['seeAlso'] || $data['details'] || $data['syntax'])
2468  && static::getBackendUserAuthentication()->check('modules', 'help_CshmanualCshmanual')
2469  ) {
2470  ‪$output['moreInfo'] = true;
2471  }
2472  // Add description
2473  if ($data['description']) {
2474  ‪$output['description'] = $data['description'];
2475  }
2476  }
2477  return ‪$output;
2478  }
2479 
2488  public static function helpText($table, $field)
2489  {
2490  $helpTextArray = self::helpTextArray($table, $field);
2491  ‪$output = '';
2492  $arrow = '';
2493  // Put header before the rest of the text
2494  if ($helpTextArray['title'] !== null) {
2495  ‪$output .= '<h2>' . $helpTextArray['title'] . '</h2>';
2496  }
2497  // Add see also arrow if we have more info
2498  if ($helpTextArray['moreInfo']) {
2500  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
2501  $arrow = $iconFactory->getIcon('actions-view-go-forward', ‪Icon::SIZE_SMALL)->render();
2502  }
2503  // Wrap description and arrow in p tag
2504  if ($helpTextArray['description'] !== null || $arrow) {
2505  ‪$output .= '<p class="t3-help-short">' . nl2br(htmlspecialchars($helpTextArray['description'])) . $arrow . '</p>';
2506  }
2507  return ‪$output;
2508  }
2509 
2520  public static function wrapInHelp($table, $field, $text = '', array $overloadHelpText = [])
2521  {
2522  // Initialize some variables
2523  $helpText = '';
2524  $abbrClassAdd = '';
2525  $hasHelpTextOverload = !empty($overloadHelpText);
2526  // Get the help text that should be shown on hover
2527  if (!$hasHelpTextOverload) {
2528  $helpText = self::helpText($table, $field);
2529  }
2530  // If there's a help text or some overload information, proceed with preparing an output
2531  if (!empty($helpText) || $hasHelpTextOverload) {
2532  // If no text was given, just use the regular help icon
2533  if ($text == '') {
2534  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
2535  $text = $iconFactory->getIcon('actions-system-help-open', ‪Icon::SIZE_SMALL)->render();
2536  $abbrClassAdd = '-icon';
2537  }
2538  $text = '<abbr class="t3-help-teaser' . $abbrClassAdd . '">' . $text . '</abbr>';
2539  $wrappedText = '<span class="t3-help-link" href="#" data-table="' . $table . '" data-field="' . $field . '"';
2540  // The overload array may provide a title and a description
2541  // If either one is defined, add them to the "data" attributes
2542  if ($hasHelpTextOverload) {
2543  if (isset($overloadHelpText['title'])) {
2544  $wrappedText .= ' data-title="' . htmlspecialchars($overloadHelpText['title']) . '"';
2545  }
2546  if (isset($overloadHelpText['description'])) {
2547  $wrappedText .= ' data-description="' . htmlspecialchars($overloadHelpText['description']) . '"';
2548  }
2549  }
2550  $wrappedText .= '>' . $text . '</span>';
2551  return $wrappedText;
2552  }
2553  return $text;
2554  }
2555 
2566  public static function cshItem($table, $field, $_ = '', $wrap = '')
2567  {
2568  static::getLanguageService()->loadSingleTableDescription($table);
2569  if (is_array(‪$GLOBALS['TCA_DESCR'][$table])
2570  && is_array(‪$GLOBALS['TCA_DESCR'][$table]['columns'][$field])
2571  ) {
2572  // Creating short description
2573  ‪$output = self::wrapInHelp($table, $field);
2574  if (‪$output && $wrap) {
2575  $wrParts = explode('|', $wrap);
2576  ‪$output = $wrParts[0] . ‪$output . $wrParts[1];
2577  }
2578  return ‪$output;
2579  }
2580  return '';
2581  }
2582 
2593  public static function editOnClick($params, $_ = '', $requestUri = '')
2594  {
2595  if ($requestUri == -1) {
2596  $returnUrl = 'T3_THIS_LOCATION';
2597  } else {
2598  $returnUrl = GeneralUtility::quoteJSvalue(rawurlencode($requestUri ?: GeneralUtility::getIndpEnv('REQUEST_URI')));
2599  }
2600  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2601  return 'window.location.href=' . GeneralUtility::quoteJSvalue((string)$uriBuilder->buildUriFromRoute('record_edit') . $params . '&returnUrl=') . '+' . $returnUrl . '; return false;';
2602  }
2603 
2617  public static function viewOnClick(
2618  $pageUid,
2619  $backPath = '',
2620  $rootLine = null,
2621  $anchorSection = '',
2622  $alternativeUrl = '',
2623  $additionalGetVars = '',
2624  $switchFocus = true
2625  ) {
2626  $previewUrl = self::getPreviewUrl(
2627  $pageUid,
2628  $backPath,
2629  $rootLine,
2630  $anchorSection,
2631  $alternativeUrl,
2632  $additionalGetVars,
2633  $switchFocus
2634  );
2635 
2636  $onclickCode = 'var previewWin = window.open(' . GeneralUtility::quoteJSvalue($previewUrl) . ',\'newTYPO3frontendWindow\');'
2637  . ($switchFocus ? 'previewWin.focus();' : '') . LF
2638  . 'if (previewWin.location.href === ' . GeneralUtility::quoteJSvalue($previewUrl) . ') { previewWin.location.reload(); };';
2639 
2640  return $onclickCode;
2641  }
2642 
2657  public static function getPreviewUrl(
2658  $pageUid,
2659  $backPath = '',
2660  $rootLine = null,
2661  $anchorSection = '',
2662  $alternativeUrl = '',
2663  $additionalGetVars = '',
2664  &$switchFocus = true
2665  ): string {
2666  $viewScript = '/index.php?id=';
2667  if ($alternativeUrl) {
2668  $viewScript = $alternativeUrl;
2669  }
2670 
2671  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['viewOnClickClass'] ?? [] as $className) {
2672  $hookObj = GeneralUtility::makeInstance($className);
2673  if (method_exists($hookObj, 'preProcess')) {
2674  $hookObj->preProcess(
2675  $pageUid,
2676  $backPath,
2677  $rootLine,
2678  $anchorSection,
2679  $viewScript,
2680  $additionalGetVars,
2681  $switchFocus
2682  );
2683  }
2684  }
2685 
2686  // If there is an alternative URL or the URL has been modified by a hook, use that one.
2687  if ($alternativeUrl || $viewScript !== '/index.php?id=') {
2688  $previewUrl = $viewScript;
2689  } else {
2690  $permissionClause = ‪$GLOBALS['BE_USER']->getPagePermsClause(‪Permission::PAGE_SHOW);
2691  $pageInfo = self::readPageAccess($pageUid, $permissionClause);
2692  // prepare custom context for link generation (to allow for example time based previews)
2693  $context = clone GeneralUtility::makeInstance(Context::class);
2694  $additionalGetVars .= self::ADMCMD_previewCmds($pageInfo, $context);
2695 
2696  // Build the URL with a site as prefix, if configured
2697  $siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
2698  // Check if the page (= its rootline) has a site attached, otherwise just keep the URL as is
2699  $rootLine = $rootLine ?? ‪BackendUtility::BEgetRootLine($pageUid);
2700  try {
2701  $site = $siteFinder->getSiteByPageId((int)$pageUid, $rootLine);
2702  // Create a multi-dimensional array out of the additional get vars
2703  $additionalQueryParams = [];
2704  parse_str($additionalGetVars, $additionalQueryParams);
2705  if (isset($additionalQueryParams['L'])) {
2706  $additionalQueryParams['_language'] = $additionalQueryParams['_language'] ?? $additionalQueryParams['L'];
2707  unset($additionalQueryParams['L']);
2708  }
2709  $previewUrl = (string)$site->getRouter($context)->generateUri(
2710  $pageUid,
2711  $additionalQueryParams,
2712  $anchorSection,
2714  );
2715  } catch (SiteNotFoundException | \InvalidArgumentException | InvalidRouteArgumentsException $e) {
2716  $previewUrl = self::createPreviewUrl($pageUid, $rootLine, $anchorSection, $additionalGetVars, $viewScript);
2717  }
2718  }
2719 
2720  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['viewOnClickClass'] ?? [] as $className) {
2721  $hookObj = GeneralUtility::makeInstance($className);
2722  if (method_exists($hookObj, 'postProcess')) {
2723  $previewUrl = $hookObj->postProcess(
2724  $previewUrl,
2725  $pageUid,
2726  $rootLine,
2727  $anchorSection,
2728  $viewScript,
2729  $additionalGetVars,
2730  $switchFocus
2731  );
2732  }
2733  }
2734 
2735  return $previewUrl;
2736  }
2737 
2760  public static function wrapClickMenuOnIcon(
2761  $content,
2762  $table,
2763  $uid = 0,
2764  $context = '',
2765  $_addParams = '',
2766  $_enDisItems = '',
2767  $returnTagParameters = false
2768  ) {
2769  $tagParameters = [
2770  'class' => 't3js-contextmenutrigger',
2771  'data-table' => $table,
2772  'data-uid' => $uid,
2773  'data-context' => $context
2774  ];
2775 
2776  if ($returnTagParameters) {
2777  return $tagParameters;
2778  }
2779  return '<a href="#" ' . GeneralUtility::implodeAttributes($tagParameters, true) . '>' . $content . '</a>';
2780  }
2781 
2789  public static function getLinkToDataHandlerAction($parameters, $redirectUrl = '')
2790  {
2791  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2792  $url = (string)$uriBuilder->buildUriFromRoute('tce_db') . $parameters . '&redirect=';
2793  if ((int)$redirectUrl === -1) {
2794  $url = GeneralUtility::quoteJSvalue($url) . '+T3_THIS_LOCATION';
2795  } else {
2796  $url .= rawurlencode($redirectUrl ?: GeneralUtility::getIndpEnv('REQUEST_URI'));
2797  }
2798  return $url;
2799  }
2800 
2812  protected static function createPreviewUrl($pageUid, $rootLine, $anchorSection, $additionalGetVars, $viewScript)
2813  {
2814  // Look if a fixed preview language should be added:
2815  $beUser = static::getBackendUserAuthentication();
2816  $viewLanguageOrder = (string)($beUser->getTSConfig()['options.']['view.']['languageOrder'] ?? '');
2817 
2818  if (!empty($viewLanguageOrder)) {
2819  $suffix = '';
2820  // Find allowed languages (if none, all are allowed!)
2821  $allowedLanguages = null;
2822  if (!$beUser->isAdmin() && $beUser->groupData['allowed_languages'] !== '') {
2823  $allowedLanguages = array_flip(explode(',', $beUser->groupData['allowed_languages']));
2824  }
2825  // Traverse the view order, match first occurrence:
2826  $languageOrder = GeneralUtility::intExplode(',', $viewLanguageOrder);
2827  foreach ($languageOrder as $langUid) {
2828  if (is_array($allowedLanguages) && !empty($allowedLanguages)) {
2829  // Choose if set.
2830  if (isset($allowedLanguages[$langUid])) {
2831  $suffix = '&L=' . $langUid;
2832  break;
2833  }
2834  } else {
2835  // All allowed since no lang. are listed.
2836  $suffix = '&L=' . $langUid;
2837  break;
2838  }
2839  }
2840  // Add it
2841  $additionalGetVars .= $suffix;
2842  }
2843 
2844  // Check a mount point needs to be previewed
2845  $pageRepository = GeneralUtility::makeInstance(PageRepository::class);
2846  $mountPointInfo = $pageRepository->getMountPointInfo($pageUid);
2847 
2848  if ($mountPointInfo && $mountPointInfo['overlay']) {
2849  $pageUid = $mountPointInfo['mount_pid'];
2850  $additionalGetVars .= '&MP=' . $mountPointInfo['MPvar'];
2851  }
2852  $viewDomain = self::getViewDomain($pageUid, $rootLine);
2853 
2854  return $viewDomain . $viewScript . $pageUid . $additionalGetVars . $anchorSection;
2855  }
2856 
2865  public static function getViewDomain($pageId, $rootLine = null)
2866  {
2867  $domain = rtrim(GeneralUtility::getIndpEnv('TYPO3_SITE_URL'), '/');
2868  if (!is_array($rootLine)) {
2869  $rootLine = self::BEgetRootLine($pageId);
2870  }
2871  // Checks alternate domains
2872  if (!empty($rootLine)) {
2873  $protocol = GeneralUtility::getIndpEnv('TYPO3_SSL') ? 'https' : 'http';
2874  $previewDomainConfig = self::getPagesTSconfig($pageId)['TCEMAIN.']['previewDomain'] ?? '';
2875  $domainName = null;
2876  if (!empty($previewDomainConfig)) {
2877  if (strpos($previewDomainConfig, '://') !== false) {
2878  list($protocol, $domainName) = explode('://', $previewDomainConfig);
2879  } else {
2880  $domainName = $previewDomainConfig;
2881  }
2882  } else {
2883  $domainResolver = GeneralUtility::makeInstance(LegacyDomainResolver::class);
2884  foreach ($rootLine as $row) {
2885  $domainRecord = $domainResolver->matchRootPageId((int)$row['uid']);
2886  if (is_array($domainRecord)) {
2887  $domainName = rtrim($domainRecord['domainName'], '/');
2888  break;
2889  }
2890  }
2891  }
2892  if ($domainName === null) {
2893  // Fetch the "sys_domain" record: First, check for the given domain,
2894  // and find the "root page" = PseudoSite to that domain, then fetch the first
2895  // available sys_domain record.
2896  $siteMatcher = GeneralUtility::makeInstance(SiteMatcher::class);
2897  $result = $siteMatcher->matchRequest(new ServerRequest($domain));
2898  $site = $result->getSite();
2899  if ($site instanceof PseudoSite) {
2900  $domainName = (string)$site->getBase();
2901  $domainName = ltrim($domainName, '/');
2902  }
2903  }
2904 
2905  if ($domainName) {
2906  $domain = $protocol . '://' . $domainName;
2907  }
2908  // Append port number if lockSSLPort is not the standard port 443
2909  $portNumber = (int)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSLPort'];
2910  if ($portNumber > 0 && $portNumber !== 443 && $portNumber < 65536 && $protocol === 'https') {
2911  $domain .= ':' . strval($portNumber);
2912  }
2913  }
2914  return $domain;
2915  }
2916 
2926  public static function getModTSconfig($id, $TSref)
2927  {
2928  trigger_error(
2929  'BackendUtility::getModTSconfig() will be removed in TYPO3 v10.0.'
2930  . ' Use BackendUtility::getPagesTSconfig() to retrieve the full page TSconfig array instead.',
2931  E_USER_DEPRECATED
2932  );
2933  $beUser = static::getBackendUserAuthentication();
2934  $pageTS_modOptions = $beUser->getTSConfig($TSref, static::getPagesTSconfig($id));
2935  $BE_USER_modOptions = $beUser->getTSConfig($TSref);
2936  if ($BE_USER_modOptions['value'] === null) {
2937  unset($BE_USER_modOptions['value']);
2938  }
2939  ‪ArrayUtility::mergeRecursiveWithOverrule($pageTS_modOptions, $BE_USER_modOptions);
2940  return $pageTS_modOptions;
2941  }
2942 
2956  public static function getFuncMenu(
2957  $mainParams,
2958  $elementName,
2959  $currentValue,
2960  $menuItems,
2961  $script = '',
2962  $addParams = ''
2963  ) {
2964  if (!is_array($menuItems) || count($menuItems) <= 1) {
2965  return '';
2966  }
2967  $scriptUrl = self::buildScriptUrl($mainParams, $addParams, $script);
2968  $options = [];
2969  foreach ($menuItems as $value => $label) {
2970  $options[] = '<option value="'
2971  . htmlspecialchars($value) . '"'
2972  . ((string)$currentValue === (string)$value ? ' selected="selected"' : '') . '>'
2973  . htmlspecialchars($label, ENT_COMPAT, 'UTF-8', false) . '</option>';
2974  }
2975  $dataMenuIdentifier = str_replace(['SET[', ']'], '', $elementName);
2976  $dataMenuIdentifier = GeneralUtility::camelCaseToLowerCaseUnderscored($dataMenuIdentifier);
2977  $dataMenuIdentifier = str_replace('_', '-', $dataMenuIdentifier);
2978  if (!empty($options)) {
2979  $onChange = 'jumpToUrl(' . GeneralUtility::quoteJSvalue($scriptUrl . '&' . $elementName . '=') . '+this.options[this.selectedIndex].value,this);';
2980  return '
2981 
2982  <!-- Function Menu of module -->
2983  <select class="form-control" name="' . $elementName . '" onchange="' . htmlspecialchars($onChange) . '" data-menu-identifier="' . htmlspecialchars($dataMenuIdentifier) . '">
2984  ' . implode('
2985  ', $options) . '
2986  </select>
2987  ';
2988  }
2989  return '';
2990  }
2991 
3006  public static function getDropdownMenu(
3007  $mainParams,
3008  $elementName,
3009  $currentValue,
3010  $menuItems,
3011  $script = '',
3012  $addParams = ''
3013  ) {
3014  if (!is_array($menuItems) || count($menuItems) <= 1) {
3015  return '';
3016  }
3017  $scriptUrl = self::buildScriptUrl($mainParams, $addParams, $script);
3018  $options = [];
3019  foreach ($menuItems as $value => $label) {
3020  $options[] = '<option value="'
3021  . htmlspecialchars($value) . '"'
3022  . ((string)$currentValue === (string)$value ? ' selected="selected"' : '') . '>'
3023  . htmlspecialchars($label, ENT_COMPAT, 'UTF-8', false) . '</option>';
3024  }
3025  $dataMenuIdentifier = str_replace(['SET[', ']'], '', $elementName);
3026  $dataMenuIdentifier = GeneralUtility::camelCaseToLowerCaseUnderscored($dataMenuIdentifier);
3027  $dataMenuIdentifier = str_replace('_', '-', $dataMenuIdentifier);
3028  if (!empty($options)) {
3029  $onChange = 'jumpToUrl(' . GeneralUtility::quoteJSvalue($scriptUrl . '&' . $elementName . '=') . '+this.options[this.selectedIndex].value,this);';
3030  return '
3031  <div class="form-group">
3032  <!-- Function Menu of module -->
3033  <select class="form-control input-sm" name="' . htmlspecialchars($elementName) . '" onchange="' . htmlspecialchars($onChange) . '" data-menu-identifier="' . htmlspecialchars($dataMenuIdentifier) . '">
3034  ' . implode(LF, $options) . '
3035  </select>
3036  </div>
3037  ';
3038  }
3039  return '';
3040  }
3041 
3055  public static function getFuncCheck(
3056  $mainParams,
3057  $elementName,
3058  $currentValue,
3059  $script = '',
3060  $addParams = '',
3061  $tagParams = ''
3062  ) {
3063  $scriptUrl = self::buildScriptUrl($mainParams, $addParams, $script);
3064  $onClick = 'jumpToUrl(' . GeneralUtility::quoteJSvalue($scriptUrl . '&' . $elementName . '=') . '+(this.checked?1:0),this);';
3065 
3066  return
3067  '<input' .
3068  ' type="checkbox"' .
3069  ' class="checkbox"' .
3070  ' name="' . $elementName . '"' .
3071  ($currentValue ? ' checked="checked"' : '') .
3072  ' onclick="' . htmlspecialchars($onClick) . '"' .
3073  ($tagParams ? ' ' . $tagParams : '') .
3074  ' value="1"' .
3075  ' />';
3076  }
3077 
3091  public static function getFuncInput(
3092  $mainParams,
3093  $elementName,
3094  $currentValue,
3095  $size = 10,
3096  $script = '',
3097  $addParams = ''
3098  ) {
3099  $scriptUrl = self::buildScriptUrl($mainParams, $addParams, $script);
3100  $onChange = 'jumpToUrl(' . GeneralUtility::quoteJSvalue($scriptUrl . '&' . $elementName . '=') . '+escape(this.value),this);';
3101  return '<input type="text" class="form-control" name="' . $elementName . '" value="' . htmlspecialchars($currentValue) . '" onchange="' . htmlspecialchars($onChange) . '" />';
3102  }
3103 
3112  protected static function buildScriptUrl($mainParams, $addParams, $script = '')
3113  {
3114  if (!is_array($mainParams)) {
3115  $mainParams = ['id' => $mainParams];
3116  }
3117  if (!$script) {
3119  }
3120 
3121  if ($routePath = GeneralUtility::_GP('route')) {
3122  $uriBuilder = GeneralUtility::makeInstance(\‪TYPO3\CMS\Backend\Routing\UriBuilder::class);
3123  $scriptUrl = (string)$uriBuilder->buildUriFromRoutePath($routePath, $mainParams);
3124  $scriptUrl .= $addParams;
3125  } else {
3126  $scriptUrl = $script . ‪HttpUtility::buildQueryString($mainParams, '?') . $addParams;
3127  }
3128 
3129  return $scriptUrl;
3130  }
3131 
3142  public static function unsetMenuItems($modTSconfig, $itemArray, $TSref)
3143  {
3144  trigger_error('BackendUtility::getPidForModTSconfig() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
3145  // Getting TS-config options for this module for the Backend User:
3146  $conf = static::getBackendUserAuthentication()->getTSConfig($TSref, $modTSconfig);
3147  if (is_array($conf['properties'])) {
3148  foreach ($conf['properties'] as $key => $val) {
3149  if (!$val) {
3150  unset($itemArray[$key]);
3151  }
3152  }
3153  }
3154  return $itemArray;
3155  }
3156 
3165  public static function setUpdateSignal($set = '', $params = '')
3166  {
3167  $beUser = static::getBackendUserAuthentication();
3168  $modData = $beUser->getModuleData(
3169  \‪TYPO3\CMS\Backend\Utility\BackendUtility::class . '::getUpdateSignal',
3170  'ses'
3171  );
3172  if ($set) {
3173  $modData[$set] = [
3174  'set' => $set,
3175  'parameter' => $params
3176  ];
3177  } else {
3178  // clear the module data
3179  $modData = [];
3180  }
3181  $beUser->pushModuleData(\‪TYPO3\CMS\Backend\Utility\BackendUtility::class . '::getUpdateSignal', $modData);
3182  }
3183 
3191  public static function getUpdateSignalCode()
3192  {
3193  $signals = [];
3194  $modData = static::getBackendUserAuthentication()->getModuleData(
3195  \‪TYPO3\CMS\Backend\Utility\BackendUtility::class . '::getUpdateSignal',
3196  'ses'
3197  );
3198  if (empty($modData)) {
3199  return '';
3200  }
3201  // Hook: Allows to let TYPO3 execute your JS code
3202  $updateSignals = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['updateSignalHook'] ?? [];
3203  // Loop through all setUpdateSignals and get the JS code
3204  foreach ($modData as $set => $val) {
3205  if (isset($updateSignals[$set])) {
3206  $params = ['set' => $set, 'parameter' => $val['parameter'], 'JScode' => ''];
3207  $ref = null;
3208  GeneralUtility::callUserFunction($updateSignals[$set], $params, $ref);
3209  $signals[] = $params['JScode'];
3210  } else {
3211  switch ($set) {
3212  case 'updatePageTree':
3213  $signals[] = '
3214  if (top && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer.PageTree) {
3215  top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
3216  }
3217  ';
3218  break;
3219  case 'updateFolderTree':
3220  $signals[] = '
3221  if (top && top.nav_frame && top.nav_frame.location) {
3222  top.nav_frame.location.reload(true);
3223  }';
3224  break;
3225  case 'updateModuleMenu':
3226  $signals[] = '
3227  if (top && top.TYPO3.ModuleMenu && top.TYPO3.ModuleMenu.App) {
3228  top.TYPO3.ModuleMenu.App.refreshMenu();
3229  }';
3230  break;
3231  case 'updateTopbar':
3232  $signals[] = '
3233  if (top && top.TYPO3.Backend && top.TYPO3.Backend.Topbar) {
3234  top.TYPO3.Backend.Topbar.refresh();
3235  }';
3236  break;
3237  }
3238  }
3239  }
3240  $content = implode(LF, $signals);
3241  // For backwards compatibility, should be replaced
3242  self::setUpdateSignal();
3243  return $content;
3244  }
3245 
3260  public static function getModuleData(
3261  $MOD_MENU,
3262  $CHANGED_SETTINGS,
3263  $modName,
3264  $type = '',
3265  $dontValidateList = '',
3266  $setDefaultList = ''
3267  ) {
3268  if ($modName && is_string($modName)) {
3269  // Getting stored user-data from this module:
3270  $beUser = static::getBackendUserAuthentication();
3271  $settings = $beUser->getModuleData($modName, $type);
3272  $changed = 0;
3273  if (!is_array($settings)) {
3274  $changed = 1;
3275  $settings = [];
3276  }
3277  if (is_array($MOD_MENU)) {
3278  foreach ($MOD_MENU as $key => $var) {
3279  // If a global var is set before entering here. eg if submitted, then it's substituting the current value the array.
3280  if (is_array($CHANGED_SETTINGS) && isset($CHANGED_SETTINGS[$key])) {
3281  if (is_array($CHANGED_SETTINGS[$key])) {
3282  $serializedSettings = serialize($CHANGED_SETTINGS[$key]);
3283  if ((string)$settings[$key] !== $serializedSettings) {
3284  $settings[$key] = $serializedSettings;
3285  $changed = 1;
3286  }
3287  } else {
3288  if ((string)$settings[$key] !== (string)$CHANGED_SETTINGS[$key]) {
3289  $settings[$key] = $CHANGED_SETTINGS[$key];
3290  $changed = 1;
3291  }
3292  }
3293  }
3294  // If the $var is an array, which denotes the existence of a menu, we check if the value is permitted
3295  if (is_array($var) && (!$dontValidateList || !GeneralUtility::inList($dontValidateList, $key))) {
3296  // If the setting is an array or not present in the menu-array, MOD_MENU, then the default value is inserted.
3297  if (is_array($settings[$key]) || !isset($MOD_MENU[$key][$settings[$key]])) {
3298  $settings[$key] = (string)key($var);
3299  $changed = 1;
3300  }
3301  }
3302  // Sets default values (only strings/checkboxes, not menus)
3303  if ($setDefaultList && !is_array($var)) {
3304  if (GeneralUtility::inList($setDefaultList, $key) && !isset($settings[$key])) {
3305  $settings[$key] = (string)$var;
3306  }
3307  }
3308  }
3309  } else {
3310  die('No menu!');
3311  }
3312  if ($changed) {
3313  $beUser->pushModuleData($modName, $settings);
3314  }
3315  return $settings;
3316  }
3317  die('Wrong module name: "' . $modName . '"');
3318  }
3319 
3328  public static function getModuleUrl($moduleName, $urlParameters = [])
3329  {
3330  trigger_error('BackendUtility::getModuleUrl() will be removed in TYPO3 v10.0, use UriBuilder->buildUriFromRoute() instead.', E_USER_DEPRECATED);
3331  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
3332  try {
3333  $uri = $uriBuilder->buildUriFromRoute($moduleName, $urlParameters);
3334  } catch (\‪TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException $e) {
3335  $uri = $uriBuilder->buildUriFromRoutePath($moduleName, $urlParameters);
3336  }
3337  return (string)$uri;
3338  }
3339 
3340  /*******************************************
3341  *
3342  * Core
3343  *
3344  *******************************************/
3354  public static function lockRecords($table = '', $uid = 0, $pid = 0)
3355  {
3356  $beUser = static::getBackendUserAuthentication();
3357  if (isset($beUser->user['uid'])) {
3358  $userId = (int)$beUser->user['uid'];
3359  if ($table && $uid) {
3360  $fieldsValues = [
3361  'userid' => $userId,
3362  'feuserid' => 0,
3363  'tstamp' => ‪$GLOBALS['EXEC_TIME'],
3364  'record_table' => $table,
3365  'record_uid' => $uid,
3366  'username' => $beUser->user['username'],
3367  'record_pid' => $pid
3368  ];
3369  GeneralUtility::makeInstance(ConnectionPool::class)
3370  ->getConnectionForTable('sys_lockedrecords')
3371  ->insert(
3372  'sys_lockedrecords',
3373  $fieldsValues
3374  );
3375  } else {
3376  GeneralUtility::makeInstance(ConnectionPool::class)
3377  ->getConnectionForTable('sys_lockedrecords')
3378  ->delete(
3379  'sys_lockedrecords',
3380  ['userid' => (int)$userId]
3381  );
3382  }
3383  }
3384  }
3385 
3398  public static function isRecordLocked($table, $uid)
3399  {
3400  $runtimeCache = self::getRuntimeCache();
3401  $cacheId = 'backend-recordLocked';
3402  $recordLockedCache = $runtimeCache->get($cacheId);
3403  if ($recordLockedCache !== false) {
3404  $lockedRecords = $recordLockedCache;
3405  } else {
3406  $lockedRecords = [];
3407 
3408  $queryBuilder = static::getQueryBuilderForTable('sys_lockedrecords');
3409  $result = $queryBuilder
3410  ->select('*')
3411  ->from('sys_lockedrecords')
3412  ->where(
3413  $queryBuilder->expr()->neq(
3414  'sys_lockedrecords.userid',
3415  $queryBuilder->createNamedParameter(
3416  static::getBackendUserAuthentication()->user['uid'],
3417  \PDO::PARAM_INT
3418  )
3419  ),
3420  $queryBuilder->expr()->gt(
3421  'sys_lockedrecords.tstamp',
3422  $queryBuilder->createNamedParameter(
3423  ‪$GLOBALS['EXEC_TIME'] - 2 * 3600,
3424  \PDO::PARAM_INT
3425  )
3426  )
3427  )
3428  ->execute();
3429 
3430  $lang = static::getLanguageService();
3431  while ($row = $result->fetch()) {
3432  // Get the type of the user that locked this record:
3433  if ($row['userid']) {
3434  $userTypeLabel = 'beUser';
3435  } elseif ($row['feuserid']) {
3436  $userTypeLabel = 'feUser';
3437  } else {
3438  $userTypeLabel = 'user';
3439  }
3440  $userType = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.' . $userTypeLabel);
3441  // Get the username (if available):
3442  if ($row['username']) {
3443  $userName = $row['username'];
3444  } else {
3445  $userName = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.unknownUser');
3446  }
3447  $lockedRecords[$row['record_table'] . ':' . $row['record_uid']] = $row;
3448  $lockedRecords[$row['record_table'] . ':' . $row['record_uid']]['msg'] = sprintf(
3449  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.lockedRecordUser'),
3450  $userType,
3451  $userName,
3452  self::calcAge(
3453  ‪$GLOBALS['EXEC_TIME'] - $row['tstamp'],
3454  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.minutesHoursDaysYears')
3455  )
3456  );
3457  if ($row['record_pid'] && !isset($lockedRecords[$row['record_table'] . ':' . $row['record_pid']])) {
3458  $lockedRecords['pages:' . $row['record_pid']]['msg'] = sprintf(
3459  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.lockedRecordUser_content'),
3460  $userType,
3461  $userName,
3462  self::calcAge(
3463  ‪$GLOBALS['EXEC_TIME'] - $row['tstamp'],
3464  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.minutesHoursDaysYears')
3465  )
3466  );
3467  }
3468  }
3469  $runtimeCache->set($cacheId, $lockedRecords);
3470  }
3471 
3472  return $lockedRecords[$table . ':' . $uid] ?? false;
3473  }
3474 
3483  public static function getTCEFORM_TSconfig($table, $row)
3484  {
3485  self::fixVersioningPid($table, $row);
3486  $res = [];
3487  // Get main config for the table
3488  list($TScID, $cPid) = self::getTSCpid($table, $row['uid'], $row['pid']);
3489  if ($TScID >= 0) {
3490  $tsConfig = static::getPagesTSconfig($TScID)['TCEFORM.'][$table . '.'] ?? [];
3491  $typeVal = self::getTCAtypeValue($table, $row);
3492  foreach ($tsConfig as $key => $val) {
3493  if (is_array($val)) {
3494  $fieldN = substr($key, 0, -1);
3495  $res[$fieldN] = $val;
3496  unset($res[$fieldN]['types.']);
3497  if ((string)$typeVal !== '' && is_array($val['types.'][$typeVal . '.'])) {
3498  ‪ArrayUtility::mergeRecursiveWithOverrule($res[$fieldN], $val['types.'][$typeVal . '.']);
3499  }
3500  }
3501  }
3502  }
3503  $res['_CURRENT_PID'] = $cPid;
3504  $res['_THIS_UID'] = $row['uid'];
3505  // So the row will be passed to foreign_table_where_query()
3506  $res['_THIS_ROW'] = $row;
3507  return $res;
3508  }
3509 
3523  public static function getTSconfig_pidValue($table, $uid, $pid)
3524  {
3525  // If pid is an integer this takes precedence in our lookup.
3527  $thePidValue = (int)$pid;
3528  // If ref to another record, look that record up.
3529  if ($thePidValue < 0) {
3530  $pidRec = self::getRecord($table, abs($thePidValue), 'pid');
3531  $thePidValue = is_array($pidRec) ? $pidRec['pid'] : -2;
3532  }
3533  } else {
3534  // Try to fetch the record pid from uid. If the uid is 'NEW...' then this will of course return nothing
3535  $rr = self::getRecord($table, $uid);
3536  $thePidValue = null;
3537  if (is_array($rr)) {
3538  // First check if the pid is -1 which means it is a workspaced element. Get the "real" record:
3539  if ($rr['pid'] == '-1') {
3540  $rr = self::getRecord($table, $rr['t3ver_oid'], 'pid');
3541  if (is_array($rr)) {
3542  $thePidValue = $rr['pid'];
3543  }
3544  } else {
3545  // Returning the "pid" of the record
3546  $thePidValue = $rr['pid'];
3547  }
3548  }
3549  if (!$thePidValue) {
3550  // Returns -1 if the record with this pid was not found.
3551  $thePidValue = -1;
3552  }
3553  }
3554  return $thePidValue;
3555  }
3556 
3567  public static function getPidForModTSconfig($table, $uid, $pid)
3568  {
3569  trigger_error('BackendUtility::getPidForModTSconfig() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
3570  return $table === 'pages' && ‪MathUtility::canBeInterpretedAsInteger($uid) ? $uid : $pid;
3571  }
3572 
3585  public static function getTSCpidCached($table, $uid, $pid)
3586  {
3587  $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
3588  $firstLevelCache = $runtimeCache->get('backendUtilityTscPidCached') ?: [];
3589  $key = $table . ':' . $uid . ':' . $pid;
3590  if (!isset($firstLevelCache[$key])) {
3591  $firstLevelCache[$key] = static::getTSCpid($table, $uid, $pid);
3592  $runtimeCache->set('backendUtilityTscPidCached', $firstLevelCache);
3593  }
3594  return $firstLevelCache[$key];
3595  }
3596 
3608  public static function getTSCpid($table, $uid, $pid)
3609  {
3610  // If pid is negative (referring to another record) the pid of the other record is fetched and returned.
3611  $cPid = self::getTSconfig_pidValue($table, $uid, $pid);
3612  // $TScID is the id of $table = pages, else it's the pid of the record.
3613  $TScID = $table === 'pages' && ‪MathUtility::canBeInterpretedAsInteger($uid) ? $uid : $cPid;
3614  return [$TScID, $cPid];
3615  }
3616 
3624  public static function firstDomainRecord($rootLine)
3625  {
3626  trigger_error('BackendUtility::firstDomainRecord() will be removed in TYPO3 v10.0. Use the new LigetDomainStartPagenk Generation functionality instead.', E_USER_DEPRECATED);
3627  $domainResolver = GeneralUtility::makeInstance(LegacyDomainResolver::class);
3628  foreach ($rootLine as $row) {
3629  $domain = $domainResolver->matchRootPageId($row['uid']);
3630  if (is_array($domain)) {
3631  return rtrim($domain['domainName'], '/');
3632  }
3633  }
3634  return null;
3635  }
3636 
3645  public static function getDomainStartPage($domain, $path = '')
3646  {
3647  trigger_error('BackendUtility::getDomainStartPage() will be removed in TYPO3 v10.0. Use the new Link Generation functionality instead.', E_USER_DEPRECATED);
3648  $domain = explode(':', $domain);
3649  $domain = strtolower(preg_replace('/\\.$/', '', $domain[0]));
3650  // Path is calculated.
3651  $path = trim(preg_replace('/\\/[^\\/]*$/', '', $path));
3652  // Stuff
3653  $domain .= $path;
3654 
3655  $queryBuilder = static::getQueryBuilderForTable('sys_domain');
3656  $queryBuilder->getRestrictions()
3657  ->removeAll()
3658  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
3659 
3660  $result = $queryBuilder
3661  ->select('sys_domain.*')
3662  ->from('sys_domain')
3663  ->from('pages')
3664  ->where(
3665  $queryBuilder->expr()->eq(
3666  'sys_domain.pid',
3667  $queryBuilder->quoteIdentifier('pages.uid')
3668  ),
3669  $queryBuilder->expr()->orX(
3670  $queryBuilder->expr()->eq(
3671  'sys_domain.domainName',
3672  $queryBuilder->createNamedParameter($domain, \PDO::PARAM_STR)
3673  ),
3674  $queryBuilder->expr()->eq(
3675  'sys_domain.domainName',
3676  $queryBuilder->createNamedParameter($domain . '/', \PDO::PARAM_STR)
3677  )
3678  )
3679  )
3680  ->execute()
3681  ->fetch();
3682 
3683  return $result;
3684  }
3685 
3693  public static function &softRefParserObj($spKey)
3694  {
3695  // If no softRef parser object has been set previously, try to create it:
3696  if (!isset(‪$GLOBALS['T3_VAR']['softRefParser'][$spKey])) {
3697  // Set the object string to blank by default:
3698  ‪$GLOBALS['T3_VAR']['softRefParser'][$spKey] = '';
3699  // Now, try to create parser object:
3700  $objRef = null;
3701  if (isset(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser'][$spKey])) {
3702  $className = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser'][$spKey];
3703  if ($className) {
3704  ‪$GLOBALS['T3_VAR']['softRefParser'][$spKey] = GeneralUtility::makeInstance($className);
3705  }
3706  }
3707  }
3708  // Return RTE object (if any!)
3709  return ‪$GLOBALS['T3_VAR']['softRefParser'][$spKey];
3710  }
3711 
3717  protected static function getRuntimeCache()
3718  {
3719  return GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
3720  }
3721 
3729  public static function explodeSoftRefParserList($parserList)
3730  {
3731  // Return immediately if list is blank:
3732  if ((string)$parserList === '') {
3733  return false;
3734  }
3735 
3736  $runtimeCache = self::getRuntimeCache();
3737  $cacheId = 'backend-softRefList-' . md5($parserList);
3738  $parserListCache = $runtimeCache->get($cacheId);
3739  if ($parserListCache !== false) {
3740  return $parserListCache;
3741  }
3742 
3743  // Otherwise parse the list:
3744  $keyList = GeneralUtility::trimExplode(',', $parserList, true);
3745  ‪$output = [];
3746  foreach ($keyList as $val) {
3747  $reg = [];
3748  if (preg_match('/^([[:alnum:]_-]+)\\[(.*)\\]$/', $val, $reg)) {
3749  ‪$output[$reg[1]] = GeneralUtility::trimExplode(';', $reg[2], true);
3750  } else {
3751  ‪$output[$val] = '';
3752  }
3753  }
3754  $runtimeCache->set($cacheId, ‪$output);
3755  return ‪$output;
3756  }
3757 
3764  public static function isModuleSetInTBE_MODULES($modName)
3765  {
3766  $loaded = [];
3767  foreach (‪$GLOBALS['TBE_MODULES'] as $mkey => $list) {
3768  $loaded[$mkey] = 1;
3769  if (!is_array($list) && trim($list)) {
3770  $subList = GeneralUtility::trimExplode(',', $list, true);
3771  foreach ($subList as $skey) {
3772  $loaded[$mkey . '_' . $skey] = 1;
3773  }
3774  }
3775  }
3776  return $modName && isset($loaded[$modName]);
3777  }
3778 
3788  public static function referenceCount($table, $ref, $msg = '', $count = null)
3789  {
3790  if ($count === null) {
3791 
3792  // Build base query
3793  $queryBuilder = static::getQueryBuilderForTable('sys_refindex');
3794  $queryBuilder
3795  ->count('*')
3796  ->from('sys_refindex')
3797  ->where(
3798  $queryBuilder->expr()->eq('ref_table', $queryBuilder->createNamedParameter($table, \PDO::PARAM_STR)),
3799  $queryBuilder->expr()->eq('deleted', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
3800  );
3801 
3802  // Look up the path:
3803  if ($table === '_FILE') {
3804  if (!GeneralUtility::isFirstPartOfStr($ref, ‪Environment::getPublicPath())) {
3805  return '';
3806  }
3807 
3809  $queryBuilder->andWhere(
3810  $queryBuilder->expr()->eq('ref_string', $queryBuilder->createNamedParameter($ref, \PDO::PARAM_STR))
3811  );
3812  } else {
3813  $queryBuilder->andWhere(
3814  $queryBuilder->expr()->eq('ref_uid', $queryBuilder->createNamedParameter($ref, \PDO::PARAM_INT))
3815  );
3816  if ($table === 'sys_file') {
3817  $queryBuilder->andWhere($queryBuilder->expr()->neq('tablename', $queryBuilder->quote('sys_file_metadata')));
3818  }
3819  }
3820 
3821  $count = $queryBuilder->execute()->fetchColumn(0);
3822  }
3823 
3824  if ($count) {
3825  return $msg ? sprintf($msg, $count) : $count;
3826  }
3827  return $msg ? '' : 0;
3828  }
3829 
3838  public static function translationCount($table, $ref, $msg = '')
3839  {
3840  $count = null;
3841  if (‪$GLOBALS['TCA'][$table]['ctrl']['languageField']
3842  && ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']
3843  ) {
3844  $queryBuilder = static::getQueryBuilderForTable($table);
3845  $queryBuilder->getRestrictions()
3846  ->removeAll()
3847  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
3848 
3849  $count = (int)$queryBuilder
3850  ->count('*')
3851  ->from($table)
3852  ->where(
3853  $queryBuilder->expr()->eq(
3854  ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'],
3855  $queryBuilder->createNamedParameter($ref, \PDO::PARAM_INT)
3856  ),
3857  $queryBuilder->expr()->neq(
3858  ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'],
3859  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
3860  )
3861  )
3862  ->execute()
3863  ->fetchColumn(0);
3864  }
3865 
3866  if ($count && $msg) {
3867  return sprintf($msg, $count);
3868  }
3869 
3870  if ($count) {
3871  return $msg ? sprintf($msg, $count) : $count;
3872  }
3873  return $msg ? '' : 0;
3874  }
3875 
3876  /*******************************************
3877  *
3878  * Workspaces / Versioning
3879  *
3880  *******************************************/
3892  public static function selectVersionsOfRecord(
3893  $table,
3894  $uid,
3895  ‪$fields = '*',
3896  $workspace = 0,
3897  $includeDeletedRecords = false,
3898  $row = null
3899  ) {
3900  $realPid = 0;
3901  $outputRows = [];
3902  if (‪$GLOBALS['TCA'][$table] && static::isTableWorkspaceEnabled($table)) {
3903  if (is_array($row) && !$includeDeletedRecords) {
3904  $row['_CURRENT_VERSION'] = true;
3905  $realPid = $row['pid'];
3906  $outputRows[] = $row;
3907  } else {
3908  // Select UID version:
3909  $row = self::getRecord($table, $uid, ‪$fields, '', !$includeDeletedRecords);
3910  // Add rows to output array:
3911  if ($row) {
3912  $row['_CURRENT_VERSION'] = true;
3913  $realPid = $row['pid'];
3914  $outputRows[] = $row;
3915  }
3916  }
3917 
3918  $queryBuilder = static::getQueryBuilderForTable($table);
3919  $queryBuilder->getRestrictions()->removeAll();
3920 
3921  // build fields to select
3922  $queryBuilder->select(...GeneralUtility::trimExplode(',', ‪$fields));
3923 
3924  $queryBuilder
3925  ->from($table)
3926  ->where(
3927  $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT)),
3928  $queryBuilder->expr()->neq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)),
3929  $queryBuilder->expr()->eq('t3ver_oid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))
3930  )
3931  ->orderBy('t3ver_id', 'DESC');
3932 
3933  if (!$includeDeletedRecords) {
3934  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
3935  }
3936 
3937  if ($workspace === 0) {
3938  // Only in Live WS
3939  $queryBuilder->andWhere(
3940  $queryBuilder->expr()->eq(
3941  't3ver_wsid',
3942  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
3943  )
3944  );
3945  } elseif ($workspace !== null) {
3946  // In Live WS and Workspace with given ID
3947  $queryBuilder->andWhere(
3948  $queryBuilder->expr()->in(
3949  't3ver_wsid',
3950  $queryBuilder->createNamedParameter([0, (int)$workspace], Connection::PARAM_INT_ARRAY)
3951  )
3952  );
3953  }
3954 
3955  $rows = $queryBuilder->execute()->fetchAll();
3956 
3957  // Add rows to output array:
3958  if (is_array($rows)) {
3959  $outputRows = array_merge($outputRows, $rows);
3960  }
3961  // Set real-pid:
3962  foreach ($outputRows as $idx => $oRow) {
3963  $outputRows[$idx]['_REAL_PID'] = $realPid;
3964  }
3965  return $outputRows;
3966  }
3967  return null;
3968  }
3969 
3987  public static function fixVersioningPid($table, &$rr, $ignoreWorkspaceMatch = false)
3988  {
3989  if (!‪ExtensionManagementUtility::isLoaded('workspaces')) {
3990  return;
3991  }
3992  // Check that the input record is an offline version from a table that supports versioning:
3993  if (is_array($rr) && $rr['pid'] == -1 && static::isTableWorkspaceEnabled($table)) {
3994  // Check values for t3ver_oid and t3ver_wsid:
3995  if (isset($rr['t3ver_oid']) && isset($rr['t3ver_wsid'])) {
3996  // If "t3ver_oid" is already a field, just set this:
3997  $oid = $rr['t3ver_oid'];
3998  $wsid = $rr['t3ver_wsid'];
3999  } else {
4000  $oid = 0;
4001  $wsid = 0;
4002  // Otherwise we have to expect "uid" to be in the record and look up based on this:
4003  $newPidRec = self::getRecord($table, $rr['uid'], 't3ver_oid,t3ver_wsid');
4004  if (is_array($newPidRec)) {
4005  $oid = $newPidRec['t3ver_oid'];
4006  $wsid = $newPidRec['t3ver_wsid'];
4007  }
4008  }
4009  // If ID of current online version is found, look up the PID value of that:
4010  if ($oid
4011  && ($ignoreWorkspaceMatch || (static::getBackendUserAuthentication() instanceof BackendUserAuthentication && (int)$wsid === (int)static::getBackendUserAuthentication()->workspace))
4012  ) {
4013  $oidRec = self::getRecord($table, $oid, 'pid');
4014  if (is_array($oidRec)) {
4015  $rr['_ORIG_pid'] = $rr['pid'];
4016  $rr['pid'] = $oidRec['pid'];
4017  }
4018  // Use target PID in case of move pointer
4019  if (
4020  !isset($rr['t3ver_state'])
4021  || ‪VersionState::cast($rr['t3ver_state'])->equals(‪VersionState::MOVE_POINTER)
4022  ) {
4023  $movePlaceholder = self::getMovePlaceholder($table, $oid, 'pid');
4024  if ($movePlaceholder) {
4025  $rr['_ORIG_pid'] = $rr['pid'];
4026  $rr['pid'] = $movePlaceholder['pid'];
4027  }
4028  }
4029  }
4030  }
4031  }
4032 
4049  public static function workspaceOL($table, &$row, $wsid = -99, $unsetMovePointers = false)
4050  {
4051  if (!‪ExtensionManagementUtility::isLoaded('workspaces')) {
4052  return;
4053  }
4054  // If this is FALSE the placeholder is shown raw in the backend.
4055  // I don't know if this move can be useful for users to toggle. Technically it can help debugging.
4056  $previewMovePlaceholders = true;
4057  // Initialize workspace ID
4058  if ($wsid == -99 && static::getBackendUserAuthentication() instanceof BackendUserAuthentication) {
4059  $wsid = static::getBackendUserAuthentication()->workspace;
4060  }
4061  // Check if workspace is different from zero and record is set:
4062  if ($wsid !== 0 && is_array($row)) {
4063  // Check if input record is a move-placeholder and if so, find the pointed-to live record:
4064  $movePldSwap = null;
4065  $orig_uid = 0;
4066  $orig_pid = 0;
4067  if ($previewMovePlaceholders) {
4068  $orig_uid = $row['uid'];
4069  $orig_pid = $row['pid'];
4070  $movePldSwap = self::movePlhOL($table, $row);
4071  }
4072  $wsAlt = self::getWorkspaceVersionOfRecord(
4073  $wsid,
4074  $table,
4075  $row['uid'],
4076  implode(',', static::purgeComputedPropertyNames(array_keys($row)))
4077  );
4078  // If version was found, swap the default record with that one.
4079  if (is_array($wsAlt)) {
4080  // Check if this is in move-state:
4081  if ($previewMovePlaceholders && !$movePldSwap && static::isTableWorkspaceEnabled($table) && $unsetMovePointers) {
4082  // Only for WS ver 2... (moving)
4083  // If t3ver_state is not found, then find it... (but we like best if it is here...)
4084  if (!isset($wsAlt['t3ver_state'])) {
4085  $stateRec = self::getRecord($table, $wsAlt['uid'], 't3ver_state');
4086  $versionState = ‪VersionState::cast($stateRec['t3ver_state']);
4087  } else {
4088  $versionState = ‪VersionState::cast($wsAlt['t3ver_state']);
4089  }
4090  if ($versionState->equals(‪VersionState::MOVE_POINTER)) {
4091  // @todo Same problem as frontend in versionOL(). See TODO point there.
4092  $row = false;
4093  return;
4094  }
4095  }
4096  // Always correct PID from -1 to what it should be
4097  if (isset($wsAlt['pid'])) {
4098  // Keep the old (-1) - indicates it was a version.
4099  $wsAlt['_ORIG_pid'] = $wsAlt['pid'];
4100  // Set in the online versions PID.
4101  $wsAlt['pid'] = $row['pid'];
4102  }
4103  // For versions of single elements or page+content, swap UID and PID
4104  $wsAlt['_ORIG_uid'] = $wsAlt['uid'];
4105  $wsAlt['uid'] = $row['uid'];
4106  // Backend css class:
4107  $wsAlt['_CSSCLASS'] = 'ver-element';
4108  // Changing input record to the workspace version alternative:
4109  $row = $wsAlt;
4110  }
4111  // If the original record was a move placeholder, the uid and pid of that is preserved here:
4112  if ($movePldSwap) {
4113  $row['_MOVE_PLH'] = true;
4114  $row['_MOVE_PLH_uid'] = $orig_uid;
4115  $row['_MOVE_PLH_pid'] = $orig_pid;
4116  // For display; To make the icon right for the placeholder vs. the original
4117  $row['t3ver_state'] = (string)new VersionState(‪VersionState::MOVE_PLACEHOLDER);
4118  }
4119  }
4120  }
4121 
4131  public static function movePlhOL($table, &$row)
4132  {
4133  if (static::isTableWorkspaceEnabled($table)) {
4134  // If t3ver_move_id or t3ver_state is not found, then find it... (but we like best if it is here...)
4135  if (!isset($row['t3ver_move_id']) || !isset($row['t3ver_state'])) {
4136  $moveIDRec = self::getRecord($table, $row['uid'], 't3ver_move_id, t3ver_state');
4137  $moveID = $moveIDRec['t3ver_move_id'];
4138  $versionState = ‪VersionState::cast($moveIDRec['t3ver_state']);
4139  } else {
4140  $moveID = $row['t3ver_move_id'];
4141  $versionState = ‪VersionState::cast($row['t3ver_state']);
4142  }
4143  // Find pointed-to record.
4144  if ($versionState->equals(‪VersionState::MOVE_PLACEHOLDER) && $moveID) {
4145  if ($origRow = self::getRecord(
4146  $table,
4147  $moveID,
4148  implode(',', static::purgeComputedPropertyNames(array_keys($row)))
4149  )) {
4150  $row = $origRow;
4151  return true;
4152  }
4153  }
4154  }
4155  return false;
4156  }
4157 
4167  public static function getWorkspaceVersionOfRecord($workspace, $table, $uid, ‪$fields = '*')
4168  {
4169  if (‪ExtensionManagementUtility::isLoaded('workspaces')) {
4170  if ($workspace !== 0 && self::isTableWorkspaceEnabled($table)) {
4171 
4172  // Select workspace version of record:
4173  $queryBuilder = static::getQueryBuilderForTable($table);
4174  $queryBuilder->getRestrictions()
4175  ->removeAll()
4176  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
4177 
4178  // build fields to select
4179  $queryBuilder->select(...GeneralUtility::trimExplode(',', ‪$fields));
4180 
4181  $row = $queryBuilder
4182  ->from($table)
4183  ->where(
4184  $queryBuilder->expr()->eq(
4185  'pid',
4186  $queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT)
4187  ),
4188  $queryBuilder->expr()->eq(
4189  't3ver_oid',
4190  $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
4191  ),
4192  $queryBuilder->expr()->eq(
4193  't3ver_wsid',
4194  $queryBuilder->createNamedParameter($workspace, \PDO::PARAM_INT)
4195  )
4196  )
4197  ->execute()
4198  ->fetch();
4199 
4200  return $row;
4201  }
4202  }
4203  return false;
4204  }
4205 
4214  public static function getLiveVersionOfRecord($table, $uid, ‪$fields = '*')
4215  {
4216  $liveVersionId = self::getLiveVersionIdOfRecord($table, $uid);
4217  if ($liveVersionId !== null) {
4218  return self::getRecord($table, $liveVersionId, ‪$fields);
4219  }
4220  return null;
4221  }
4222 
4230  public static function getLiveVersionIdOfRecord($table, $uid)
4231  {
4232  if (!‪ExtensionManagementUtility::isLoaded('workspaces')) {
4233  return null;
4234  }
4235  $liveVersionId = null;
4236  if (self::isTableWorkspaceEnabled($table)) {
4237  $currentRecord = self::getRecord($table, $uid, 'pid,t3ver_oid');
4238  if (is_array($currentRecord) && $currentRecord['pid'] == -1) {
4239  $liveVersionId = $currentRecord['t3ver_oid'];
4240  }
4241  }
4242  return $liveVersionId;
4243  }
4244 
4252  public static function versioningPlaceholderClause($table)
4253  {
4254  if (static::isTableWorkspaceEnabled($table) && static::getBackendUserAuthentication() instanceof BackendUserAuthentication) {
4255  $currentWorkspace = (int)static::getBackendUserAuthentication()->workspace;
4256  return ' AND (' . $table . '.t3ver_state <= ' . new VersionState(‪VersionState::DEFAULT_STATE) . ' OR ' . $table . '.t3ver_wsid = ' . $currentWorkspace . ')';
4257  }
4258  return '';
4259  }
4260 
4268  public static function getWorkspaceWhereClause($table, $workspaceId = null)
4269  {
4270  $whereClause = '';
4271  if (self::isTableWorkspaceEnabled($table) && static::getBackendUserAuthentication() instanceof BackendUserAuthentication) {
4272  if ($workspaceId === null) {
4273  $workspaceId = static::getBackendUserAuthentication()->workspace;
4274  }
4275  $workspaceId = (int)$workspaceId;
4276  $pidOperator = $workspaceId === 0 ? '!=' : '=';
4277  $whereClause = ' AND ' . $table . '.t3ver_wsid=' . $workspaceId . ' AND ' . $table . '.pid' . $pidOperator . '-1';
4278  }
4279  return $whereClause;
4280  }
4281 
4289  public static function wsMapId($table, $uid)
4290  {
4291  $wsRec = null;
4292  if (static::getBackendUserAuthentication() instanceof BackendUserAuthentication) {
4293  $wsRec = self::getWorkspaceVersionOfRecord(
4294  static::getBackendUserAuthentication()->workspace,
4295  $table,
4296  $uid,
4297  'uid'
4298  );
4299  }
4300  return is_array($wsRec) ? $wsRec['uid'] : $uid;
4301  }
4302 
4312  public static function getMovePlaceholder($table, $uid, ‪$fields = '*', $workspace = null)
4313  {
4314  if ($workspace === null && static::getBackendUserAuthentication() instanceof BackendUserAuthentication) {
4315  $workspace = static::getBackendUserAuthentication()->workspace;
4316  }
4317  if ((int)$workspace !== 0 && ‪$GLOBALS['TCA'][$table] && static::isTableWorkspaceEnabled($table)) {
4318  // Select workspace version of record:
4319  $queryBuilder = static::getQueryBuilderForTable($table);
4320  $queryBuilder->getRestrictions()
4321  ->removeAll()
4322  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
4323 
4324  $row = $queryBuilder
4325  ->select(...GeneralUtility::trimExplode(',', ‪$fields, true))
4326  ->from($table)
4327  ->where(
4328  $queryBuilder->expr()->neq(
4329  'pid',
4330  $queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT)
4331  ),
4332  $queryBuilder->expr()->eq(
4333  't3ver_state',
4334  $queryBuilder->createNamedParameter(
4335  (string)new VersionState(‪VersionState::MOVE_PLACEHOLDER),
4336  \PDO::PARAM_INT
4337  )
4338  ),
4339  $queryBuilder->expr()->eq(
4340  't3ver_move_id',
4341  $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
4342  ),
4343  $queryBuilder->expr()->eq(
4344  't3ver_wsid',
4345  $queryBuilder->createNamedParameter($workspace, \PDO::PARAM_INT)
4346  )
4347  )
4348  ->execute()
4349  ->fetch();
4350 
4351  return $row ?: false;
4352  }
4353  return false;
4354  }
4355 
4356  /*******************************************
4357  *
4358  * Miscellaneous
4359  *
4360  *******************************************/
4371  public static function TYPO3_copyRightNotice()
4372  {
4373  // Copyright Notice
4374  $loginCopyrightWarrantyProvider = strip_tags(trim(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['loginCopyrightWarrantyProvider']));
4375  $loginCopyrightWarrantyURL = strip_tags(trim(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['loginCopyrightWarrantyURL']));
4376 
4377  $lang = static::getLanguageService();
4378 
4379  if (strlen($loginCopyrightWarrantyProvider) >= 2 && strlen($loginCopyrightWarrantyURL) >= 10) {
4380  $warrantyNote = sprintf(
4381  $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_login.xlf:warranty.by'),
4382  htmlspecialchars($loginCopyrightWarrantyProvider),
4383  '<a href="' . htmlspecialchars($loginCopyrightWarrantyURL) . '" target="_blank" rel="noopener noreferrer">',
4384  '</a>'
4385  );
4386  } else {
4387  $warrantyNote = sprintf(
4388  $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_login.xlf:no.warranty'),
4389  '<a href="' . TYPO3_URL_LICENSE . '" target="_blank" rel="noopener noreferrer">',
4390  '</a>'
4391  );
4392  }
4393  $cNotice = '<a href="' . TYPO3_URL_GENERAL . '" target="_blank" rel="noopener noreferrer">' .
4394  $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_login.xlf:typo3.cms') . '</a>. ' .
4395  $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_login.xlf:copyright') . ' &copy; '
4396  . htmlspecialchars(TYPO3_copyright_year) . ' Kasper Sk&aring;rh&oslash;j. ' .
4397  $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_login.xlf:extension.copyright') . ' ' .
4398  sprintf(
4399  $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_login.xlf:details.link'),
4400  '<a href="' . TYPO3_URL_GENERAL . '" target="_blank" rel="noopener noreferrer">' . TYPO3_URL_GENERAL . '</a>'
4401  ) . ' ' .
4402  strip_tags($warrantyNote, '<a>') . ' ' .
4403  sprintf(
4404  $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_login.xlf:free.software'),
4405  '<a href="' . TYPO3_URL_LICENSE . '" target="_blank" rel="noopener noreferrer">',
4406  '</a> '
4407  )
4408  . $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_login.xlf:keep.notice');
4409  return $cNotice;
4410  }
4411 
4420  public static function ADMCMD_previewCmds($pageInfo, Context $context)
4421  {
4422  $simUser = '';
4423  $simTime = '';
4424  if ($pageInfo['fe_group'] > 0) {
4425  $simUser = '&ADMCMD_simUser=' . $pageInfo['fe_group'];
4426  } elseif ((int)$pageInfo['fe_group'] === -2) {
4427  // -2 means "show at any login". We simulate first available fe_group.
4428  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
4429  ->getQueryBuilderForTable('fe_groups');
4430  $queryBuilder->getRestrictions()
4431  ->removeAll()
4432  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
4433  ->add(GeneralUtility::makeInstance(HiddenRestriction::class));
4434 
4435  $activeFeGroupRow = $queryBuilder->select('uid')
4436  ->from('fe_groups')
4437  ->execute()
4438  ->fetch();
4439 
4440  if (!empty($activeFeGroupRow)) {
4441  $simUser = '&ADMCMD_simUser=' . $activeFeGroupRow['uid'];
4442  }
4443  }
4444  $startTime = (int)$pageInfo['starttime'];
4445  $endTime = (int)$pageInfo['endtime'];
4446  if ($startTime > ‪$GLOBALS['EXEC_TIME']) {
4447  // simulate access time to ensure PageRepository will find the page and in turn PageRouter will generate
4448  // an URL for it
4449  $dateAspect = GeneralUtility::makeInstance(DateTimeAspect::class, new \DateTimeImmutable('@' . $startTime));
4450  $context->setAspect('date', $dateAspect);
4451  $simTime = '&ADMCMD_simTime=' . $startTime;
4452  }
4453  if ($endTime < ‪$GLOBALS['EXEC_TIME'] && $endTime !== 0) {
4454  // Set access time to page's endtime subtracted one second to ensure PageRepository will find the page and
4455  // in turn PageRouter will generate an URL for it
4456  $dateAspect = GeneralUtility::makeInstance(
4457  DateTimeAspect::class,
4458  new \DateTimeImmutable('@' . ($endTime - 1))
4459  );
4460  $context->setAspect('date', $dateAspect);
4461  $simTime = '&ADMCMD_simTime=' . ($endTime - 1);
4462  }
4463  return $simUser . $simTime;
4464  }
4465 
4472  public static function getBackendScript($interface = '')
4473  {
4474  if (!$interface) {
4475  $interface = static::getBackendUserAuthentication()->uc['interfaceSetup'];
4476  }
4477  switch ($interface) {
4478  case 'frontend':
4479  $script = '../.';
4480  break;
4481  case 'backend':
4482  default:
4483  $script = (string)GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute('main');
4484  }
4485  return $script;
4486  }
4487 
4494  public static function isTableWorkspaceEnabled($table)
4495  {
4496  return !empty(‪$GLOBALS['TCA'][$table]['ctrl']['versioningWS']);
4497  }
4498 
4506  public static function getTcaFieldConfiguration($table, $field)
4507  {
4508  $configuration = [];
4509  if (isset(‪$GLOBALS['TCA'][$table]['columns'][$field]['config'])) {
4510  $configuration = ‪$GLOBALS['TCA'][$table]['columns'][$field]['config'];
4511  }
4512  return $configuration;
4513  }
4514 
4523  public static function isWebMountRestrictionIgnored($table)
4524  {
4525  return !empty(‪$GLOBALS['TCA'][$table]['ctrl']['security']['ignoreWebMountRestriction']);
4526  }
4527 
4536  public static function isRootLevelRestrictionIgnored($table)
4537  {
4538  return !empty(‪$GLOBALS['TCA'][$table]['ctrl']['security']['ignoreRootLevelRestriction']);
4539  }
4540 
4549  public static function shortcutExists($url)
4550  {
4551  trigger_error(
4552  'Method BackendUtility::shortcutExists() has been marked as deprecated and will be removed in TYPO3 v10.0. Use an instance of ShortcutRepository instead.',
4553  E_USER_DEPRECATED
4554  );
4555 
4556  $shortcutRepository = GeneralUtility::makeInstance(ShortcutRepository::class);
4557  return $shortcutRepository->shortcutExists($url);
4558  }
4559 
4565  protected static function getSignalSlotDispatcher()
4566  {
4567  return GeneralUtility::makeInstance(\‪TYPO3\CMS\‪Extbase\SignalSlot\Dispatcher::class);
4568  }
4569 
4578  protected static function emitGetPagesTSconfigPreIncludeSignal(
4579  array $TSdataArray,
4580  $id,
4581  array $rootLine
4582  ) {
4583  $signalArguments = static::getSignalSlotDispatcher()->dispatch(
4584  __CLASS__,
4585  'getPagesTSconfigPreInclude',
4586  [$TSdataArray, $id, $rootLine, false]
4587  );
4588  return $signalArguments[0];
4589  }
4590 
4595  protected static function getConnectionForTable($table)
4596  {
4597  return GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
4598  }
4599 
4604  protected static function getQueryBuilderForTable($table)
4605  {
4606  return GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
4607  }
4608 
4612  protected static function getLogger()
4613  {
4614  return GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
4615  }
4616 
4620  protected static function getLanguageService()
4621  {
4622  return ‪$GLOBALS['LANG'];
4623  }
4624 
4628  protected static function getBackendUserAuthentication()
4629  {
4630  return ‪$GLOBALS['BE_USER'] ?? null;
4631  }
4632 }
‪TYPO3\CMS\Core\Imaging\Icon\SIZE_SMALL
‪const SIZE_SMALL
Definition: Icon.php:29
‪TYPO3\CMS\Backend\Backend\Shortcut\ShortcutRepository
Definition: ShortcutRepository.php:41
‪TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction
Definition: HiddenRestriction.php:25
‪TYPO3\CMS\Backend\Utility\BackendUtility\getBackendUserAuthentication
‪static BackendUserAuthentication getBackendUserAuthentication()
Definition: BackendUtility.php:4627
‪TYPO3\CMS\Core\Database\Query\QueryHelper\getDateTimeFormats
‪static array getDateTimeFormats()
Definition: QueryHelper.php:175
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTcaFieldConfiguration
‪static array getTcaFieldConfiguration($table, $field)
Definition: BackendUtility.php:4505
‪TYPO3\CMS\Backend\Utility\BackendUtility\getModTSconfig
‪static array getModTSconfig($id, $TSref)
Definition: BackendUtility.php:2925
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGEPREVIEW
‪const CONTEXT_IMAGEPREVIEW
Definition: ProcessedFile.php:50
‪TYPO3\CMS\Frontend\Page\PageRepository\DOKTYPE_MOUNTPOINT
‪const DOKTYPE_MOUNTPOINT
Definition: PageRepository.php:172
‪TYPO3\CMS\Backend\Utility\BackendUtility\getBackendScript
‪static string getBackendScript($interface='')
Definition: BackendUtility.php:4471
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:23
‪TYPO3\CMS\Backend\Utility\BackendUtility\isModuleSetInTBE_MODULES
‪static bool isModuleSetInTBE_MODULES($modName)
Definition: BackendUtility.php:3763
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Core\Routing\RouterInterface
Definition: RouterInterface.php:27
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordLocalization
‪static mixed getRecordLocalization($table, $uid, $language, $andWhereClause='')
Definition: BackendUtility.php:316
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLinkToDataHandlerAction
‪static string getLinkToDataHandlerAction($parameters, $redirectUrl='')
Definition: BackendUtility.php:2788
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:153
‪TYPO3\CMS\Core\Versioning\VersionState\NEW_PLACEHOLDER
‪const NEW_PLACEHOLDER
Definition: VersionState.php:46
‪TYPO3\CMS\Extbase\Annotation
Definition: IgnoreValidation.php:4
‪TYPO3\CMS\Backend\Utility\BackendUtility\getDomainStartPage
‪static array bool getDomainStartPage($domain, $path='')
Definition: BackendUtility.php:3644
‪TYPO3\CMS\Backend\Utility\BackendUtility\resolveFileReferences
‪static TYPO3 CMS Core Resource FileReference[] null resolveFileReferences($tableName, $fieldName, $element, $workspaceId=null)
Definition: BackendUtility.php:1267
‪TYPO3\CMS\Backend\Utility\BackendUtility\getListGroupNames
‪static array getListGroupNames($fields='title, uid')
Definition: BackendUtility.php:1082
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTCAtypes
‪static array null getTCAtypes($table, $rec, $useFieldNameAsKey=false)
Definition: BackendUtility.php:667
‪TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser
Definition: TypoScriptParser.php:37
‪TYPO3\CMS\Backend\Utility\BackendUtility\datetime
‪static string datetime($value)
Definition: BackendUtility.php:1190
‪TYPO3\CMS\Core\Imaging\Icon
Definition: Icon.php:25
‪TYPO3\CMS\Frontend\Page\PageRepository\DOKTYPE_SHORTCUT
‪const DOKTYPE_SHORTCUT
Definition: PageRepository.php:170
‪TYPO3\CMS\Backend\Utility\BackendUtility\softRefParserObj
‪static mixed & softRefParserObj($spKey)
Definition: BackendUtility.php:3692
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTSCpidCached
‪static array getTSCpidCached($table, $uid, $pid)
Definition: BackendUtility.php:3584
‪TYPO3\CMS\Backend\Utility\BackendUtility\unsetMenuItems
‪static array unsetMenuItems($modTSconfig, $itemArray, $TSref)
Definition: BackendUtility.php:3141
‪TYPO3\CMS\Backend\Utility\BackendUtility\setUpdateSignal
‪static setUpdateSignal($set='', $params='')
Definition: BackendUtility.php:3164
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:371
‪TYPO3\CMS\Core\Database\RelationHandler
Definition: RelationHandler.php:32
‪TYPO3\CMS\Backend\Utility\BackendUtility\$tcaTableTypeConfigurationCache
‪static array $tcaTableTypeConfigurationCache
Definition: BackendUtility.php:79
‪TYPO3\CMS\Backend\Utility\BackendUtility\getCommonSelectFields
‪static string getCommonSelectFields($table, $prefix='', $fields=[])
Definition: BackendUtility.php:2397
‪TYPO3
‪TYPO3\CMS\Backend\Utility\BackendUtility\calcAge
‪static string calcAge($seconds, $labels='min|hrs|days|yrs|min|hour|day|year')
Definition: BackendUtility.php:1218
‪TYPO3\CMS\Backend\Exception
Definition: Exception.php:23
‪TYPO3\CMS\Backend\Utility\BackendUtility\storeHash
‪static storeHash($hash, $data, $ident)
Definition: BackendUtility.php:823
‪TYPO3\CMS\Backend\Utility\BackendUtility\getModuleUrl
‪static string getModuleUrl($moduleName, $urlParameters=[])
Definition: BackendUtility.php:3327
‪TYPO3\CMS\Core\Exception\SiteNotFoundException
Definition: SiteNotFoundException.php:25
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Backend\Utility\BackendUtility\getItemLabel
‪static string getItemLabel($table, $col)
Definition: BackendUtility.php:1791
‪TYPO3\CMS\Backend\Utility\BackendUtility\purgeComputedPropertyNames
‪static array purgeComputedPropertyNames(array $propertyNames)
Definition: BackendUtility.php:223
‪TYPO3\CMS\Backend\Utility\BackendUtility\getNoRecordTitle
‪static string getNoRecordTitle($prep=false)
Definition: BackendUtility.php:1904
‪TYPO3\CMS\Core\Core\Environment\getCurrentScript
‪static string getCurrentScript()
Definition: Environment.php:193
‪TYPO3\CMS\Core\Resource\ResourceFactory\getInstance
‪static ResourceFactory getInstance()
Definition: ResourceFactory.php:39
‪TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction
Definition: BackendWorkspaceRestriction.php:28
‪TYPO3\CMS\Backend\Utility\BackendUtility\cshItem
‪static string cshItem($table, $field, $_='', $wrap='')
Definition: BackendUtility.php:2565
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordIconAltText
‪static string getRecordIconAltText($row, $table='pages')
Definition: BackendUtility.php:1621
‪TYPO3\CMS\Backend\Utility\BackendUtility\lockRecords
‪static lockRecords($table='', $uid=0, $pid=0)
Definition: BackendUtility.php:3353
‪TYPO3\CMS\Backend\Utility\BackendUtility\thumbCode
‪static string thumbCode( $row, $table, $field, $backPath='', $thumbScript='', $uploaddir=null, $abs=0, $tparams='', $size='', $linkInfoPopup=true)
Definition: BackendUtility.php:1338
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:31
‪TYPO3\CMS\Backend\Utility\BackendUtility\daysUntil
‪static int daysUntil($tstamp)
Definition: BackendUtility.php:1167
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPageForRootline
‪static array getPageForRootline($uid, $clause, $workspaceOL, array $additionalFields=[])
Definition: BackendUtility.php:449
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:614
‪TYPO3\CMS\Core\Versioning\VersionState\DELETE_PLACEHOLDER
‪const DELETE_PLACEHOLDER
Definition: VersionState.php:54
‪TYPO3\CMS\Backend\Utility\BackendUtility\referenceCount
‪static string referenceCount($table, $ref, $msg='', $count=null)
Definition: BackendUtility.php:3787
‪TYPO3\CMS\Backend\Utility\BackendUtility\getUserNames
‪static array getUserNames($fields='username, usergroup, usergroup_cached_list, uid', $where='')
Definition: BackendUtility.php:1003
‪TYPO3\CMS\Core\Utility\PathUtility\getCanonicalPath
‪static string getCanonicalPath($path)
Definition: PathUtility.php:306
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRuntimeCache
‪static FrontendInterface getRuntimeCache()
Definition: BackendUtility.php:3716
‪TYPO3\CMS\Backend\Utility\BackendUtility\BEgetRootLine
‪static array BEgetRootLine($uid, $clause='', $workspaceOL=false, array $additionalFields=[])
Definition: BackendUtility.php:374
‪TYPO3\CMS\Core\Versioning\VersionState\MOVE_POINTER
‪const MOVE_POINTER
Definition: VersionState.php:72
‪TYPO3\CMS\Backend\Utility\BackendUtility\isRootLevelRestrictionIgnored
‪static bool isRootLevelRestrictionIgnored($table)
Definition: BackendUtility.php:4535
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPreviewUrl
‪static string getPreviewUrl( $pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', &$switchFocus=true)
Definition: BackendUtility.php:2656
‪TYPO3\CMS\Backend\Utility\BackendUtility\helpText
‪static string helpText($table, $field)
Definition: BackendUtility.php:2487
‪$fields
‪$fields
Definition: pages.php:4
‪TYPO3\CMS\Backend\Utility\BackendUtility\emitGetPagesTSconfigPreIncludeSignal
‪static array emitGetPagesTSconfigPreIncludeSignal(array $TSdataArray, $id, array $rootLine)
Definition: BackendUtility.php:4577
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:49
‪TYPO3\CMS\Backend\Utility\BackendUtility\wrapInHelp
‪static string wrapInHelp($table, $field, $text='', array $overloadHelpText=[])
Definition: BackendUtility.php:2519
‪TYPO3\CMS\Backend\Utility\BackendUtility\getFuncMenu
‪static string getFuncMenu( $mainParams, $elementName, $currentValue, $menuItems, $script='', $addParams='')
Definition: BackendUtility.php:2955
‪TYPO3\CMS\Backend\Utility\BackendUtility\getWorkspaceWhereClause
‪static string getWorkspaceWhereClause($table, $workspaceId=null)
Definition: BackendUtility.php:4267
‪TYPO3\CMS\Core\Utility\PathUtility\basename
‪static string basename($path)
Definition: PathUtility.php:164
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:23
‪TYPO3\CMS\Backend\Utility\BackendUtility\isWebMountRestrictionIgnored
‪static bool isWebMountRestrictionIgnored($table)
Definition: BackendUtility.php:4522
‪TYPO3\CMS\Core\Context\Context\setAspect
‪setAspect(string $name, AspectInterface $aspect)
Definition: Context.php:141
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:47
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:36
‪TYPO3\CMS\Backend\Utility\BackendUtility\isTableWorkspaceEnabled
‪static bool isTableWorkspaceEnabled($table)
Definition: BackendUtility.php:4493
‪TYPO3\CMS\Backend\Utility\BackendUtility\translationCount
‪static string translationCount($table, $ref, $msg='')
Definition: BackendUtility.php:3837
‪TYPO3\CMS\Frontend\Compatibility\LegacyDomainResolver
Definition: LegacyDomainResolver.php:37
‪TYPO3\CMS\Backend\Utility\BackendUtility\wrapClickMenuOnIcon
‪static string wrapClickMenuOnIcon( $content, $table, $uid=0, $context='', $_addParams='', $_enDisItems='', $returnTagParameters=false)
Definition: BackendUtility.php:2759
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:182
‪TYPO3\CMS\Backend\Utility\BackendUtility\getSignalSlotDispatcher
‪static TYPO3 CMS Extbase SignalSlot Dispatcher getSignalSlotDispatcher()
Definition: BackendUtility.php:4564
‪TYPO3\CMS\Backend\Utility\BackendUtility\fixVersioningPid
‪static fixVersioningPid($table, &$rr, $ignoreWorkspaceMatch=false)
Definition: BackendUtility.php:3986
‪TYPO3\CMS\Frontend\Page\PageRepository\DOKTYPE_LINK
‪const DOKTYPE_LINK
Definition: PageRepository.php:169
‪TYPO3\CMS\Backend\Utility
Definition: BackendUtility.php:2
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordTitlePrep
‪static string getRecordTitlePrep($title, $titleLength=0)
Definition: BackendUtility.php:1883
‪TYPO3\CMS\Core\Resource\AbstractFile
Definition: AbstractFile.php:24
‪TYPO3\CMS\Backend\Utility\BackendUtility\getOriginalTranslationTable
‪static string getOriginalTranslationTable($table)
Definition: BackendUtility.php:604
‪TYPO3\CMS\Backend\Utility\BackendUtility\createPreviewUrl
‪static string createPreviewUrl($pageUid, $rootLine, $anchorSection, $additionalGetVars, $viewScript)
Definition: BackendUtility.php:2811
‪TYPO3\CMS\Backend\Utility\BackendUtility\ADMCMD_previewCmds
‪static string ADMCMD_previewCmds($pageInfo, Context $context)
Definition: BackendUtility.php:4419
‪TYPO3\CMS\Backend\Utility\BackendUtility\firstDomainRecord
‪static string null firstDomainRecord($rootLine)
Definition: BackendUtility.php:3623
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:30
‪TYPO3\CMS\Frontend\Page\PageRepository
Definition: PageRepository.php:53
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLogger
‪static LoggerInterface getLogger()
Definition: BackendUtility.php:4611
‪TYPO3\CMS\Backend\Utility\BackendUtility\versioningPlaceholderClause
‪static string versioningPlaceholderClause($table)
Definition: BackendUtility.php:4251
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:35
‪TYPO3\CMS\Backend\Utility\BackendUtility\getDropdownMenu
‪static string getDropdownMenu( $mainParams, $elementName, $currentValue, $menuItems, $script='', $addParams='')
Definition: BackendUtility.php:3005
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:33
‪TYPO3\CMS\Core\Utility\HttpUtility\buildQueryString
‪static string buildQueryString(array $parameters, string $prependCharacter='', bool $skipEmptyParameters=false)
Definition: HttpUtility.php:160
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLiveVersionOfRecord
‪static array null getLiveVersionOfRecord($table, $uid, $fields=' *')
Definition: BackendUtility.php:4213
‪TYPO3\CMS\Backend\Utility\BackendUtility\getGroupNames
‪static array getGroupNames($fields='title, uid', $where='')
Definition: BackendUtility.php:1020
‪TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException
Definition: ResourceDoesNotExistException.php:21
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:23
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLabelFromItemListMerged
‪static string getLabelFromItemListMerged($pageId, $table, $column, $key)
Definition: BackendUtility.php:1704
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordToolTip
‪static string getRecordToolTip(array $row, $table='pages')
Definition: BackendUtility.php:1603
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordsSortedByTitle
‪static array getRecordsSortedByTitle(array $fields, $table, $titleField, $where='')
Definition: BackendUtility.php:1041
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordTitle
‪static string getRecordTitle($table, $row, $prep=false, $forceResult=true)
Definition: BackendUtility.php:1811
‪TYPO3\CMS\Backend\Utility\BackendUtility\getModuleData
‪static array getModuleData( $MOD_MENU, $CHANGED_SETTINGS, $modName, $type='', $dontValidateList='', $setDefaultList='')
Definition: BackendUtility.php:3259
‪TYPO3\CMS\Backend\Utility\BackendUtility\getFuncCheck
‪static string getFuncCheck( $mainParams, $elementName, $currentValue, $script='', $addParams='', $tagParams='')
Definition: BackendUtility.php:3054
‪TYPO3\CMS\Backend\Utility\BackendUtility\getMovePlaceholder
‪static array bool getMovePlaceholder($table, $uid, $fields=' *', $workspace=null)
Definition: BackendUtility.php:4311
‪TYPO3\CMS\Backend\Utility\BackendUtility\titleAttribForPages
‪static string titleAttribForPages($row, $perms_clause='', $includeAttrib=true)
Definition: BackendUtility.php:1502
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key, $exitOnError=null)
Definition: ExtensionManagementUtility.php:115
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:34
‪TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser\checkIncludeLines_array
‪static array checkIncludeLines_array(array $array)
Definition: TypoScriptParser.php:1214
‪TYPO3\CMS\Backend\Utility\BackendUtility\purgeComputedPropertiesFromRecord
‪static array purgeComputedPropertiesFromRecord(array $record)
Definition: BackendUtility.php:206
‪TYPO3\CMS\Backend\Utility\BackendUtility\getViewDomain
‪static string getViewDomain($pageId, $rootLine=null)
Definition: BackendUtility.php:2864
‪TYPO3\CMS\Core\Resource\ResourceFactory\getFileReferenceObject
‪FileReference getFileReferenceObject($uid, array $fileReferenceData=[], $raw=false)
Definition: ResourceFactory.php:629
‪TYPO3\CMS\Core\Http\ServerRequest
Definition: ServerRequest.php:35
‪TYPO3\CMS\Backend\Utility\BackendUtility\getProcessedValueExtra
‪static string getProcessedValueExtra( $table, $fN, $fV, $fixed_lgd_chars=0, $uid=0, $forceResult=true, $pid=0)
Definition: BackendUtility.php:2362
‪TYPO3\CMS\Backend\Utility\BackendUtility\deleteClause
‪static string deleteClause($table, $tableAlias='')
Definition: BackendUtility.php:101
‪TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException
Definition: InvalidRouteArgumentsException.php:23
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Backend\Utility\BackendUtility\editOnClick
‪static string editOnClick($params, $_='', $requestUri='')
Definition: BackendUtility.php:2592
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:32
‪TYPO3\CMS\Backend\Utility\BackendUtility\BEenableFields
‪static string BEenableFields($table, $inv=false)
Definition: BackendUtility.php:256
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Backend\Utility\BackendUtility\getWorkspaceVersionOfRecord
‪static array bool getWorkspaceVersionOfRecord($workspace, $table, $uid, $fields=' *')
Definition: BackendUtility.php:4166
‪TYPO3\CMS\Backend\Utility\BackendUtility\explodeSoftRefParserList
‪static array bool explodeSoftRefParserList($parserList)
Definition: BackendUtility.php:3728
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordWSOL
‪static array getRecordWSOL( $table, $uid, $fields=' *', $where='', $useDeleteClause=true, $unsetMovePointers=false)
Definition: BackendUtility.php:174
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:130
‪TYPO3\CMS\Core\Versioning\VersionState
Definition: VersionState.php:23
‪TYPO3\CMS\Backend\Utility\BackendUtility\getFuncInput
‪static string getFuncInput( $mainParams, $elementName, $currentValue, $size=10, $script='', $addParams='')
Definition: BackendUtility.php:3090
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:42
‪$output
‪$output
Definition: annotationChecker.php:113
‪TYPO3\CMS\Backend\Utility\BackendUtility\dateTimeAge
‪static string dateTimeAge($tstamp, $prefix=1, $date='')
Definition: BackendUtility.php:1248
‪TYPO3\CMS\Backend\Utility\BackendUtility\blindGroupNames
‪static array blindGroupNames($groups, $groupArray, $excludeBlindedFlag=false)
Definition: BackendUtility.php:1137
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:31
‪TYPO3\CMS\Core\Versioning\VersionState\NEW_PLACEHOLDER_VERSION
‪const NEW_PLACEHOLDER_VERSION
Definition: VersionState.php:32
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:21
‪TYPO3\CMS\Backend\Utility\BackendUtility\viewOnClick
‪static string viewOnClick( $pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=true)
Definition: BackendUtility.php:2616
‪TYPO3\CMS\Backend\Utility\BackendUtility\getProcessedValue
‪static string null getProcessedValue( $table, $col, $value, $fixed_lgd_chars=0, $defaultPassthrough=false, $noRecordLookup=false, $uid=0, $forceResult=true, $pid=0)
Definition: BackendUtility.php:1933
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLabelsFromItemsList
‪static string getLabelsFromItemsList($table, $column, $keyList, array $columnTsConfig=[])
Definition: BackendUtility.php:1742
‪TYPO3\CMS\Backend\Utility\BackendUtility\time
‪static string time($value, $withSeconds=true)
Definition: BackendUtility.php:1206
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLiveVersionIdOfRecord
‪static int getLiveVersionIdOfRecord($table, $uid)
Definition: BackendUtility.php:4229
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTSCpid
‪static array getTSCpid($table, $uid, $pid)
Definition: BackendUtility.php:3607
‪TYPO3\CMS\Backend\Utility\BackendUtility\isTableLocalizable
‪static bool isTableLocalizable($table)
Definition: BackendUtility.php:616
‪TYPO3\CMS\Core\Database\Query\QueryHelper\stripLogicalOperatorPrefix
‪static string stripLogicalOperatorPrefix(string $constraint)
Definition: QueryHelper.php:163
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPagesTSconfig
‪static array getPagesTSconfig($id, $rootLine=null, $returnPartArray=false)
Definition: BackendUtility.php:864
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTSconfig_pidValue
‪static int getTSconfig_pidValue($table, $uid, $pid)
Definition: BackendUtility.php:3522
‪TYPO3\CMS\Core\Versioning\VersionState\DEFAULT_STATE
‪const DEFAULT_STATE
Definition: VersionState.php:38
‪TYPO3\CMS\Core\Resource\AbstractFile\getExtension
‪string getExtension()
Definition: AbstractFile.php:252
‪TYPO3\CMS\Backend\Utility\BackendUtility\buildScriptUrl
‪static string buildScriptUrl($mainParams, $addParams, $script='')
Definition: BackendUtility.php:3111
‪TYPO3\CMS\Backend\Utility\BackendUtility\getHash
‪static mixed getHash($hash)
Definition: BackendUtility.php:838
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:23
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Utility\BackendUtility\workspaceOL
‪static workspaceOL($table, &$row, $wsid=-99, $unsetMovePointers=false)
Definition: BackendUtility.php:4048
‪TYPO3\CMS\Backend\Utility\BackendUtility\shortcutExists
‪static bool shortcutExists($url)
Definition: BackendUtility.php:4548
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:26
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:25
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:39
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRawPagesTSconfig
‪static array getRawPagesTSconfig($id, array $rootLine=null)
Definition: BackendUtility.php:946
‪TYPO3\CMS\Core\Site\Entity\PseudoSite
Definition: PseudoSite.php:28
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLabelFromItemlist
‪static string getLabelFromItemlist($table, $col, $key)
Definition: BackendUtility.php:1680
‪TYPO3\CMS\Backend\Utility\BackendUtility\selectVersionsOfRecord
‪static array null selectVersionsOfRecord( $table, $uid, $fields=' *', $workspace=0, $includeDeletedRecords=false, $row=null)
Definition: BackendUtility.php:3891
‪TYPO3\CMS\Backend\Utility\BackendUtility\getConnectionForTable
‪static Connection getConnectionForTable($table)
Definition: BackendUtility.php:4594
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection
Definition: CropVariantCollection.php:21
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\extPath
‪static string extPath($key, $script='')
Definition: ExtensionManagementUtility.php:149
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPidForModTSconfig
‪static int getPidForModTSconfig($table, $uid, $pid)
Definition: BackendUtility.php:3566
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:21
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:29
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTCEFORM_TSconfig
‪static array getTCEFORM_TSconfig($table, $row)
Definition: BackendUtility.php:3482
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Utility\ArrayUtility\sortArraysByKey
‪static array sortArraysByKey(array $arrays, $key, $ascending=true)
Definition: ArrayUtility.php:369
‪TYPO3\CMS\Core\Routing\RouterInterface\ABSOLUTE_URL
‪const ABSOLUTE_URL
Definition: RouterInterface.php:31
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordPath
‪static mixed getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit=0)
Definition: BackendUtility.php:572
‪TYPO3\CMS\Backend\Utility\BackendUtility\movePlhOL
‪static bool movePlhOL($table, &$row)
Definition: BackendUtility.php:4130
‪TYPO3\CMS\Backend\Utility\BackendUtility\getQueryBuilderForTable
‪static QueryBuilder getQueryBuilderForTable($table)
Definition: BackendUtility.php:4603
‪TYPO3\CMS\Backend\Utility\BackendUtility\blindUserNames
‪static array blindUserNames($usernames, $groupArray, $excludeBlindedFlag=false)
Definition: BackendUtility.php:1103
‪TYPO3\CMS\Backend\Utility\BackendUtility\getUpdateSignalCode
‪static string getUpdateSignalCode()
Definition: BackendUtility.php:3190
‪TYPO3\CMS\Backend\Utility\BackendUtility\helpTextArray
‪static array helpTextArray($table, $field)
Definition: BackendUtility.php:2449
‪TYPO3\CMS\Frontend\Page\PageRepository\SHORTCUT_MODE_NONE
‪const SHORTCUT_MODE_NONE
Definition: PageRepository.php:180
‪TYPO3\CMS\Backend\Utility\BackendUtility\date
‪static string date($tstamp)
Definition: BackendUtility.php:1179
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection\create
‪static CropVariantCollection create(string $jsonString, array $tcaConfig=[])
Definition: CropVariantCollection.php:40
‪TYPO3\CMS\Backend\Utility\BackendUtility\openPageTree
‪static openPageTree($pid, $clearExpansion)
Definition: BackendUtility.php:532
‪TYPO3\CMS\Core\Context\DateTimeAspect
Definition: DateTimeAspect.php:33
‪TYPO3\CMS\Backend\Utility\BackendUtility\wsMapId
‪static int wsMapId($table, $uid)
Definition: BackendUtility.php:4288
‪TYPO3\CMS\Backend\Utility\BackendUtility\splitTable_Uid
‪static array splitTable_Uid($str)
Definition: BackendUtility.php:240
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLanguageService
‪static LanguageService getLanguageService()
Definition: BackendUtility.php:4619
‪TYPO3\CMS\Core\Routing\SiteMatcher
Definition: SiteMatcher.php:53
‪TYPO3\CMS\Backend\Utility\BackendUtility\TYPO3_copyRightNotice
‪static string TYPO3_copyRightNotice()
Definition: BackendUtility.php:4370
‪TYPO3\CMS\Backend\Utility\BackendUtility\readPageAccess
‪static array bool readPageAccess($id, $perms_clause)
Definition: BackendUtility.php:635
‪TYPO3\CMS\Backend\Utility\BackendUtility\isRecordLocked
‪static array bool isRecordLocked($table, $uid)
Definition: BackendUtility.php:3397
‪TYPO3\CMS\Core\Versioning\VersionState\MOVE_PLACEHOLDER
‪const MOVE_PLACEHOLDER
Definition: VersionState.php:71
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTCAtypeValue
‪static string getTCAtypeValue($table, $row)
Definition: BackendUtility.php:759