‪TYPO3CMS  10.4
BackendUtility.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Psr\EventDispatcher\EventDispatcherInterface;
19 use Psr\Log\LoggerInterface;
65 
75 {
76  /*******************************************
77  *
78  * SQL-related, selecting records, searching
79  *
80  *******************************************/
95  public static function ‪getRecord($table, $uid, ‪$fields = '*', $where = '', $useDeleteClause = true)
96  {
97  // Ensure we have a valid uid (not 0 and not NEWxxxx) and a valid TCA
98  if ((int)$uid && !empty(‪$GLOBALS['TCA'][$table])) {
99  $queryBuilder = static::getQueryBuilderForTable($table);
100 
101  // do not use enabled fields here
102  $queryBuilder->getRestrictions()->removeAll();
103 
104  // should the delete clause be used
105  if ($useDeleteClause) {
106  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
107  }
108 
109  // set table and where clause
110  $queryBuilder
111  ->select(...‪GeneralUtility::trimExplode(',', ‪$fields, true))
112  ->from($table)
113  ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter((int)$uid, \PDO::PARAM_INT)));
114 
115  // add custom where clause
116  if ($where) {
117  $queryBuilder->andWhere(‪QueryHelper::stripLogicalOperatorPrefix($where));
118  }
119 
120  $row = $queryBuilder->execute()->fetch();
121  if ($row) {
122  return $row;
123  }
124  }
125  return null;
126  }
127 
139  public static function ‪getRecordWSOL(
140  $table,
141  $uid,
142  ‪$fields = '*',
143  $where = '',
144  $useDeleteClause = true,
145  $unsetMovePointers = false
146  ) {
147  if (‪$fields !== '*') {
148  $internalFields = GeneralUtility::uniqueList(‪$fields . ',uid,pid');
149  $row = ‪self::getRecord($table, $uid, $internalFields, $where, $useDeleteClause);
150  ‪self::workspaceOL($table, $row, -99, $unsetMovePointers);
151  if (is_array($row)) {
152  foreach ($row as $key => $_) {
153  if (!GeneralUtility::inList(‪$fields, $key) && $key[0] !== '_') {
154  unset($row[$key]);
155  }
156  }
157  }
158  } else {
159  $row = ‪self::getRecord($table, $uid, ‪$fields, $where, $useDeleteClause);
160  ‪self::workspaceOL($table, $row, -99, $unsetMovePointers);
161  }
162  return $row;
163  }
164 
172  public static function ‪purgeComputedPropertiesFromRecord(array $record): array
173  {
174  return array_filter(
175  $record,
176  function (string $propertyName): bool {
177  return $propertyName[0] !== '_';
178  },
179  ARRAY_FILTER_USE_KEY
180  );
181  }
182 
190  public static function ‪purgeComputedPropertyNames(array $propertyNames): array
191  {
192  return array_filter(
193  $propertyNames,
194  function (string $propertyName): bool {
195  return $propertyName[0] !== '_';
196  }
197  );
198  }
199 
208  public static function ‪splitTable_Uid($str)
209  {
210  [$uid, $table] = explode('_', strrev($str), 2);
211  return [strrev($table), strrev($uid)];
212  }
213 
225  public static function ‪BEenableFields($table, $inv = false)
226  {
227  $ctrl = ‪$GLOBALS['TCA'][$table]['ctrl'];
228  $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
229  ->getConnectionForTable($table)
230  ->getExpressionBuilder();
231  $query = $expressionBuilder->andX();
232  $invQuery = $expressionBuilder->orX();
233 
234  if (is_array($ctrl)) {
235  if (is_array($ctrl['enablecolumns'])) {
236  if ($ctrl['enablecolumns']['disabled'] ?? false) {
237  $field = $table . '.' . $ctrl['enablecolumns']['disabled'];
238  $query->add($expressionBuilder->eq($field, 0));
239  $invQuery->add($expressionBuilder->neq($field, 0));
240  }
241  if ($ctrl['enablecolumns']['starttime'] ?? false) {
242  $field = $table . '.' . $ctrl['enablecolumns']['starttime'];
243  $query->add($expressionBuilder->lte($field, (int)‪$GLOBALS['SIM_ACCESS_TIME']));
244  $invQuery->add(
245  $expressionBuilder->andX(
246  $expressionBuilder->neq($field, 0),
247  $expressionBuilder->gt($field, (int)‪$GLOBALS['SIM_ACCESS_TIME'])
248  )
249  );
250  }
251  if ($ctrl['enablecolumns']['endtime'] ?? false) {
252  $field = $table . '.' . $ctrl['enablecolumns']['endtime'];
253  $query->add(
254  $expressionBuilder->orX(
255  $expressionBuilder->eq($field, 0),
256  $expressionBuilder->gt($field, (int)‪$GLOBALS['SIM_ACCESS_TIME'])
257  )
258  );
259  $invQuery->add(
260  $expressionBuilder->andX(
261  $expressionBuilder->neq($field, 0),
262  $expressionBuilder->lte($field, (int)‪$GLOBALS['SIM_ACCESS_TIME'])
263  )
264  );
265  }
266  }
267  }
268 
269  if ($query->count() === 0) {
270  return '';
271  }
272 
273  return ' AND ' . ($inv ? $invQuery : $query);
274  }
275 
285  public static function ‪getRecordLocalization($table, $uid, $language, $andWhereClause = '')
286  {
287  $recordLocalization = false;
288 
289  if (self::isTableLocalizable($table)) {
290  $tcaCtrl = ‪$GLOBALS['TCA'][$table]['ctrl'];
291 
292  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
293  ->getQueryBuilderForTable($table);
294  $queryBuilder->getRestrictions()
295  ->removeAll()
296  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
297  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, static::getBackendUserAuthentication()->workspace ?? 0));
298 
299  $queryBuilder->select('*')
300  ->from($table)
301  ->where(
302  $queryBuilder->expr()->eq(
303  $tcaCtrl['translationSource'] ?? $tcaCtrl['transOrigPointerField'],
304  $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
305  ),
306  $queryBuilder->expr()->eq(
307  $tcaCtrl['languageField'],
308  $queryBuilder->createNamedParameter((int)$language, \PDO::PARAM_INT)
309  )
310  )
311  ->setMaxResults(1);
312 
313  if ($andWhereClause) {
314  $queryBuilder->andWhere(‪QueryHelper::stripLogicalOperatorPrefix($andWhereClause));
315  }
316 
317  $recordLocalization = $queryBuilder->execute()->fetchAll();
318  }
319 
320  return $recordLocalization;
321  }
322 
323  /*******************************************
324  *
325  * Page tree, TCA related
326  *
327  *******************************************/
343  public static function ‪BEgetRootLine($uid, $clause = '', $workspaceOL = false, array $additionalFields = [])
344  {
345  $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('runtime');
346  $beGetRootLineCache = $runtimeCache->get('backendUtilityBeGetRootLine') ?: [];
347  ‪$output = [];
348  $pid = $uid;
349  $ident = $pid . '-' . $clause . '-' . $workspaceOL . ($additionalFields ? '-' . md5(implode(',', $additionalFields)) : '');
350  if (is_array($beGetRootLineCache[$ident] ?? false)) {
351  ‪$output = $beGetRootLineCache[$ident];
352  } else {
353  $loopCheck = 100;
354  $theRowArray = [];
355  while ($uid != 0 && $loopCheck) {
356  $loopCheck--;
357  $row = ‪self::getPageForRootline($uid, $clause, $workspaceOL, $additionalFields);
358  if (is_array($row)) {
359  $uid = $row['pid'];
360  $theRowArray[] = $row;
361  } else {
362  break;
363  }
364  }
365  ‪$fields = [
366  'uid',
367  'pid',
368  'title',
369  'doktype',
370  'slug',
371  'tsconfig_includes',
372  'TSconfig',
373  'is_siteroot',
374  't3ver_oid',
375  't3ver_wsid',
376  't3ver_state',
377  't3ver_stage',
378  'backend_layout_next_level',
379  'hidden',
380  'starttime',
381  'endtime',
382  'fe_group',
383  'nav_hide',
384  'content_from_pid',
385  'module',
386  'extendToSubpages'
387  ];
388  ‪$fields = array_merge(‪$fields, $additionalFields);
389  $rootPage = array_fill_keys(‪$fields, null);
390  if ($uid == 0) {
391  $rootPage['uid'] = 0;
392  $theRowArray[] = $rootPage;
393  }
394  $c = count($theRowArray);
395  foreach ($theRowArray as $val) {
396  $c--;
397  ‪$output[$c] = array_intersect_key($val, $rootPage);
398  if (isset($val['_ORIG_pid'])) {
399  ‪$output[$c]['_ORIG_pid'] = $val['_ORIG_pid'];
400  }
401  }
402  $beGetRootLineCache[$ident] = ‪$output;
403  $runtimeCache->set('backendUtilityBeGetRootLine', $beGetRootLineCache);
404  }
405  return ‪$output;
406  }
407 
418  protected static function ‪getPageForRootline($uid, $clause, $workspaceOL, array $additionalFields = [])
419  {
420  $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('runtime');
421  $pageForRootlineCache = $runtimeCache->get('backendUtilityPageForRootLine') ?: [];
422  $statementCacheIdent = md5($clause . ($additionalFields ? '-' . implode(',', $additionalFields) : ''));
423  $ident = $uid . '-' . $workspaceOL . '-' . $statementCacheIdent;
424  if (is_array($pageForRootlineCache[$ident] ?? false)) {
425  $row = $pageForRootlineCache[$ident];
426  } else {
427  $statement = $runtimeCache->get('getPageForRootlineStatement-' . $statementCacheIdent);
428  if (!$statement) {
429  $queryBuilder = static::getQueryBuilderForTable('pages');
430  $queryBuilder->getRestrictions()
431  ->removeAll()
432  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
433 
434  $queryBuilder
435  ->select(
436  'pid',
437  'uid',
438  'title',
439  'doktype',
440  'slug',
441  'tsconfig_includes',
442  'TSconfig',
443  'is_siteroot',
444  't3ver_oid',
445  't3ver_wsid',
446  't3ver_state',
447  't3ver_stage',
448  'backend_layout_next_level',
449  'hidden',
450  'starttime',
451  'endtime',
452  'fe_group',
453  'nav_hide',
454  'content_from_pid',
455  'module',
456  'extendToSubpages',
457  ...$additionalFields
458  )
459  ->from('pages')
460  ->where(
461  $queryBuilder->expr()->eq('uid', $queryBuilder->createPositionalParameter($uid, \PDO::PARAM_INT)),
463  );
464  $statement = $queryBuilder->execute();
465  if (class_exists(\Doctrine\DBAL\ForwardCompatibility\Result::class) && $statement instanceof \Doctrine\DBAL\ForwardCompatibility\Result) {
466  $statement = $statement->getIterator();
467  }
468  $runtimeCache->set('getPageForRootlineStatement-' . $statementCacheIdent, $statement);
469  } else {
470  $statement->bindValue(1, (int)$uid);
471  $statement->execute();
472  }
473  $row = $statement->fetch();
474  $statement->closeCursor();
475 
476  if ($row) {
477  $newLocation = false;
478  if ($workspaceOL) {
479  ‪self::workspaceOL('pages', $row);
480  if (is_array($row) && (int)$row['t3ver_state'] === ‪VersionState::MOVE_POINTER) {
481  $newLocation = ‪self::getMovePlaceholder('pages', $row['uid'], 'pid');
482  }
483  }
484  if (is_array($row)) {
485  if ($newLocation !== false) {
486  $row['pid'] = $newLocation['pid'];
487  } else {
488  ‪self::fixVersioningPid('pages', $row);
489  }
490  $pageForRootlineCache[$ident] = $row;
491  $runtimeCache->set('backendUtilityPageForRootLine', $pageForRootlineCache);
492  }
493  }
494  }
495  return $row;
496  }
497 
505  public static function ‪openPageTree($pid, $clearExpansion)
506  {
507  $beUser = static::getBackendUserAuthentication();
508  // Get current expansion data:
509  if ($clearExpansion) {
510  $expandedPages = [];
511  } else {
512  $expandedPages = $beUser->uc['BackendComponents']['States']['Pagetree']['stateHash'];
513  }
514  // Get rootline:
515  $rL = ‪self::BEgetRootLine($pid);
516  // First, find out what mount index to use (if more than one DB mount exists):
517  $mountIndex = 0;
518  $mountKeys = $beUser->returnWebmounts();
519 
520  foreach ($rL as $rLDat) {
521  if (isset($mountKeys[$rLDat['uid']])) {
522  $mountIndex = $mountKeys[$rLDat['uid']];
523  break;
524  }
525  }
526  // Traverse rootline and open paths:
527  foreach ($rL as $rLDat) {
528  $expandedPages[$mountIndex . '_' . $rLDat['uid']] = '1';
529  }
530  // Write back:
531  $beUser->uc['BackendComponents']['States']['Pagetree']['stateHash'] = $expandedPages;
532  $beUser->writeUC();
533  }
534 
546  public static function ‪getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit = 0)
547  {
548  if (!$titleLimit) {
549  $titleLimit = 1000;
550  }
551  ‪$output = $fullOutput = '/';
552  $clause = trim($clause);
553  if ($clause !== '' && strpos($clause, 'AND') !== 0) {
554  $clause = 'AND ' . $clause;
555  }
556  $data = ‪self::BEgetRootLine($uid, $clause, true);
557  foreach ($data as $record) {
558  if ($record['uid'] === 0) {
559  continue;
560  }
561  ‪$output = '/' . GeneralUtility::fixed_lgd_cs(strip_tags($record['title']), $titleLimit) . ‪$output;
562  if ($fullTitleLimit) {
563  $fullOutput = '/' . GeneralUtility::fixed_lgd_cs(strip_tags($record['title']), $fullTitleLimit) . $fullOutput;
564  }
565  }
566  if ($fullTitleLimit) {
567  return [‪$output, $fullOutput];
568  }
569  return ‪$output;
570  }
571 
578  public static function ‪isTableLocalizable($table)
579  {
580  $isLocalizable = false;
581  if (isset(‪$GLOBALS['TCA'][$table]['ctrl']) && is_array(‪$GLOBALS['TCA'][$table]['ctrl'])) {
582  $tcaCtrl = ‪$GLOBALS['TCA'][$table]['ctrl'];
583  $isLocalizable = isset($tcaCtrl['languageField']) && $tcaCtrl['languageField'] && isset($tcaCtrl['transOrigPointerField']) && $tcaCtrl['transOrigPointerField'];
584  }
585  return $isLocalizable;
586  }
587 
597  public static function ‪readPageAccess($id, $perms_clause)
598  {
599  if ((string)$id !== '') {
600  $id = (int)$id;
601  if (!$id) {
602  if (static::getBackendUserAuthentication()->isAdmin()) {
603  return ['_thePath' => '/'];
604  }
605  } else {
606  $pageinfo = ‪self::getRecord('pages', $id, '*', $perms_clause);
607  if ($pageinfo['uid'] && static::getBackendUserAuthentication()->isInWebMount($pageinfo, $perms_clause)) {
608  ‪self::workspaceOL('pages', $pageinfo);
609  if (is_array($pageinfo)) {
610  ‪self::fixVersioningPid('pages', $pageinfo);
611  [$pageinfo['_thePath'], $pageinfo['_thePathFull']] = ‪self::getRecordPath((int)$pageinfo['uid'], $perms_clause, 15, 1000);
612  return $pageinfo;
613  }
614  }
615  }
616  }
617  return false;
618  }
619 
636  public static function ‪getTCAtypeValue($table, $row)
637  {
638  $typeNum = 0;
639  if (‪$GLOBALS['TCA'][$table]) {
640  $field = ‪$GLOBALS['TCA'][$table]['ctrl']['type'];
641  if (strpos($field, ':') !== false) {
642  [$pointerField, $foreignTableTypeField] = explode(':', $field);
643  // Get field value from database if field is not in the $row array
644  if (!isset($row[$pointerField])) {
645  $localRow = ‪self::getRecord($table, $row['uid'], $pointerField);
646  $foreignUid = $localRow[$pointerField];
647  } else {
648  $foreignUid = $row[$pointerField];
649  }
650  if ($foreignUid) {
651  $fieldConfig = ‪$GLOBALS['TCA'][$table]['columns'][$pointerField]['config'];
652  $relationType = $fieldConfig['type'];
653  if ($relationType === 'select') {
654  $foreignTable = $fieldConfig['foreign_table'];
655  } elseif ($relationType === 'group') {
656  $allowedTables = explode(',', $fieldConfig['allowed']);
657  $foreignTable = $allowedTables[0];
658  } else {
659  throw new \RuntimeException(
660  'TCA foreign field pointer fields are only allowed to be used with group or select field types.',
661  1325862240
662  );
663  }
664  $foreignRow = ‪self::getRecord($foreignTable, $foreignUid, $foreignTableTypeField);
665  if ($foreignRow[$foreignTableTypeField]) {
666  $typeNum = $foreignRow[$foreignTableTypeField];
667  }
668  }
669  } else {
670  $typeNum = $row[$field];
671  }
672  // If that value is an empty string, set it to "0" (zero)
673  if (empty($typeNum)) {
674  $typeNum = 0;
675  }
676  }
677  // If current typeNum doesn't exist, set it to 0 (or to 1 for historical reasons, if 0 doesn't exist)
678  if (!isset(‪$GLOBALS['TCA'][$table]['types'][$typeNum]) || !‪$GLOBALS['TCA'][$table]['types'][$typeNum]) {
679  $typeNum = isset(‪$GLOBALS['TCA'][$table]['types']['0']) ? 0 : 1;
680  }
681  // Force to string. Necessary for eg '-1' to be recognized as a type value.
682  $typeNum = (string)$typeNum;
683  return $typeNum;
684  }
685 
686  /*******************************************
687  *
688  * TypoScript related
689  *
690  *******************************************/
698  public static function ‪getPagesTSconfig($id)
699  {
700  $id = (int)$id;
701 
702  $cache = ‪self::getRuntimeCache();
703  $pagesTsConfigIdToHash = $cache->get('pagesTsConfigIdToHash' . $id);
704  if ($pagesTsConfigIdToHash !== false) {
705  return $cache->get('pagesTsConfigHashToContent' . $pagesTsConfigIdToHash);
706  }
707 
708  $rootLine = ‪self::BEgetRootLine($id, '', true);
709  // Order correctly
710  ksort($rootLine);
711 
712  try {
713  $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($id);
714  } catch (‪SiteNotFoundException $exception) {
715  $site = null;
716  }
717 
718  // Load PageTS from all pages of the rootLine
719  $pageTs = GeneralUtility::makeInstance(PageTsConfigLoader::class)->load($rootLine);
720 
721  // Parse the PageTS into an array, also applying conditions
722  ‪$parser = GeneralUtility::makeInstance(
723  PageTsConfigParser::class,
724  GeneralUtility::makeInstance(TypoScriptParser::class),
725  GeneralUtility::makeInstance(CacheManager::class)->getCache('hash')
726  );
727  $matcher = GeneralUtility::makeInstance(ConditionMatcher::class, null, $id, $rootLine);
728  $tsConfig = ‪$parser->parse($pageTs, $matcher, $site);
729  $cacheHash = md5((string)json_encode($tsConfig));
730 
731  // Get User TSconfig overlay, if no backend user is logged-in, this needs to be checked as well
732  if (static::getBackendUserAuthentication()) {
733  $userTSconfig = static::getBackendUserAuthentication()->getTSConfig() ?? [];
734  } else {
735  $userTSconfig = [];
736  }
737 
738  if (is_array($userTSconfig['page.'] ?? null)) {
739  // Override page TSconfig with user TSconfig
740  ‪ArrayUtility::mergeRecursiveWithOverrule($tsConfig, $userTSconfig['page.']);
741  $cacheHash .= '_user' . static::getBackendUserAuthentication()->user['uid'];
742  }
743 
744  // Many pages end up with the same ts config. To reduce memory usage, the cache
745  // entries are a linked list: One or more pids point to content hashes which then
746  // contain the cached content.
747  $cache->set('pagesTsConfigHashToContent' . $cacheHash, $tsConfig, ['pagesTsConfig']);
748  $cache->set('pagesTsConfigIdToHash' . $id, $cacheHash, ['pagesTsConfig']);
749 
750  return $tsConfig;
751  }
752 
760  public static function ‪getRawPagesTSconfig($id, array $rootLine = null)
761  {
762  trigger_error('BackendUtility::getRawPagesTSconfig will be removed in TYPO3 v11.0. Use PageTsConfigLoader instead.', E_USER_DEPRECATED);
763  if (!is_array($rootLine)) {
764  $rootLine = ‪self::BEgetRootLine($id, '', true);
765  }
766 
767  // Order correctly
768  ksort($rootLine);
769  $tsDataArray = [];
770  // Setting default configuration
771  $tsDataArray['defaultPageTSconfig'] = ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'];
772  foreach ($rootLine as $k => $v) {
773  if (trim($v['tsconfig_includes'])) {
774  $includeTsConfigFileList = ‪GeneralUtility::trimExplode(',', $v['tsconfig_includes'], true);
775  // Traversing list
776  foreach ($includeTsConfigFileList as $key => $includeTsConfigFile) {
777  if (strpos($includeTsConfigFile, 'EXT:') === 0) {
778  [$includeTsConfigFileExtensionKey, $includeTsConfigFilename] = explode(
779  '/',
780  substr($includeTsConfigFile, 4),
781  2
782  );
783  if ((string)$includeTsConfigFileExtensionKey !== ''
784  && ‪ExtensionManagementUtility::isLoaded($includeTsConfigFileExtensionKey)
785  && (string)$includeTsConfigFilename !== ''
786  ) {
787  $extensionPath = ‪ExtensionManagementUtility::extPath($includeTsConfigFileExtensionKey);
788  $includeTsConfigFileAndPath = ‪PathUtility::getCanonicalPath($extensionPath . $includeTsConfigFilename);
789  if (strpos($includeTsConfigFileAndPath, $extensionPath) === 0 && file_exists($includeTsConfigFileAndPath)) {
790  $tsDataArray['uid_' . $v['uid'] . '_static_' . $key] = file_get_contents($includeTsConfigFileAndPath);
791  }
792  }
793  }
794  }
795  }
796  $tsDataArray['uid_' . $v['uid']] = $v['TSconfig'];
797  }
798 
799  $eventDispatcher = GeneralUtility::getContainer()->get(EventDispatcherInterface::class);
800  $event = $eventDispatcher->dispatch(new ‪ModifyLoadedPageTsConfigEvent($tsDataArray, $rootLine));
801  return ‪TypoScriptParser::checkIncludeLines_array($event->getTsConfig());
802  }
803 
804  /*******************************************
805  *
806  * Users / Groups related
807  *
808  *******************************************/
818  public static function ‪getUserNames(‪$fields = 'username,usergroup,usergroup_cached_list,uid', $where = '')
819  {
822  'be_users',
823  'username',
824  'AND pid=0 ' . $where
825  );
826  }
827 
836  public static function ‪getGroupNames(‪$fields = 'title,uid', $where = '')
837  {
840  'be_groups',
841  'title',
842  'AND pid=0 ' . $where
843  );
844  }
845 
857  protected static function ‪getRecordsSortedByTitle(array ‪$fields, $table, $titleField, $where = '')
858  {
859  $fieldsIndex = array_flip(‪$fields);
860  // Make sure the titleField is amongst the fields when getting sorted
861  $fieldsIndex[$titleField] = 1;
862 
863  $result = [];
864 
865  $queryBuilder = static::getQueryBuilderForTable($table);
866  $queryBuilder->getRestrictions()
867  ->removeAll()
868  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
869 
870  $res = $queryBuilder
871  ->select('*')
872  ->from($table)
874  ->execute();
875 
876  while ($record = $res->fetch()) {
877  // store the uid, because it might be unset if it's not among the requested $fields
878  $recordId = $record['uid'];
879  $record[$titleField] = ‪self::getRecordTitle($table, $record);
880 
881  // include only the requested fields in the result
882  $result[$recordId] = array_intersect_key($record, $fieldsIndex);
883  }
884 
885  // sort records by $sortField. This is not done in the query because the title might have been overwritten by
886  // self::getRecordTitle();
887  return ‪ArrayUtility::sortArraysByKey($result, $titleField);
888  }
889 
901  public static function ‪blindUserNames($usernames, $groupArray, $excludeBlindedFlag = false)
902  {
903  if (is_array($usernames) && is_array($groupArray)) {
904  foreach ($usernames as $uid => $row) {
905  $userN = $uid;
906  $set = 0;
907  if ($row['uid'] != static::getBackendUserAuthentication()->user['uid']) {
908  foreach ($groupArray as $v) {
909  if ($v && GeneralUtility::inList($row['usergroup_cached_list'], $v)) {
910  $userN = $row['username'];
911  $set = 1;
912  }
913  }
914  } else {
915  $userN = $row['username'];
916  $set = 1;
917  }
918  $usernames[$uid]['username'] = $userN;
919  if ($excludeBlindedFlag && !$set) {
920  unset($usernames[$uid]);
921  }
922  }
923  }
924  return $usernames;
925  }
926 
936  public static function ‪blindGroupNames($groups, $groupArray, $excludeBlindedFlag = false)
937  {
938  if (is_array($groups) && is_array($groupArray)) {
939  foreach ($groups as $uid => $row) {
940  $groupN = $uid;
941  $set = 0;
942  if (in_array($uid, $groupArray, false)) {
943  $groupN = $row['title'];
944  $set = 1;
945  }
946  $groups[$uid]['title'] = $groupN;
947  if ($excludeBlindedFlag && !$set) {
948  unset($groups[$uid]);
949  }
950  }
951  }
952  return $groups;
953  }
954 
955  /*******************************************
956  *
957  * Output related
958  *
959  *******************************************/
966  public static function ‪daysUntil($tstamp)
967  {
968  $delta_t = $tstamp - ‪$GLOBALS['EXEC_TIME'];
969  return ceil($delta_t / (3600 * 24));
970  }
971 
978  public static function ‪date($tstamp)
979  {
980  return ‪date(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], (int)$tstamp);
981  }
982 
989  public static function ‪datetime($value)
990  {
991  return ‪date(
992  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' ' . ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'],
993  $value
994  );
995  }
996 
1005  public static function ‪time($value, $withSeconds = true)
1006  {
1007  return gmdate('H:i' . ($withSeconds ? ':s' : ''), (int)$value);
1008  }
1009 
1017  public static function ‪calcAge($seconds, $labels = 'min|hrs|days|yrs|min|hour|day|year')
1018  {
1019  $labelArr = ‪GeneralUtility::trimExplode('|', $labels, true);
1020  $absSeconds = abs($seconds);
1021  $sign = $seconds < 0 ? -1 : 1;
1022  if ($absSeconds < 3600) {
1023  $val = round($absSeconds / 60);
1024  $seconds = $sign * $val . ' ' . ($val == 1 ? $labelArr[4] : $labelArr[0]);
1025  } elseif ($absSeconds < 24 * 3600) {
1026  $val = round($absSeconds / 3600);
1027  $seconds = $sign * $val . ' ' . ($val == 1 ? $labelArr[5] : $labelArr[1]);
1028  } elseif ($absSeconds < 365 * 24 * 3600) {
1029  $val = round($absSeconds / (24 * 3600));
1030  $seconds = $sign * $val . ' ' . ($val == 1 ? $labelArr[6] : $labelArr[2]);
1031  } else {
1032  $val = round($absSeconds / (365 * 24 * 3600));
1033  $seconds = $sign * $val . ' ' . ($val == 1 ? $labelArr[7] : $labelArr[3]);
1034  }
1035  return $seconds;
1036  }
1037 
1047  public static function ‪dateTimeAge($tstamp, $prefix = 1, $date = '')
1048  {
1049  if (!$tstamp) {
1050  return '';
1051  }
1052  $label = static::getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.minutesHoursDaysYears');
1053  $age = ' (' . ‪self::calcAge($prefix * (‪$GLOBALS['EXEC_TIME'] - $tstamp), $label) . ')';
1054  return ($date === 'date' ? self::date($tstamp) : self::datetime($tstamp)) . $age;
1055  }
1056 
1066  public static function ‪resolveFileReferences($tableName, $fieldName, $element, $workspaceId = null)
1067  {
1068  if (empty(‪$GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config'])) {
1069  return null;
1070  }
1071  $configuration = ‪$GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config'];
1072  if (empty($configuration['type']) || $configuration['type'] !== 'inline'
1073  || empty($configuration['foreign_table']) || $configuration['foreign_table'] !== 'sys_file_reference'
1074  ) {
1075  return null;
1076  }
1077 
1078  $fileReferences = [];
1080  $relationHandler = GeneralUtility::makeInstance(RelationHandler::class);
1081  if ($workspaceId !== null) {
1082  $relationHandler->setWorkspaceId($workspaceId);
1083  }
1084  $relationHandler->start(
1085  $element[$fieldName],
1086  $configuration['foreign_table'],
1087  $configuration['MM'] ?? '',
1088  $element['uid'],
1089  $tableName,
1090  $configuration
1091  );
1092  $relationHandler->processDeletePlaceholder();
1093  $referenceUids = $relationHandler->tableArray[$configuration['foreign_table']];
1094 
1095  foreach ($referenceUids as $referenceUid) {
1096  try {
1097  $fileReference = GeneralUtility::makeInstance(ResourceFactory::class)->getFileReferenceObject(
1098  $referenceUid,
1099  [],
1100  $workspaceId === 0
1101  );
1102  $fileReferences[$fileReference->getUid()] = $fileReference;
1103  } catch (‪FileDoesNotExistException $e) {
1108  } catch (\InvalidArgumentException $e) {
1113  ‪self::getLogger()->error($e->getMessage(), ['table' => $tableName, 'fieldName' => $fieldName, 'referenceUid' => $referenceUid, 'exception' => $e]);
1114  }
1115  }
1116 
1117  return $fileReferences;
1118  }
1119 
1137  public static function ‪thumbCode(
1138  $row,
1139  $table,
1140  $field,
1141  $backPath = '',
1142  $thumbScript = '',
1143  $uploaddir = null,
1144  $abs = 0,
1145  $tparams = '',
1146  $size = '',
1147  $linkInfoPopup = true
1148  ) {
1149  $size = (int)(trim((string)$size) ?: 64);
1150  $targetDimension = new ‪ImageDimension($size, $size);
1151  $thumbData = '';
1152  $fileReferences = static::resolveFileReferences($table, $field, $row);
1153  // FAL references
1154  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
1155  if ($fileReferences !== null) {
1156  foreach ($fileReferences as $fileReferenceObject) {
1157  // Do not show previews of hidden references
1158  if ($fileReferenceObject->getProperty('hidden')) {
1159  continue;
1160  }
1161  $fileObject = $fileReferenceObject->getOriginalFile();
1162 
1163  if ($fileObject->isMissing()) {
1164  $thumbData .= '<span class="label label-danger">'
1165  . htmlspecialchars(
1166  static::getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.file_missing')
1167  )
1168  . '</span>&nbsp;' . htmlspecialchars($fileObject->getName()) . '<br />';
1169  continue;
1170  }
1171 
1172  // Preview web image or media elements
1173  if (‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails']
1174  && $fileReferenceObject->getOriginalFile()->isImage()
1175  ) {
1176  $cropVariantCollection = ‪CropVariantCollection::create((string)$fileReferenceObject->getProperty('crop'));
1177  $cropArea = $cropVariantCollection->getCropArea();
1179  $processingConfiguration = [
1180  'width' => $targetDimension->getWidth(),
1181  'height' => $targetDimension->getHeight(),
1182  ];
1183  if (!$cropArea->isEmpty()) {
1185  $processingConfiguration = [
1186  'maxWidth' => $targetDimension->getWidth(),
1187  'maxHeight' => $targetDimension->getHeight(),
1188  'crop' => $cropArea->makeAbsoluteBasedOnFile($fileReferenceObject),
1189  ];
1190  }
1191  $processedImage = $fileObject->process($taskType, $processingConfiguration);
1192  $attributes = [
1193  'src' => $processedImage->getPublicUrl(true),
1194  'width' => $processedImage->getProperty('width'),
1195  'height' => $processedImage->getProperty('height'),
1196  'alt' => $fileReferenceObject->getName(),
1197  ];
1198  $imgTag = '<img ' . GeneralUtility::implodeAttributes($attributes, true) . $tparams . '/>';
1199  } else {
1200  // Icon
1201  $imgTag = '<span title="' . htmlspecialchars($fileObject->getName()) . '">'
1202  . $iconFactory->getIconForResource($fileObject, ‪Icon::SIZE_SMALL)->render()
1203  . '</span>';
1204  }
1205  if ($linkInfoPopup) {
1206  // relies on module 'TYPO3/CMS/Backend/ActionDispatcher'
1207  $attributes = GeneralUtility::implodeAttributes([
1208  'data-dispatch-action' => 'TYPO3.InfoWindow.showItem',
1209  'data-dispatch-args-list' => '_FILE,' . (int)$fileObject->getUid(),
1210  ], true);
1211  $thumbData .= '<a href="#" ' . $attributes . '>' . $imgTag . '</a> ';
1212  } else {
1213  $thumbData .= $imgTag;
1214  }
1215  }
1216  }
1217  return $thumbData;
1218  }
1219 
1225  public static function ‪getThumbnailUrl(int $fileId, array $configuration): string
1226  {
1227  $taskType = $configuration['_context'] ?? ‪ProcessedFile::CONTEXT_IMAGEPREVIEW;
1228  unset($configuration['_context']);
1229 
1230  return GeneralUtility::makeInstance(ResourceFactory::class)
1231  ->getFileObject($fileId)
1232  ->process($taskType, $configuration)
1233  ->getPublicUrl(true);
1234  }
1235 
1244  public static function ‪titleAttribForPages($row, $perms_clause = '', $includeAttrib = true)
1245  {
1246  $lang = static::getLanguageService();
1247  $parts = [];
1248  $parts[] = 'id=' . $row['uid'];
1249  if ($row['uid'] === 0) {
1250  $out = htmlspecialchars($parts[0]);
1251  return $includeAttrib ? 'title="' . $out . '"' : $out;
1252  }
1253  switch (‪VersionState::cast($row['t3ver_state'])) {
1255  $parts[] = 'PLH WSID#' . $row['t3ver_wsid'];
1256  break;
1258  $parts[] = 'Deleted element!';
1259  break;
1261  $parts[] = 'OLD LOCATION (Move Placeholder) WSID#' . $row['t3ver_wsid'];
1262  break;
1264  $parts[] = 'NEW LOCATION (Move-to Pointer) WSID#' . $row['t3ver_wsid'];
1265  break;
1267  $parts[] = 'New element!';
1268  break;
1269  }
1270  if ($row['doktype'] == ‪PageRepository::DOKTYPE_LINK) {
1271  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['url']['label']) . ' ' . $row['url'];
1272  } elseif ($row['doktype'] == ‪PageRepository::DOKTYPE_SHORTCUT) {
1273  if ($perms_clause) {
1274  $label = ‪self::getRecordPath((int)$row['shortcut'], $perms_clause, 20);
1275  } else {
1276  $row['shortcut'] = (int)$row['shortcut'];
1277  $lRec = ‪self::getRecordWSOL('pages', $row['shortcut'], 'title');
1278  $label = $lRec['title'] . ' (id=' . $row['shortcut'] . ')';
1279  }
1280  if ($row['shortcut_mode'] != ‪PageRepository::SHORTCUT_MODE_NONE) {
1281  $label .= ', ' . $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['shortcut_mode']['label']) . ' '
1282  . $lang->sL(self::getLabelFromItemlist('pages', 'shortcut_mode', $row['shortcut_mode']));
1283  }
1284  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['shortcut']['label']) . ' ' . $label;
1285  } elseif ($row['doktype'] == ‪PageRepository::DOKTYPE_MOUNTPOINT) {
1286  if ((int)$row['mount_pid'] > 0) {
1287  if ($perms_clause) {
1288  $label = ‪self::getRecordPath((int)$row['mount_pid'], $perms_clause, 20);
1289  } else {
1290  $lRec = ‪self::getRecordWSOL('pages', (int)$row['mount_pid'], 'title');
1291  $label = $lRec['title'] . ' (id=' . $row['mount_pid'] . ')';
1292  }
1293  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['mount_pid']['label']) . ' ' . $label;
1294  if ($row['mount_pid_ol']) {
1295  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['mount_pid_ol']['label']);
1296  }
1297  } else {
1298  $parts[] = $lang->sL('LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:no_mount_pid');
1299  }
1300  }
1301  if ($row['nav_hide']) {
1302  $parts[] = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.nav_hide');
1303  }
1304  if ($row['hidden']) {
1305  $parts[] = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.hidden');
1306  }
1307  if ($row['starttime']) {
1308  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['starttime']['label'])
1309  . ' ' . ‪self::dateTimeAge($row['starttime'], -1, 'date');
1310  }
1311  if ($row['endtime']) {
1312  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['endtime']['label']) . ' '
1313  . ‪self::dateTimeAge($row['endtime'], -1, 'date');
1314  }
1315  if ($row['fe_group']) {
1316  $fe_groups = [];
1317  foreach (‪GeneralUtility::intExplode(',', $row['fe_group']) as $fe_group) {
1318  if ($fe_group < 0) {
1319  $fe_groups[] = $lang->sL(self::getLabelFromItemlist('pages', 'fe_group', (string)$fe_group));
1320  } else {
1321  $lRec = ‪self::getRecordWSOL('fe_groups', $fe_group, 'title');
1322  $fe_groups[] = $lRec['title'];
1323  }
1324  }
1325  $label = implode(', ', $fe_groups);
1326  $parts[] = $lang->sL(‪$GLOBALS['TCA']['pages']['columns']['fe_group']['label']) . ' ' . $label;
1327  }
1328  $out = htmlspecialchars(implode(' - ', $parts));
1329  return $includeAttrib ? 'title="' . $out . '"' : $out;
1330  }
1331 
1339  public static function ‪getRecordToolTip(array $row, $table = 'pages')
1340  {
1341  $toolTipText = ‪self::getRecordIconAltText($row, $table);
1342  $toolTipCode = 'data-toggle="tooltip" data-title=" '
1343  . str_replace(' - ', '<br>', $toolTipText)
1344  . '" data-html="true" data-placement="right"';
1345  return $toolTipCode;
1346  }
1347 
1357  public static function ‪getRecordIconAltText($row, $table = 'pages')
1358  {
1359  if ($table === 'pages') {
1360  $out = ‪self::titleAttribForPages($row, '', false);
1361  } else {
1362  $out = !empty(trim(‪$GLOBALS['TCA'][$table]['ctrl']['descriptionColumn'])) ? $row[‪$GLOBALS['TCA'][$table]['ctrl']['descriptionColumn']] . ' ' : '';
1363  $ctrl = ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
1364  // Uid is added
1365  $out .= 'id=' . $row['uid'];
1366  if (static::isTableWorkspaceEnabled($table)) {
1367  switch (‪VersionState::cast($row['t3ver_state'])) {
1369  $out .= ' - PLH WSID#' . $row['t3ver_wsid'];
1370  break;
1372  $out .= ' - Deleted element!';
1373  break;
1375  $out .= ' - OLD LOCATION (Move Placeholder) WSID#' . $row['t3ver_wsid'];
1376  break;
1378  $out .= ' - NEW LOCATION (Move-to Pointer) WSID#' . $row['t3ver_wsid'];
1379  break;
1381  $out .= ' - New element!';
1382  break;
1383  }
1384  }
1385  // Hidden
1386  $lang = static::getLanguageService();
1387  if ($ctrl['disabled']) {
1388  $out .= $row[$ctrl['disabled']] ? ' - ' . $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.hidden') : '';
1389  }
1390  if ($ctrl['starttime']) {
1391  if ($row[$ctrl['starttime']] > ‪$GLOBALS['EXEC_TIME']) {
1392  $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') . ')';
1393  }
1394  }
1395  if ($row[$ctrl['endtime']]) {
1396  $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') . ')';
1397  }
1398  }
1399  return htmlspecialchars($out);
1400  }
1401 
1410  public static function ‪getLabelFromItemlist($table, $col, $key)
1411  {
1412  // Check, if there is an "items" array:
1413  if (is_array(‪$GLOBALS['TCA'][$table]['columns'][$col]['config']['items'] ?? false)) {
1414  // Traverse the items-array...
1415  foreach (‪$GLOBALS['TCA'][$table]['columns'][$col]['config']['items'] as $v) {
1416  // ... and return the first found label where the value was equal to $key
1417  if ((string)$v[1] === (string)$key) {
1418  return $v[0];
1419  }
1420  }
1421  }
1422  return '';
1423  }
1424 
1434  public static function ‪getLabelFromItemListMerged($pageId, $table, $column, $key)
1435  {
1436  $pageTsConfig = static::getPagesTSconfig($pageId);
1437  $label = '';
1438  if (isset($pageTsConfig['TCEFORM.'])
1439  && \is_array($pageTsConfig['TCEFORM.'])
1440  && \is_array($pageTsConfig['TCEFORM.'][$table . '.'])
1441  && \is_array($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.'])
1442  ) {
1443  if (\is_array($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['addItems.'])
1444  && isset($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['addItems.'][$key])
1445  ) {
1446  $label = $pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['addItems.'][$key];
1447  } elseif (\is_array($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['altLabels.'])
1448  && isset($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['altLabels.'][$key])
1449  ) {
1450  $label = $pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['altLabels.'][$key];
1451  }
1452  }
1453  if (empty($label)) {
1454  $tcaValue = ‪self::getLabelFromItemlist($table, $column, $key);
1455  if (!empty($tcaValue)) {
1456  $label = $tcaValue;
1457  }
1458  }
1459  return $label;
1460  }
1461 
1472  public static function ‪getLabelsFromItemsList($table, $column, $keyList, array $columnTsConfig = [])
1473  {
1474  // Check if there is an "items" array
1475  if (
1476  !isset(‪$GLOBALS['TCA'][$table]['columns'][$column]['config']['items'])
1477  || !is_array(‪$GLOBALS['TCA'][$table]['columns'][$column]['config']['items'])
1478  || $keyList === ''
1479  ) {
1480  return '';
1481  }
1482 
1483  $keys = ‪GeneralUtility::trimExplode(',', $keyList, true);
1484  $labels = [];
1485  // Loop on all selected values
1486  foreach ($keys as $key) {
1487  $label = null;
1488  if ($columnTsConfig) {
1489  // Check if label has been defined or redefined via pageTsConfig
1490  if (isset($columnTsConfig['addItems.'][$key])) {
1491  $label = $columnTsConfig['addItems.'][$key];
1492  } elseif (isset($columnTsConfig['altLabels.'][$key])) {
1493  $label = $columnTsConfig['altLabels.'][$key];
1494  }
1495  }
1496  if ($label === null) {
1497  // Otherwise lookup the label in TCA items list
1498  foreach (‪$GLOBALS['TCA'][$table]['columns'][$column]['config']['items'] as $itemConfiguration) {
1499  [$currentLabel, $currentKey] = $itemConfiguration;
1500  if ((string)$key === (string)$currentKey) {
1501  $label = $currentLabel;
1502  break;
1503  }
1504  }
1505  }
1506  if ($label !== null) {
1507  $labels[] = static::getLanguageService()->sL($label);
1508  }
1509  }
1510  return implode(', ', $labels);
1511  }
1512 
1521  public static function ‪getItemLabel($table, $col)
1522  {
1523  // Check if column exists
1524  if (is_array(‪$GLOBALS['TCA'][$table]) && is_array(‪$GLOBALS['TCA'][$table]['columns'][$col])) {
1525  return ‪$GLOBALS['TCA'][$table]['columns'][$col]['label'];
1526  }
1527 
1528  return null;
1529  }
1530 
1541  public static function ‪getRecordTitle($table, $row, $prep = false, $forceResult = true)
1542  {
1543  $params = [];
1544  $recordTitle = '';
1545  if (isset(‪$GLOBALS['TCA'][$table]) && is_array(‪$GLOBALS['TCA'][$table])) {
1546  // If configured, call userFunc
1547  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['label_userFunc'])) {
1548  $params['table'] = $table;
1549  $params['row'] = $row;
1550  $params['title'] = '';
1551  $params['options'] = ‪$GLOBALS['TCA'][$table]['ctrl']['label_userFunc_options'] ?? [];
1552 
1553  // Create NULL-reference
1554  $null = null;
1555  GeneralUtility::callUserFunction(‪$GLOBALS['TCA'][$table]['ctrl']['label_userFunc'], $params, $null);
1556  $recordTitle = $params['title'];
1557  } else {
1558  // No userFunc: Build label
1559  $recordTitle = ‪self::getProcessedValue(
1560  $table,
1561  ‪$GLOBALS['TCA'][$table]['ctrl']['label'],
1562  $row[‪$GLOBALS['TCA'][$table]['ctrl']['label']],
1563  0,
1564  false,
1565  false,
1566  $row['uid'],
1567  $forceResult
1568  ) ?? '';
1569  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['label_alt'])
1570  && (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['label_alt_force']) || (string)$recordTitle === '')
1571  ) {
1572  $altFields = ‪GeneralUtility::trimExplode(',', ‪$GLOBALS['TCA'][$table]['ctrl']['label_alt'], true);
1573  $tA = [];
1574  if (!empty($recordTitle)) {
1575  $tA[] = $recordTitle;
1576  }
1577  foreach ($altFields as $fN) {
1578  $recordTitle = trim(strip_tags($row[$fN]));
1579  if ((string)$recordTitle !== '') {
1580  $recordTitle = ‪self::getProcessedValue($table, $fN, $recordTitle, 0, false, false, $row['uid']);
1581  if (!‪$GLOBALS['TCA'][$table]['ctrl']['label_alt_force']) {
1582  break;
1583  }
1584  $tA[] = $recordTitle;
1585  }
1586  }
1587  if (‪$GLOBALS['TCA'][$table]['ctrl']['label_alt_force']) {
1588  $recordTitle = implode(', ', $tA);
1589  }
1590  }
1591  }
1592  // If the current result is empty, set it to '[No title]' (localized) and prepare for output if requested
1593  if ($prep || $forceResult) {
1594  if ($prep) {
1595  $recordTitle = ‪self::getRecordTitlePrep($recordTitle);
1596  }
1597  if (trim($recordTitle) === '') {
1598  $recordTitle = ‪self::getNoRecordTitle($prep);
1599  }
1600  }
1601  }
1602 
1603  return $recordTitle;
1604  }
1605 
1614  public static function ‪getRecordTitlePrep($title, $titleLength = 0)
1615  {
1616  // If $titleLength is not a valid positive integer, use BE_USER->uc['titleLen']:
1617  if (!$titleLength || !‪MathUtility::canBeInterpretedAsInteger($titleLength) || $titleLength < 0) {
1618  $titleLength = static::getBackendUserAuthentication()->uc['titleLen'];
1619  }
1620  $titleOrig = htmlspecialchars($title);
1621  $title = htmlspecialchars(GeneralUtility::fixed_lgd_cs($title, $titleLength));
1622  // If title was cropped, offer a tooltip:
1623  if ($titleOrig != $title) {
1624  $title = '<span title="' . $titleOrig . '">' . $title . '</span>';
1625  }
1626  return $title;
1627  }
1628 
1635  public static function ‪getNoRecordTitle($prep = false)
1636  {
1637  $noTitle = '[' .
1638  htmlspecialchars(static::getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title'))
1639  . ']';
1640  if ($prep) {
1641  $noTitle = '<em>' . $noTitle . '</em>';
1642  }
1643  return $noTitle;
1644  }
1645 
1664  public static function ‪getProcessedValue(
1665  $table,
1666  $col,
1667  $value,
1668  $fixed_lgd_chars = 0,
1669  $defaultPassthrough = false,
1670  $noRecordLookup = false,
1671  $uid = 0,
1672  $forceResult = true,
1673  $pid = 0
1674  ) {
1675  if ($col === 'uid') {
1676  // uid is not in TCA-array
1677  return $value;
1678  }
1679  // Check if table and field is configured
1680  if (!isset(‪$GLOBALS['TCA'][$table]['columns'][$col]) || !is_array(‪$GLOBALS['TCA'][$table]['columns'][$col])) {
1681  return null;
1682  }
1683  // Depending on the fields configuration, make a meaningful output value.
1684  $theColConf = ‪$GLOBALS['TCA'][$table]['columns'][$col]['config'] ?? [];
1685  /*****************
1686  *HOOK: pre-processing the human readable output from a record
1687  ****************/
1688  $referenceObject = new \stdClass();
1689  $referenceObject->table = $table;
1690  $referenceObject->fieldName = $col;
1691  $referenceObject->uid = $uid;
1692  $referenceObject->value = &$value;
1693  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['preProcessValue'] ?? [] as $_funcRef) {
1694  GeneralUtility::callUserFunction($_funcRef, $theColConf, $referenceObject);
1695  }
1696 
1697  $l = '';
1698  $lang = static::getLanguageService();
1699  switch ((string)($theColConf['type'] ?? '')) {
1700  case 'radio':
1701  $l = ‪self::getLabelFromItemlist($table, $col, $value);
1702  $l = $lang->sL($l);
1703  break;
1704  case 'inline':
1705  case 'select':
1706  if (!empty($theColConf['MM'])) {
1707  if ($uid) {
1708  // Display the title of MM related records in lists
1709  if ($noRecordLookup) {
1710  $MMfields = [];
1711  $MMfields[] = $theColConf['foreign_table'] . '.uid';
1712  } else {
1713  $MMfields = [$theColConf['foreign_table'] . '.' . ‪$GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label']];
1714  if (isset(‪$GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label_alt'])) {
1716  ',',
1717  ‪$GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label_alt'],
1718  true
1719  ) as $f) {
1720  $MMfields[] = $theColConf['foreign_table'] . '.' . $f;
1721  }
1722  }
1723  }
1725  $dbGroup = GeneralUtility::makeInstance(RelationHandler::class);
1726  $dbGroup->start(
1727  $value,
1728  $theColConf['foreign_table'],
1729  $theColConf['MM'],
1730  $uid,
1731  $table,
1732  $theColConf
1733  );
1734  $selectUids = $dbGroup->tableArray[$theColConf['foreign_table']];
1735  if (is_array($selectUids) && !empty($selectUids)) {
1736  $queryBuilder = static::getQueryBuilderForTable($theColConf['foreign_table']);
1737  $queryBuilder->getRestrictions()
1738  ->removeAll()
1739  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1740 
1741  $result = $queryBuilder
1742  ->select('uid', ...$MMfields)
1743  ->from($theColConf['foreign_table'])
1744  ->where(
1745  $queryBuilder->expr()->in(
1746  'uid',
1747  $queryBuilder->createNamedParameter($selectUids, Connection::PARAM_INT_ARRAY)
1748  )
1749  )
1750  ->execute();
1751 
1752  $mmlA = [];
1753  while ($MMrow = $result->fetch()) {
1754  // Keep sorting of $selectUids
1755  $selectedUid = array_search($MMrow['uid'], $selectUids);
1756  $mmlA[$selectedUid] = $MMrow['uid'];
1757  if (!$noRecordLookup) {
1758  $mmlA[$selectedUid] = static::getRecordTitle(
1759  $theColConf['foreign_table'],
1760  $MMrow,
1761  false,
1762  $forceResult
1763  );
1764  }
1765  }
1766 
1767  if (!empty($mmlA)) {
1768  ksort($mmlA);
1769  $l = implode('; ', $mmlA);
1770  } else {
1771  $l = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:notAvailableAbbreviation');
1772  }
1773  } else {
1774  $l = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:notAvailableAbbreviation');
1775  }
1776  } else {
1777  $l = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:notAvailableAbbreviation');
1778  }
1779  } else {
1780  $columnTsConfig = [];
1781  if ($pid) {
1782  $pageTsConfig = ‪self::getPagesTSconfig($pid);
1783  if (isset($pageTsConfig['TCEFORM.'][$table . '.'][$col . '.']) && is_array($pageTsConfig['TCEFORM.'][$table . '.'][$col . '.'])) {
1784  $columnTsConfig = $pageTsConfig['TCEFORM.'][$table . '.'][$col . '.'];
1785  }
1786  }
1787  $l = ‪self::getLabelsFromItemsList($table, $col, $value, $columnTsConfig);
1788  if (!empty($theColConf['foreign_table']) && !$l && !empty(‪$GLOBALS['TCA'][$theColConf['foreign_table']])) {
1789  if ($noRecordLookup) {
1790  $l = $value;
1791  } else {
1792  $rParts = [];
1793  if ($uid && isset($theColConf['foreign_field']) && $theColConf['foreign_field'] !== '') {
1794  $queryBuilder = static::getQueryBuilderForTable($theColConf['foreign_table']);
1795  $queryBuilder->getRestrictions()
1796  ->removeAll()
1797  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1798  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, static::getBackendUserAuthentication()->workspace));
1799  $constraints = [
1800  $queryBuilder->expr()->eq(
1801  $theColConf['foreign_field'],
1802  $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
1803  )
1804  ];
1805 
1806  if (!empty($theColConf['foreign_table_field'])) {
1807  $constraints[] = $queryBuilder->expr()->eq(
1808  $theColConf['foreign_table_field'],
1809  $queryBuilder->createNamedParameter($table, \PDO::PARAM_STR)
1810  );
1811  }
1812 
1813  // Add additional where clause if foreign_match_fields are defined
1814  $foreignMatchFields = [];
1815  if (is_array($theColConf['foreign_match_fields'])) {
1816  $foreignMatchFields = $theColConf['foreign_match_fields'];
1817  }
1818 
1819  foreach ($foreignMatchFields as $matchField => $matchValue) {
1820  $constraints[] = $queryBuilder->expr()->eq(
1821  $matchField,
1822  $queryBuilder->createNamedParameter($matchValue)
1823  );
1824  }
1825 
1826  $result = $queryBuilder
1827  ->select('*')
1828  ->from($theColConf['foreign_table'])
1829  ->where(...$constraints)
1830  ->execute();
1831 
1832  while ($record = $result->fetch()) {
1833  $rParts[] = $record['uid'];
1834  }
1835  }
1836  if (empty($rParts)) {
1837  $rParts = ‪GeneralUtility::trimExplode(',', $value, true);
1838  }
1839  $lA = [];
1840  foreach ($rParts as $rVal) {
1841  $rVal = (int)$rVal;
1842  $r = ‪self::getRecordWSOL($theColConf['foreign_table'], $rVal);
1843  if (is_array($r)) {
1844  $lA[] = $lang->sL($theColConf['foreign_table_prefix'])
1845  . ‪self::getRecordTitle($theColConf['foreign_table'], $r, false, $forceResult);
1846  } else {
1847  $lA[] = $rVal ? '[' . $rVal . '!]' : '';
1848  }
1849  }
1850  $l = implode(', ', $lA);
1851  }
1852  }
1853  if (empty($l) && !empty($value)) {
1854  // Use plain database value when label is empty
1855  $l = $value;
1856  }
1857  }
1858  break;
1859  case 'group':
1860  // resolve the titles for DB records
1861  if (isset($theColConf['internal_type']) && $theColConf['internal_type'] === 'db') {
1862  if (isset($theColConf['MM']) && $theColConf['MM']) {
1863  if ($uid) {
1864  // Display the title of MM related records in lists
1865  if ($noRecordLookup) {
1866  $MMfields = [];
1867  $MMfields[] = $theColConf['foreign_table'] . '.uid';
1868  } else {
1869  $MMfields = [$theColConf['foreign_table'] . '.' . ‪$GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label']];
1870  $altLabelFields = explode(
1871  ',',
1872  ‪$GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label_alt']
1873  );
1874  foreach ($altLabelFields as $f) {
1875  $f = trim($f);
1876  if ($f !== '') {
1877  $MMfields[] = $theColConf['foreign_table'] . '.' . $f;
1878  }
1879  }
1880  }
1882  $dbGroup = GeneralUtility::makeInstance(RelationHandler::class);
1883  $dbGroup->start(
1884  $value,
1885  $theColConf['foreign_table'],
1886  $theColConf['MM'],
1887  $uid,
1888  $table,
1889  $theColConf
1890  );
1891  $selectUids = $dbGroup->tableArray[$theColConf['foreign_table']];
1892  if (!empty($selectUids) && is_array($selectUids)) {
1893  $queryBuilder = static::getQueryBuilderForTable($theColConf['foreign_table']);
1894  $queryBuilder->getRestrictions()
1895  ->removeAll()
1896  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1897 
1898  $result = $queryBuilder
1899  ->select('uid', ...$MMfields)
1900  ->from($theColConf['foreign_table'])
1901  ->where(
1902  $queryBuilder->expr()->in(
1903  'uid',
1904  $queryBuilder->createNamedParameter(
1905  $selectUids,
1906  Connection::PARAM_INT_ARRAY
1907  )
1908  )
1909  )
1910  ->execute();
1911 
1912  $mmlA = [];
1913  while ($MMrow = $result->fetch()) {
1914  // Keep sorting of $selectUids
1915  $selectedUid = array_search($MMrow['uid'], $selectUids);
1916  $mmlA[$selectedUid] = $MMrow['uid'];
1917  if (!$noRecordLookup) {
1918  $mmlA[$selectedUid] = static::getRecordTitle(
1919  $theColConf['foreign_table'],
1920  $MMrow,
1921  false,
1922  $forceResult
1923  );
1924  }
1925  }
1926 
1927  if (!empty($mmlA)) {
1928  ksort($mmlA);
1929  $l = implode('; ', $mmlA);
1930  } else {
1931  $l = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:notAvailableAbbreviation');
1932  }
1933  } else {
1934  $l = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:notAvailableAbbreviation');
1935  }
1936  } else {
1937  $l = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:notAvailableAbbreviation');
1938  }
1939  } else {
1940  $finalValues = [];
1941  $relationTableName = $theColConf['allowed'];
1942  $explodedValues = ‪GeneralUtility::trimExplode(',', $value, true);
1943 
1944  foreach ($explodedValues as $explodedValue) {
1945  if (‪MathUtility::canBeInterpretedAsInteger($explodedValue)) {
1946  $relationTableNameForField = $relationTableName;
1947  } else {
1948  [$relationTableNameForField, $explodedValue] = ‪self::splitTable_Uid($explodedValue);
1949  }
1950 
1951  $relationRecord = static::getRecordWSOL($relationTableNameForField, $explodedValue);
1952  $finalValues[] = static::getRecordTitle($relationTableNameForField, $relationRecord);
1953  }
1954  $l = implode(', ', $finalValues);
1955  }
1956  } else {
1957  $l = implode(', ', ‪GeneralUtility::trimExplode(',', $value, true));
1958  }
1959  break;
1960  case 'check':
1961  if (!is_array($theColConf['items'])) {
1962  $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');
1963  } elseif (count($theColConf['items']) === 1) {
1964  reset($theColConf['items']);
1965  $invertStateDisplay = current($theColConf['items'])['invertStateDisplay'] ?? false;
1966  if ($invertStateDisplay) {
1967  $value = !$value;
1968  }
1969  $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');
1970  } else {
1971  $lA = [];
1972  foreach ($theColConf['items'] as $key => $val) {
1973  if ($value & 2 ** $key) {
1974  $lA[] = $lang->sL($val[0]);
1975  }
1976  }
1977  $l = implode(', ', $lA);
1978  }
1979  break;
1980  case 'input':
1981  // Hide value 0 for dates, but show it for everything else
1982  // todo: phpstan states that $value always exists and is not nullable. At the moment, this is a false
1983  // positive as null can be passed into this method via $value. As soon as more strict types are
1984  // used, this isset check must be replaced with a more appropriate check.
1985  if (isset($value)) {
1986  $dateTimeFormats = ‪QueryHelper::getDateTimeFormats();
1987 
1988  if (GeneralUtility::inList($theColConf['eval'] ?? '', 'date')) {
1989  // Handle native date field
1990  if (isset($theColConf['dbType']) && $theColConf['dbType'] === 'date') {
1991  $value = $value === $dateTimeFormats['date']['empty'] ? 0 : (int)strtotime($value);
1992  } else {
1993  $value = (int)$value;
1994  }
1995  if (!empty($value)) {
1996  $ageSuffix = '';
1997  $dateColumnConfiguration = ‪$GLOBALS['TCA'][$table]['columns'][$col]['config'];
1998  $ageDisplayKey = 'disableAgeDisplay';
1999 
2000  // generate age suffix as long as not explicitly suppressed
2001  if (!isset($dateColumnConfiguration[$ageDisplayKey])
2002  // non typesafe comparison on intention
2003  || $dateColumnConfiguration[$ageDisplayKey] == false
2004  ) {
2005  $ageSuffix = ' (' . (‪$GLOBALS['EXEC_TIME'] - $value > 0 ? '-' : '')
2006  . self::calcAge(
2007  (int)abs(‪$GLOBALS['EXEC_TIME'] - $value),
2008  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.minutesHoursDaysYears')
2009  )
2010  . ')';
2011  }
2012 
2013  $l = ‪self::date($value) . $ageSuffix;
2014  }
2015  } elseif (GeneralUtility::inList($theColConf['eval'] ?? '', 'time')) {
2016  // Handle native time field
2017  if (isset($theColConf['dbType']) && $theColConf['dbType'] === 'time') {
2018  $value = $value === $dateTimeFormats['time']['empty'] ? 0 : (int)strtotime('1970-01-01 ' . $value . ' UTC');
2019  } else {
2020  $value = (int)$value;
2021  }
2022  if (!empty($value)) {
2023  $l = gmdate('H:i', (int)$value);
2024  }
2025  } elseif (GeneralUtility::inList($theColConf['eval'] ?? '', 'timesec')) {
2026  // Handle native time field
2027  if (isset($theColConf['dbType']) && $theColConf['dbType'] === 'time') {
2028  $value = $value === $dateTimeFormats['time']['empty'] ? 0 : (int)strtotime('1970-01-01 ' . $value . ' UTC');
2029  } else {
2030  $value = (int)$value;
2031  }
2032  if (!empty($value)) {
2033  $l = gmdate('H:i:s', (int)$value);
2034  }
2035  } elseif (GeneralUtility::inList($theColConf['eval'] ?? '', 'datetime')) {
2036  // Handle native datetime field
2037  if (isset($theColConf['dbType']) && $theColConf['dbType'] === 'datetime') {
2038  $value = $value === $dateTimeFormats['datetime']['empty'] ? 0 : (int)strtotime($value);
2039  } else {
2040  $value = (int)$value;
2041  }
2042  if (!empty($value)) {
2043  $l = ‪self::datetime($value);
2044  }
2045  } else {
2046  $l = $value;
2047  }
2048  }
2049  break;
2050  case 'flex':
2051  $l = strip_tags($value);
2052  break;
2053  default:
2054  if ($defaultPassthrough) {
2055  $l = $value;
2056  } elseif (isset($theColConf['MM'])) {
2057  $l = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:notAvailableAbbreviation');
2058  } elseif ($value) {
2059  $l = GeneralUtility::fixed_lgd_cs(strip_tags($value), 200);
2060  }
2061  }
2062  // If this field is a password field, then hide the password by changing it to a random number of asterisk (*)
2063  if (!empty($theColConf['eval']) && stripos($theColConf['eval'], 'password') !== false) {
2064  $l = '';
2065  $randomNumber = random_int(5, 12);
2066  for ($i = 0; $i < $randomNumber; $i++) {
2067  $l .= '*';
2068  }
2069  }
2070  /*****************
2071  *HOOK: post-processing the human readable output from a record
2072  ****************/
2073  $null = null;
2074  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['postProcessValue'] ?? [] as $_funcRef) {
2075  $params = [
2076  'value' => $l,
2077  'colConf' => $theColConf
2078  ];
2079  $l = GeneralUtility::callUserFunction($_funcRef, $params, $null);
2080  }
2081  if ($fixed_lgd_chars) {
2082  return GeneralUtility::fixed_lgd_cs($l, $fixed_lgd_chars);
2083  }
2084  return $l;
2085  }
2086 
2100  public static function ‪getProcessedValueExtra(
2101  $table,
2102  $fN,
2103  $fV,
2104  $fixed_lgd_chars = 0,
2105  $uid = 0,
2106  $forceResult = true,
2107  $pid = 0
2108  ) {
2109  $fVnew = ‪self::getProcessedValue($table, $fN, $fV, $fixed_lgd_chars, true, false, $uid, $forceResult, $pid);
2110  if (!isset($fVnew)) {
2111  if (is_array(‪$GLOBALS['TCA'][$table])) {
2112  if ($fN == ‪$GLOBALS['TCA'][$table]['ctrl']['tstamp'] || $fN == ‪$GLOBALS['TCA'][$table]['ctrl']['crdate']) {
2113  $fVnew = ‪self::datetime((int)$fV);
2114  } elseif ($fN === 'pid') {
2115  // Fetches the path with no regard to the users permissions to select pages.
2116  $fVnew = ‪self::getRecordPath((int)$fV, '1=1', 20);
2117  } else {
2118  $fVnew = $fV;
2119  }
2120  }
2121  }
2122  return $fVnew;
2123  }
2124 
2136  public static function ‪getCommonSelectFields($table, $prefix = '', ‪$fields = [])
2137  {
2138  ‪$fields[] = $prefix . 'uid';
2139  if (isset(‪$GLOBALS['TCA'][$table]['ctrl']['label']) && ‪$GLOBALS['TCA'][$table]['ctrl']['label'] != '') {
2140  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['label'];
2141  }
2142  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['label_alt'])) {
2143  $secondFields = ‪GeneralUtility::trimExplode(',', ‪$GLOBALS['TCA'][$table]['ctrl']['label_alt'], true);
2144  foreach ($secondFields as $fieldN) {
2145  ‪$fields[] = $prefix . $fieldN;
2146  }
2147  }
2148  if (static::isTableWorkspaceEnabled($table)) {
2149  ‪$fields[] = $prefix . 't3ver_state';
2150  ‪$fields[] = $prefix . 't3ver_wsid';
2151  ‪$fields[] = $prefix . 't3ver_count';
2152  }
2153  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['selicon_field'])) {
2154  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['selicon_field'];
2155  }
2156  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['typeicon_column'])) {
2157  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['typeicon_column'];
2158  }
2159  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'])) {
2160  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'];
2161  }
2162  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['starttime'])) {
2163  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['starttime'];
2164  }
2165  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime'])) {
2166  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime'];
2167  }
2168  if (!empty(‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['fe_group'])) {
2169  ‪$fields[] = $prefix . ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['fe_group'];
2170  }
2171  return implode(',', array_unique(‪$fields));
2172  }
2173 
2174  /*******************************************
2175  *
2176  * Backend Modules API functions
2177  *
2178  *******************************************/
2179 
2188  public static function ‪helpTextArray($table, $field)
2189  {
2190  if (!isset(‪$GLOBALS['TCA_DESCR'][$table]['columns'])) {
2191  static::getLanguageService()->loadSingleTableDescription($table);
2192  }
2193  ‪$output = [
2194  'description' => null,
2195  'title' => null,
2196  'moreInfo' => false
2197  ];
2198  if (isset(‪$GLOBALS['TCA_DESCR'][$table]['columns'][$field]) && is_array(‪$GLOBALS['TCA_DESCR'][$table]['columns'][$field])) {
2199  $data = ‪$GLOBALS['TCA_DESCR'][$table]['columns'][$field];
2200  // Add alternative title, if defined
2201  if ($data['alttitle']) {
2202  ‪$output['title'] = $data['alttitle'];
2203  }
2204  // If we have more information to show and access to the cshmanual
2205  if (($data['image_descr'] || $data['seeAlso'] || $data['details'] || $data['syntax'])
2206  && static::getBackendUserAuthentication()->check('modules', 'help_cshmanual')
2207  ) {
2208  ‪$output['moreInfo'] = true;
2209  }
2210  // Add description
2211  if ($data['description']) {
2212  ‪$output['description'] = $data['description'];
2213  }
2214  }
2215  return ‪$output;
2216  }
2217 
2227  public static function ‪helpText($table, $field)
2228  {
2229  $helpTextArray = ‪self::helpTextArray($table, $field);
2230  ‪$output = '';
2231  $arrow = '';
2232  // Put header before the rest of the text
2233  if ($helpTextArray['title'] !== null) {
2234  ‪$output .= '<h2>' . $helpTextArray['title'] . '</h2>';
2235  }
2236  // Add see also arrow if we have more info
2237  if ($helpTextArray['moreInfo']) {
2239  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
2240  $arrow = $iconFactory->getIcon('actions-view-go-forward', ‪Icon::SIZE_SMALL)->render();
2241  }
2242  // Wrap description and arrow in p tag
2243  if ($helpTextArray['description'] !== null || $arrow) {
2244  ‪$output .= '<p class="help-short">' . nl2br(htmlspecialchars($helpTextArray['description'])) . $arrow . '</p>';
2245  }
2246  return ‪$output;
2247  }
2248 
2260  public static function ‪wrapInHelp($table, $field, $text = '', array $overloadHelpText = [])
2261  {
2262  // Initialize some variables
2263  $helpText = '';
2264  $abbrClassAdd = '';
2265  $hasHelpTextOverload = !empty($overloadHelpText);
2266  // Get the help text that should be shown on hover
2267  if (!$hasHelpTextOverload) {
2268  $helpText = ‪self::helpText($table, $field);
2269  }
2270  // If there's a help text or some overload information, proceed with preparing an output
2271  if (!empty($helpText) || $hasHelpTextOverload) {
2272  // If no text was given, just use the regular help icon
2273  if ($text == '') {
2274  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
2275  $text = $iconFactory->getIcon('actions-system-help-open', ‪Icon::SIZE_SMALL)->render();
2276  $abbrClassAdd = ' help-teaser-icon';
2277  }
2278  $text = '<abbr class="help-teaser' . $abbrClassAdd . '">' . $text . '</abbr>';
2279  $wrappedText = '<span class="help-link" data-table="' . $table . '" data-field="' . $field . '"';
2280  // The overload array may provide a title and a description
2281  // If either one is defined, add them to the "data" attributes
2282  if ($hasHelpTextOverload) {
2283  if (isset($overloadHelpText['title'])) {
2284  $wrappedText .= ' data-title="' . htmlspecialchars($overloadHelpText['title']) . '"';
2285  }
2286  if (isset($overloadHelpText['description'])) {
2287  $wrappedText .= ' data-description="' . htmlspecialchars($overloadHelpText['description']) . '"';
2288  }
2289  }
2290  $wrappedText .= '>' . $text . '</span>';
2291  return $wrappedText;
2292  }
2293  return $text;
2294  }
2295 
2306  public static function ‪cshItem($table, $field, $_ = '', $wrap = '')
2307  {
2308  static::getLanguageService()->loadSingleTableDescription($table);
2309  if (is_array(‪$GLOBALS['TCA_DESCR'][$table])
2310  && is_array(‪$GLOBALS['TCA_DESCR'][$table]['columns'][$field])
2311  ) {
2312  // Creating short description
2313  ‪$output = ‪self::wrapInHelp($table, $field);
2314  if (‪$output && $wrap) {
2315  $wrParts = explode('|', $wrap);
2316  ‪$output = $wrParts[0] . ‪$output . $wrParts[1];
2317  }
2318  return ‪$output;
2319  }
2320  return '';
2321  }
2322 
2334  public static function ‪editOnClick($params, $_ = '', $requestUri = '')
2335  {
2336  trigger_error(__METHOD__ . ' has been marked as deprecated and will be removed in TYPO3 v11. Consider using regular links and use the UriBuilder API instead.', E_USER_DEPRECATED);
2337  if ($requestUri == -1) {
2338  $returnUrl = 'T3_THIS_LOCATION';
2339  } else {
2340  $returnUrl = GeneralUtility::quoteJSvalue(rawurlencode($requestUri ?: GeneralUtility::getIndpEnv('REQUEST_URI')));
2341  }
2342  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2343  return 'window.location.href=' . GeneralUtility::quoteJSvalue((string)$uriBuilder->buildUriFromRoute('record_edit') . $params . '&returnUrl=') . '+' . $returnUrl . '; return false;';
2344  }
2345 
2359  public static function ‪viewOnClick(
2360  $pageUid,
2361  $backPath = '',
2362  $rootLine = null,
2363  $anchorSection = '',
2364  $alternativeUrl = '',
2365  $additionalGetVars = '',
2366  $switchFocus = true
2367  ) {
2368  try {
2369  $previewUrl = ‪self::getPreviewUrl(
2370  $pageUid,
2371  $backPath,
2372  $rootLine,
2373  $anchorSection,
2374  $alternativeUrl,
2375  $additionalGetVars,
2376  $switchFocus
2377  );
2378  } catch (‪UnableToLinkToPageException $e) {
2379  return '';
2380  }
2381 
2382  $onclickCode = 'var previewWin = window.open(' . GeneralUtility::quoteJSvalue($previewUrl) . ',\'newTYPO3frontendWindow\');'
2383  . ($switchFocus ? 'previewWin.focus();' : '') . LF
2384  . 'if (previewWin.location.href === ' . GeneralUtility::quoteJSvalue($previewUrl) . ') { previewWin.location.reload(); };';
2385 
2386  return $onclickCode;
2387  }
2388 
2403  public static function ‪getPreviewUrl(
2404  $pageUid,
2405  $backPath = '',
2406  $rootLine = null,
2407  $anchorSection = '',
2408  $alternativeUrl = '',
2409  $additionalGetVars = '',
2410  &$switchFocus = true
2411  ): string {
2412  $viewScript = '/index.php?id=';
2413  if ($alternativeUrl) {
2414  $viewScript = $alternativeUrl;
2415  }
2416 
2417  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['viewOnClickClass'] ?? [] as $className) {
2418  $hookObj = GeneralUtility::makeInstance($className);
2419  if (method_exists($hookObj, 'preProcess')) {
2420  $hookObj->preProcess(
2421  $pageUid,
2422  $backPath,
2423  $rootLine,
2424  $anchorSection,
2425  $viewScript,
2426  $additionalGetVars,
2427  $switchFocus
2428  );
2429  }
2430  }
2431 
2432  // If there is an alternative URL or the URL has been modified by a hook, use that one.
2433  if ($alternativeUrl || $viewScript !== '/index.php?id=') {
2434  $previewUrl = $viewScript;
2435  } else {
2436  $permissionClause = ‪$GLOBALS['BE_USER']->getPagePermsClause(‪Permission::PAGE_SHOW);
2437  $pageInfo = ‪self::readPageAccess($pageUid, $permissionClause) ?: [];
2438  // prepare custom context for link generation (to allow for example time based previews)
2439  $context = clone GeneralUtility::makeInstance(Context::class);
2440  $additionalGetVars .= ‪self::ADMCMD_previewCmds($pageInfo, $context);
2441 
2442  // Build the URL with a site as prefix, if configured
2443  $siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
2444  // Check if the page (= its rootline) has a site attached, otherwise just keep the URL as is
2445  $rootLine = $rootLine ?? ‪BackendUtility::BEgetRootLine($pageUid);
2446  try {
2447  $site = $siteFinder->getSiteByPageId((int)$pageUid, $rootLine);
2448  } catch (‪SiteNotFoundException $e) {
2449  throw new ‪UnableToLinkToPageException('The page ' . $pageUid . ' had no proper connection to a site, no link could be built.', 1559794919);
2450  }
2451  // Create a multi-dimensional array out of the additional get vars
2452  $additionalQueryParams = [];
2453  parse_str($additionalGetVars, $additionalQueryParams);
2454  if (isset($additionalQueryParams['L'])) {
2455  $additionalQueryParams['_language'] = $additionalQueryParams['_language'] ?? $additionalQueryParams['L'];
2456  unset($additionalQueryParams['L']);
2457  }
2458  try {
2459  $previewUrl = (string)$site->getRouter($context)->generateUri(
2460  $pageUid,
2461  $additionalQueryParams,
2462  $anchorSection,
2464  );
2465  } catch (\InvalidArgumentException | ‪InvalidRouteArgumentsException $e) {
2466  throw new ‪UnableToLinkToPageException('The page ' . $pageUid . ' had no proper connection to a site, no link could be built.', 1559794914);
2467  }
2468  }
2469 
2470  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['viewOnClickClass'] ?? [] as $className) {
2471  $hookObj = GeneralUtility::makeInstance($className);
2472  if (method_exists($hookObj, 'postProcess')) {
2473  $previewUrl = $hookObj->postProcess(
2474  $previewUrl,
2475  $pageUid,
2476  $rootLine,
2477  $anchorSection,
2478  $viewScript,
2479  $additionalGetVars,
2480  $switchFocus
2481  );
2482  }
2483  }
2484 
2485  return $previewUrl;
2486  }
2487 
2510  public static function ‪wrapClickMenuOnIcon(
2511  $content,
2512  $table,
2513  $uid = 0,
2514  $context = '',
2515  $_addParams = '',
2516  $_enDisItems = '',
2517  $returnTagParameters = false
2518  ) {
2519  $tagParameters = [
2520  'class' => 't3js-contextmenutrigger',
2521  'data-table' => $table,
2522  'data-uid' => (string)$uid,
2523  'data-context' => $context
2524  ];
2525 
2526  if ($returnTagParameters) {
2527  return $tagParameters;
2528  }
2529  return '<a href="#" ' . GeneralUtility::implodeAttributes($tagParameters, true) . '>' . $content . '</a>';
2530  }
2531 
2539  public static function ‪getLinkToDataHandlerAction($parameters, $redirectUrl = '')
2540  {
2541  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2542  $url = (string)$uriBuilder->buildUriFromRoute('tce_db') . $parameters . '&redirect=';
2543  if ((int)$redirectUrl === -1) {
2544  trigger_error('Generating URLs to DataHandler for JavaScript click handlers is deprecated. Consider using the href attribute instead.', E_USER_DEPRECATED);
2545  $url = GeneralUtility::quoteJSvalue($url) . '+T3_THIS_LOCATION';
2546  } else {
2547  $url .= rawurlencode((string)($redirectUrl ?: GeneralUtility::getIndpEnv('REQUEST_URI')));
2548  }
2549  return $url;
2550  }
2551 
2561  public static function ‪getViewDomain($pageId, $rootLine = null)
2562  {
2563  trigger_error('BackendUtility::getViewDomain() will be removed in TYPO3 v11.0. Use a Site and its PageRouter to link to a page directly', E_USER_DEPRECATED);
2564  $domain = rtrim(GeneralUtility::getIndpEnv('TYPO3_SITE_URL'), '/');
2565  if (!is_array($rootLine)) {
2566  $rootLine = ‪self::BEgetRootLine($pageId);
2567  }
2568  // Checks alternate domains
2569  if (!empty($rootLine)) {
2570  try {
2571  $site = GeneralUtility::makeInstance(SiteFinder::class)
2572  ->getSiteByPageId((int)$pageId, $rootLine);
2573  $uri = $site->getBase();
2574  } catch (‪SiteNotFoundException $e) {
2575  // Just use the current domain
2576  $uri = new ‪Uri($domain);
2577  // Append port number if lockSSLPort is not the standard port 443
2578  $portNumber = (int)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSLPort'];
2579  if ($portNumber > 0 && $portNumber !== 443 && $portNumber < 65536 && $uri->getScheme() === 'https') {
2580  $uri = $uri->withPort((int)$portNumber);
2581  }
2582  }
2583  return (string)$uri;
2584  }
2585  return $domain;
2586  }
2587 
2599  public static function ‪getFuncMenu(
2600  $mainParams,
2601  $elementName,
2602  $currentValue,
2603  $menuItems,
2604  $script = '',
2605  $addParams = ''
2606  ) {
2607  if (!is_array($menuItems) || count($menuItems) <= 1) {
2608  return '';
2609  }
2610  $scriptUrl = ‪self::buildScriptUrl($mainParams, $addParams, $script);
2611  $options = [];
2612  foreach ($menuItems as $value => $label) {
2613  $options[] = '<option value="'
2614  . htmlspecialchars($value) . '"'
2615  . ((string)$currentValue === (string)$value ? ' selected="selected"' : '') . '>'
2616  . htmlspecialchars($label, ENT_COMPAT, 'UTF-8', false) . '</option>';
2617  }
2618  $dataMenuIdentifier = str_replace(['SET[', ']'], '', $elementName);
2619  $dataMenuIdentifier = ‪GeneralUtility::camelCaseToLowerCaseUnderscored($dataMenuIdentifier);
2620  $dataMenuIdentifier = str_replace('_', '-', $dataMenuIdentifier);
2621  if (!empty($options)) {
2622  // relies on module 'TYPO3/CMS/Backend/ActionDispatcher'
2623  $attributes = GeneralUtility::implodeAttributes([
2624  'name' => $elementName,
2625  'class' => 'form-control',
2626  'data-menu-identifier' => $dataMenuIdentifier,
2627  'data-global-event' => 'change',
2628  'data-action-navigate' => '$data=~s/$value/',
2629  'data-navigate-value' => $scriptUrl . '&' . $elementName . '=${value}',
2630  ], true);
2631  return sprintf(
2632  '<select %s>%s</select>',
2633  $attributes,
2634  implode('', $options)
2635  );
2636  }
2637  return '';
2638  }
2639 
2653  public static function ‪getDropdownMenu(
2654  $mainParams,
2655  $elementName,
2656  $currentValue,
2657  $menuItems,
2658  $script = '',
2659  $addParams = ''
2660  ) {
2661  if (!is_array($menuItems) || count($menuItems) <= 1) {
2662  return '';
2663  }
2664  $scriptUrl = ‪self::buildScriptUrl($mainParams, $addParams, $script);
2665  $options = [];
2666  foreach ($menuItems as $value => $label) {
2667  $options[] = '<option value="'
2668  . htmlspecialchars($value) . '"'
2669  . ((string)$currentValue === (string)$value ? ' selected="selected"' : '') . '>'
2670  . htmlspecialchars($label, ENT_COMPAT, 'UTF-8', false) . '</option>';
2671  }
2672  $dataMenuIdentifier = str_replace(['SET[', ']'], '', $elementName);
2673  $dataMenuIdentifier = ‪GeneralUtility::camelCaseToLowerCaseUnderscored($dataMenuIdentifier);
2674  $dataMenuIdentifier = str_replace('_', '-', $dataMenuIdentifier);
2675  if (!empty($options)) {
2676  // relies on module 'TYPO3/CMS/Backend/ActionDispatcher'
2677  $attributes = GeneralUtility::implodeAttributes([
2678  'name' => $elementName,
2679  'data-menu-identifier' => $dataMenuIdentifier,
2680  'data-global-event' => 'change',
2681  'data-action-navigate' => '$data=~s/$value/',
2682  'data-navigate-value' => $scriptUrl . '&' . $elementName . '=${value}',
2683  ], true);
2684  return '
2685  <div class="form-group">
2686  <!-- Function Menu of module -->
2687  <select class="form-control input-sm" ' . $attributes . '>
2688  ' . implode(LF, $options) . '
2689  </select>
2690  </div>
2691  ';
2692  }
2693  return '';
2694  }
2695 
2709  public static function ‪getFuncCheck(
2710  $mainParams,
2711  $elementName,
2712  $currentValue,
2713  $script = '',
2714  $addParams = '',
2715  $tagParams = ''
2716  ) {
2717  // relies on module 'TYPO3/CMS/Backend/ActionDispatcher'
2718  $scriptUrl = ‪self::buildScriptUrl($mainParams, $addParams, $script);
2719  $attributes = GeneralUtility::implodeAttributes([
2720  'type' => 'checkbox',
2721  'class' => 'checkbox',
2722  'name' => $elementName,
2723  'value' => '1',
2724  'data-global-event' => 'change',
2725  'data-action-navigate' => '$data=~s/$value/',
2726  'data-navigate-value' => sprintf('%s&%s=${value}', $scriptUrl, $elementName),
2727  'data-empty-value' => '0',
2728  ], true);
2729  return
2730  '<input ' . $attributes .
2731  ($currentValue ? ' checked="checked"' : '') .
2732  ($tagParams ? ' ' . $tagParams : '') .
2733  ' />';
2734  }
2735 
2749  public static function ‪getFuncInput(
2750  $mainParams,
2751  $elementName,
2752  $currentValue,
2753  $size = 10,
2754  $script = '',
2755  $addParams = ''
2756  ) {
2757  $scriptUrl = ‪self::buildScriptUrl($mainParams, $addParams, $script);
2758  $onChange = 'window.location.href = ' . GeneralUtility::quoteJSvalue($scriptUrl . '&' . $elementName . '=') . '+escape(this.value);';
2759  return '<input type="text" class="form-control" name="' . $elementName . '" value="' . htmlspecialchars($currentValue) . '" onchange="' . htmlspecialchars($onChange) . '" />';
2760  }
2761 
2770  protected static function ‪buildScriptUrl($mainParams, $addParams, $script = '')
2771  {
2772  if (!is_array($mainParams)) {
2773  $mainParams = ['id' => $mainParams];
2774  }
2775  if (!$script) {
2777  }
2778 
2779  if ($routePath = GeneralUtility::_GP('route')) {
2780  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2781  $scriptUrl = (string)$uriBuilder->buildUriFromRoutePath($routePath, $mainParams);
2782  $scriptUrl .= $addParams;
2783  } else {
2784  $scriptUrl = $script . ‪HttpUtility::buildQueryString($mainParams, '?') . $addParams;
2785  }
2786 
2787  return $scriptUrl;
2788  }
2789 
2798  public static function ‪setUpdateSignal($set = '', $params = '')
2799  {
2800  $beUser = static::getBackendUserAuthentication();
2801  $modData = $beUser->getModuleData(
2802  \‪TYPO3\CMS\Backend\Utility\BackendUtility::class . '::getUpdateSignal',
2803  'ses'
2804  );
2805  if ($set) {
2806  $modData[$set] = [
2807  'set' => $set,
2808  'parameter' => $params
2809  ];
2810  } else {
2811  // clear the module data
2812  $modData = [];
2813  }
2814  $beUser->pushModuleData(\‪TYPO3\CMS\Backend\Utility\BackendUtility::class . '::getUpdateSignal', $modData);
2815  }
2816 
2824  public static function ‪getUpdateSignalCode()
2825  {
2826  $signals = [];
2827  $modData = static::getBackendUserAuthentication()->getModuleData(
2828  \‪TYPO3\CMS\Backend\Utility\BackendUtility::class . '::getUpdateSignal',
2829  'ses'
2830  );
2831  if (empty($modData)) {
2832  return '';
2833  }
2834  // Hook: Allows to let TYPO3 execute your JS code
2835  $updateSignals = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['updateSignalHook'] ?? [];
2836  // Loop through all setUpdateSignals and get the JS code
2837  foreach ($modData as $set => $val) {
2838  if (isset($updateSignals[$set])) {
2839  $params = ['set' => $set, 'parameter' => $val['parameter'], 'JScode' => ''];
2840  $ref = null;
2841  GeneralUtility::callUserFunction($updateSignals[$set], $params, $ref);
2842  $signals[] = $params['JScode'];
2843  } else {
2844  switch ($set) {
2845  case 'updatePageTree':
2846  $signals[] = '
2847  if (top && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer.PageTree) {
2848  top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
2849  }
2850  ';
2851  break;
2852  case 'updateFolderTree':
2853  $signals[] = '
2854  if (top && top.nav_frame && top.nav_frame.location) {
2855  top.nav_frame.location.reload(true);
2856  }';
2857  break;
2858  case 'updateModuleMenu':
2859  $signals[] = '
2860  if (top && top.TYPO3.ModuleMenu && top.TYPO3.ModuleMenu.App) {
2861  top.TYPO3.ModuleMenu.App.refreshMenu();
2862  }';
2863  break;
2864  case 'updateTopbar':
2865  $signals[] = '
2866  if (top && top.TYPO3.Backend && top.TYPO3.Backend.Topbar) {
2867  top.TYPO3.Backend.Topbar.refresh();
2868  }';
2869  break;
2870  }
2871  }
2872  }
2873  $content = implode(LF, $signals);
2874  // For backwards compatibility, should be replaced
2876  return $content;
2877  }
2878 
2893  public static function ‪getModuleData(
2894  $MOD_MENU,
2895  $CHANGED_SETTINGS,
2896  $modName,
2897  $type = '',
2898  $dontValidateList = '',
2899  $setDefaultList = ''
2900  ) {
2901  if ($modName && is_string($modName)) {
2902  // Getting stored user-data from this module:
2903  $beUser = static::getBackendUserAuthentication();
2904  $settings = $beUser->getModuleData($modName, $type);
2905  $changed = 0;
2906  if (!is_array($settings)) {
2907  $changed = 1;
2908  $settings = [];
2909  }
2910  if (is_array($MOD_MENU)) {
2911  foreach ($MOD_MENU as $key => $var) {
2912  // If a global var is set before entering here. eg if submitted, then it's substituting the current value the array.
2913  if (is_array($CHANGED_SETTINGS) && isset($CHANGED_SETTINGS[$key])) {
2914  if (is_array($CHANGED_SETTINGS[$key])) {
2915  $serializedSettings = serialize($CHANGED_SETTINGS[$key]);
2916  if ((string)$settings[$key] !== $serializedSettings) {
2917  $settings[$key] = $serializedSettings;
2918  $changed = 1;
2919  }
2920  } else {
2921  if ((string)$settings[$key] !== (string)$CHANGED_SETTINGS[$key]) {
2922  $settings[$key] = $CHANGED_SETTINGS[$key];
2923  $changed = 1;
2924  }
2925  }
2926  }
2927  // If the $var is an array, which denotes the existence of a menu, we check if the value is permitted
2928  if (is_array($var) && (!$dontValidateList || !GeneralUtility::inList($dontValidateList, $key))) {
2929  // If the setting is an array or not present in the menu-array, MOD_MENU, then the default value is inserted.
2930  if (is_array($settings[$key]) || !isset($MOD_MENU[$key][$settings[$key]])) {
2931  $settings[$key] = (string)key($var);
2932  $changed = 1;
2933  }
2934  }
2935  // Sets default values (only strings/checkboxes, not menus)
2936  if ($setDefaultList && !is_array($var)) {
2937  if (GeneralUtility::inList($setDefaultList, $key) && !isset($settings[$key])) {
2938  $settings[$key] = (string)$var;
2939  }
2940  }
2941  }
2942  } else {
2943  throw new \RuntimeException('No menu', 1568119229);
2944  }
2945  if ($changed) {
2946  $beUser->pushModuleData($modName, $settings);
2947  }
2948  return $settings;
2949  }
2950  throw new \RuntimeException('Wrong module name "' . $modName . '"', 1568119221);
2951  }
2952 
2953  /*******************************************
2954  *
2955  * Core
2956  *
2957  *******************************************/
2967  public static function ‪lockRecords($table = '', $uid = 0, $pid = 0)
2968  {
2969  $beUser = static::getBackendUserAuthentication();
2970  if (isset($beUser->user['uid'])) {
2971  $userId = (int)$beUser->user['uid'];
2972  ‪if ($table && $uid) {
2973  $fieldsValues = [
2974  'userid' => $userId,
2975  'feuserid' => 0,
2976  'tstamp' => ‪$GLOBALS['EXEC_TIME'],
2977  'record_table' => $table,
2978  'record_uid' => $uid,
2979  'username' => $beUser->user['username'],
2980  'record_pid' => $pid
2981  ];
2982  GeneralUtility::makeInstance(ConnectionPool::class)
2983  ->getConnectionForTable('sys_lockedrecords')
2984  ->insert(
2985  'sys_lockedrecords',
2986  $fieldsValues
2987  );
2988  } else {
2989  GeneralUtility::makeInstance(ConnectionPool::class)
2990  ->getConnectionForTable('sys_lockedrecords')
2991  ->delete(
2992  'sys_lockedrecords',
2993  ['userid' => (int)$userId]
2994  );
2995  }
2996  }
2997  }
2998 
3011  public static function ‪isRecordLocked($table, $uid)
3012  {
3013  $runtimeCache = ‪self::getRuntimeCache();
3014  $cacheId = 'backend-recordLocked';
3015  $recordLockedCache = $runtimeCache->get($cacheId);
3016  if ($recordLockedCache !== false) {
3017  $lockedRecords = $recordLockedCache;
3018  } else {
3019  $lockedRecords = [];
3020 
3021  $queryBuilder = static::getQueryBuilderForTable('sys_lockedrecords');
3022  $result = $queryBuilder
3023  ->select('*')
3024  ->from('sys_lockedrecords')
3025  ->where(
3026  $queryBuilder->expr()->neq(
3027  'sys_lockedrecords.userid',
3028  $queryBuilder->createNamedParameter(
3029  static::getBackendUserAuthentication()->user['uid'],
3030  \PDO::PARAM_INT
3031  )
3032  ),
3033  $queryBuilder->expr()->gt(
3034  'sys_lockedrecords.tstamp',
3035  $queryBuilder->createNamedParameter(
3036  ‪$GLOBALS['EXEC_TIME'] - 2 * 3600,
3037  \PDO::PARAM_INT
3038  )
3039  )
3040  )
3041  ->execute();
3042 
3043  $lang = static::getLanguageService();
3044  while ($row = $result->fetch()) {
3045  // Get the type of the user that locked this record:
3046  if ($row['userid']) {
3047  $userTypeLabel = 'beUser';
3048  } elseif ($row['feuserid']) {
3049  $userTypeLabel = 'feUser';
3050  } else {
3051  $userTypeLabel = 'user';
3052  }
3053  $userType = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.' . $userTypeLabel);
3054  // Get the username (if available):
3055  if ($row['username']) {
3056  $userName = $row['username'];
3057  } else {
3058  $userName = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.unknownUser');
3059  }
3060  $lockedRecords[$row['record_table'] . ':' . $row['record_uid']] = $row;
3061  $lockedRecords[$row['record_table'] . ':' . $row['record_uid']]['msg'] = sprintf(
3062  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.lockedRecordUser'),
3063  $userType,
3064  $userName,
3065  self::calcAge(
3066  ‪$GLOBALS['EXEC_TIME'] - $row['tstamp'],
3067  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.minutesHoursDaysYears')
3068  )
3069  );
3070  if ($row['record_pid'] && !isset($lockedRecords[$row['record_table'] . ':' . $row['record_pid']])) {
3071  $lockedRecords['pages:' . $row['record_pid']]['msg'] = sprintf(
3072  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.lockedRecordUser_content'),
3073  $userType,
3074  $userName,
3075  self::calcAge(
3076  ‪$GLOBALS['EXEC_TIME'] - $row['tstamp'],
3077  $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.minutesHoursDaysYears')
3078  )
3079  );
3080  }
3081  }
3082  $runtimeCache->set($cacheId, $lockedRecords);
3083  }
3084 
3085  return $lockedRecords[$table . ':' . $uid] ?? false;
3086  }
3087 
3096  public static function ‪getTCEFORM_TSconfig($table, $row)
3097  {
3098  ‪self::fixVersioningPid($table, $row);
3099  $res = [];
3100  // Get main config for the table
3101  [$TScID, $cPid] = ‪self::getTSCpid($table, $row['uid'], $row['pid']);
3102  if ($TScID >= 0) {
3103  $tsConfig = static::getPagesTSconfig($TScID)['TCEFORM.'][$table . '.'] ?? [];
3104  $typeVal = ‪self::getTCAtypeValue($table, $row);
3105  foreach ($tsConfig as $key => $val) {
3106  if (is_array($val)) {
3107  $fieldN = substr($key, 0, -1);
3108  $res[$fieldN] = $val;
3109  unset($res[$fieldN]['types.']);
3110  if ((string)$typeVal !== '' && is_array($val['types.'][$typeVal . '.'])) {
3111  ‪ArrayUtility::mergeRecursiveWithOverrule($res[$fieldN], $val['types.'][$typeVal . '.']);
3112  }
3113  }
3114  }
3115  }
3116  $res['_CURRENT_PID'] = $cPid;
3117  $res['_THIS_UID'] = $row['uid'];
3118  // So the row will be passed to foreign_table_where_query()
3119  $res['_THIS_ROW'] = $row;
3120  return $res;
3121  }
3122 
3137  public static function ‪getTSconfig_pidValue($table, $uid, $pid)
3138  {
3139  // If pid is an integer this takes precedence in our lookup.
3141  $thePidValue = (int)$pid;
3142  // If ref to another record, look that record up.
3143  if ($thePidValue < 0) {
3144  $pidRec = ‪self::getRecord($table, abs($thePidValue), 'pid');
3145  $thePidValue = is_array($pidRec) ? $pidRec['pid'] : -2;
3146  }
3147  } else {
3148  // Try to fetch the record pid from uid. If the uid is 'NEW...' then this will of course return nothing
3149  $rr = ‪self::getRecord($table, $uid);
3150  $thePidValue = null;
3151  if (is_array($rr)) {
3152  // First check if the t3ver_oid value is greater 0, which means
3153  // it is a workspace element. If so, get the "real" record:
3154  if ((int)($rr['t3ver_oid'] ?? 0) > 0) {
3155  $rr = ‪self::getRecord($table, $rr['t3ver_oid'], 'pid');
3156  if (is_array($rr)) {
3157  $thePidValue = $rr['pid'];
3158  }
3159  } else {
3160  // Returning the "pid" of the record
3161  $thePidValue = $rr['pid'];
3162  }
3163  }
3164  if (!$thePidValue) {
3165  // Returns -1 if the record with this pid was not found.
3166  $thePidValue = -1;
3167  }
3168  }
3169  return $thePidValue;
3170  }
3171 
3184  public static function ‪getTSCpidCached($table, $uid, $pid)
3185  {
3186  $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('runtime');
3187  $firstLevelCache = $runtimeCache->get('backendUtilityTscPidCached') ?: [];
3188  $key = $table . ':' . $uid . ':' . $pid;
3189  if (!isset($firstLevelCache[$key])) {
3190  $firstLevelCache[$key] = static::getTSCpid($table, (int)$uid, (int)$pid);
3191  $runtimeCache->set('backendUtilityTscPidCached', $firstLevelCache);
3192  }
3193  return $firstLevelCache[$key];
3194  }
3195 
3208  public static function ‪getTSCpid($table, $uid, $pid)
3209  {
3210  // If pid is negative (referring to another record) the pid of the other record is fetched and returned.
3211  $cPid = ‪self::getTSconfig_pidValue($table, $uid, $pid);
3212  // $TScID is the id of $table = pages, else it's the pid of the record.
3213  $TScID = $table === 'pages' && ‪MathUtility::canBeInterpretedAsInteger($uid) ? $uid : $cPid;
3214  return [$TScID, $cPid];
3215  }
3216 
3225  public static function ‪softRefParserObj($spKey)
3226  {
3227  $className = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser'][$spKey] ?? false;
3228  if ($className) {
3229  return GeneralUtility::makeInstance($className);
3230  }
3231  return false;
3232  }
3233 
3239  protected static function ‪getRuntimeCache()
3240  {
3241  return GeneralUtility::makeInstance(CacheManager::class)->getCache('runtime');
3242  }
3243 
3252  public static function ‪explodeSoftRefParserList($parserList)
3253  {
3254  // Return immediately if list is blank:
3255  if ((string)$parserList === '') {
3256  return false;
3257  }
3258 
3259  $runtimeCache = ‪self::getRuntimeCache();
3260  $cacheId = 'backend-softRefList-' . md5($parserList);
3261  $parserListCache = $runtimeCache->get($cacheId);
3262  if ($parserListCache !== false) {
3263  return $parserListCache;
3264  }
3265 
3266  // Otherwise parse the list:
3267  $keyList = ‪GeneralUtility::trimExplode(',', $parserList, true);
3268  ‪$output = [];
3269  foreach ($keyList as $val) {
3270  $reg = [];
3271  if (preg_match('/^([[:alnum:]_-]+)\\[(.*)\\]$/', $val, $reg)) {
3272  ‪$output[$reg[1]] = ‪GeneralUtility::trimExplode(';', $reg[2], true);
3273  } else {
3274  ‪$output[$val] = '';
3275  }
3276  }
3277  $runtimeCache->set($cacheId, ‪$output);
3278  return ‪$output;
3279  }
3280 
3287  public static function ‪isModuleSetInTBE_MODULES($modName)
3288  {
3289  $loaded = [];
3290  foreach (‪$GLOBALS['TBE_MODULES'] as $mkey => $list) {
3291  $loaded[$mkey] = 1;
3292  if (!is_array($list) && trim($list)) {
3293  $subList = ‪GeneralUtility::trimExplode(',', $list, true);
3294  foreach ($subList as $skey) {
3295  $loaded[$mkey . '_' . $skey] = 1;
3296  }
3297  }
3298  }
3299  return $modName && isset($loaded[$modName]);
3300  }
3301 
3311  public static function ‪referenceCount($table, $ref, $msg = '', $count = null)
3312  {
3313  if ($count === null) {
3314 
3315  // Build base query
3316  $queryBuilder = static::getQueryBuilderForTable('sys_refindex');
3317  $queryBuilder
3318  ->count('*')
3319  ->from('sys_refindex')
3320  ->where(
3321  $queryBuilder->expr()->eq('ref_table', $queryBuilder->createNamedParameter($table, \PDO::PARAM_STR)),
3322  $queryBuilder->expr()->eq('deleted', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
3323  );
3324 
3325  // Look up the path:
3326  if ($table === '_FILE') {
3327  if (!GeneralUtility::isFirstPartOfStr($ref, ‪Environment::getPublicPath())) {
3328  return '';
3329  }
3330 
3332  $queryBuilder->andWhere(
3333  $queryBuilder->expr()->eq('ref_string', $queryBuilder->createNamedParameter($ref, \PDO::PARAM_STR))
3334  );
3335  } else {
3336  $queryBuilder->andWhere(
3337  $queryBuilder->expr()->eq('ref_uid', $queryBuilder->createNamedParameter($ref, \PDO::PARAM_INT))
3338  );
3339  if ($table === 'sys_file') {
3340  $queryBuilder->andWhere($queryBuilder->expr()->neq('tablename', $queryBuilder->quote('sys_file_metadata')));
3341  }
3342  }
3343 
3344  $count = $queryBuilder->execute()->fetchColumn(0);
3345  }
3346 
3347  if ($count) {
3348  return $msg ? sprintf($msg, $count) : $count;
3349  }
3350  return $msg ? '' : 0;
3351  }
3352 
3361  public static function ‪translationCount($table, $ref, $msg = '')
3362  {
3363  $count = null;
3364  if (‪$GLOBALS['TCA'][$table]['ctrl']['languageField']
3365  && ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']
3366  ) {
3367  $queryBuilder = static::getQueryBuilderForTable($table);
3368  $queryBuilder->getRestrictions()
3369  ->removeAll()
3370  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
3371 
3372  $count = (int)$queryBuilder
3373  ->count('*')
3374  ->from($table)
3375  ->where(
3376  $queryBuilder->expr()->eq(
3377  ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'],
3378  $queryBuilder->createNamedParameter($ref, \PDO::PARAM_INT)
3379  ),
3380  $queryBuilder->expr()->neq(
3381  ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'],
3382  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
3383  )
3384  )
3385  ->execute()
3386  ->fetchColumn(0);
3387  }
3388 
3389  if ($count && $msg) {
3390  return sprintf($msg, $count);
3391  }
3392 
3393  if ($count) {
3394  return $msg ? sprintf($msg, $count) : $count;
3395  }
3396  return $msg ? '' : 0;
3397  }
3398 
3399  /*******************************************
3400  *
3401  * Workspaces / Versioning
3402  *
3403  *******************************************/
3416  public static function ‪selectVersionsOfRecord(
3417  $table,
3418  $uid,
3419  ‪$fields = '*',
3420  $workspace = 0,
3421  $includeDeletedRecords = false,
3422  $row = null
3423  ) {
3424  $realPid = 0;
3425  $outputRows = [];
3426  if (static::isTableWorkspaceEnabled($table)) {
3427  if (is_array($row) && !$includeDeletedRecords) {
3428  $row['_CURRENT_VERSION'] = true;
3429  $realPid = $row['pid'];
3430  $outputRows[] = $row;
3431  } else {
3432  // Select UID version:
3433  $row = ‪self::getRecord($table, $uid, ‪$fields, '', !$includeDeletedRecords);
3434  // Add rows to output array:
3435  if ($row) {
3436  $row['_CURRENT_VERSION'] = true;
3437  $realPid = $row['pid'];
3438  $outputRows[] = $row;
3439  }
3440  }
3441 
3442  $queryBuilder = static::getQueryBuilderForTable($table);
3443  $queryBuilder->getRestrictions()->removeAll();
3444 
3445  // build fields to select
3446  $queryBuilder->select(...‪GeneralUtility::trimExplode(',', ‪$fields));
3447 
3448  $queryBuilder
3449  ->from($table)
3450  ->where(
3451  $queryBuilder->expr()->neq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)),
3452  $queryBuilder->expr()->eq('t3ver_oid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))
3453  )
3454  ->orderBy('uid', 'DESC');
3455 
3456  if (!$includeDeletedRecords) {
3457  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
3458  }
3459 
3460  if ($workspace === 0) {
3461  // Only in Live WS
3462  $queryBuilder->andWhere(
3463  $queryBuilder->expr()->eq(
3464  't3ver_wsid',
3465  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
3466  )
3467  );
3468  } elseif ($workspace !== null) {
3469  // In Live WS and Workspace with given ID
3470  $queryBuilder->andWhere(
3471  $queryBuilder->expr()->in(
3472  't3ver_wsid',
3473  $queryBuilder->createNamedParameter([0, (int)$workspace], Connection::PARAM_INT_ARRAY)
3474  )
3475  );
3476  }
3477 
3478  $rows = $queryBuilder->execute()->fetchAll();
3479 
3480  // Add rows to output array:
3481  if (is_array($rows)) {
3482  $outputRows = array_merge($outputRows, $rows);
3483  }
3484  // Set real-pid:
3485  foreach ($outputRows as $idx => $oRow) {
3486  $outputRows[$idx]['_REAL_PID'] = $realPid;
3487  }
3488  return $outputRows;
3489  }
3490  return null;
3491  }
3492 
3511  public static function ‪fixVersioningPid($table, &$rr, $ignoreWorkspaceMatch = false)
3512  {
3513  if (!‪ExtensionManagementUtility::isLoaded('workspaces')) {
3514  return;
3515  }
3516  if (!static::isTableWorkspaceEnabled($table)) {
3517  return;
3518  }
3519  // Check that the input record is an offline version from a table that supports versioning
3520  if (!is_array($rr)) {
3521  return;
3522  }
3523  $incomingPid = $rr['pid'] ?? null;
3524  // Check values for t3ver_oid and t3ver_wsid:
3525  if (isset($rr['t3ver_oid']) && isset($rr['t3ver_wsid']) && isset($rr['t3ver_state'])) {
3526  // If "t3ver_oid" is already a field, just set this:
3527  $oid = $rr['t3ver_oid'];
3528  $workspaceId = (int)$rr['t3ver_wsid'];
3529  $versionState = (int)$rr['t3ver_state'];
3530  } else {
3531  $oid = 0;
3532  $workspaceId = 0;
3533  $versionState = 0;
3534  // Otherwise we have to expect "uid" to be in the record and look up based on this:
3535  $newPidRec = ‪self::getRecord($table, $rr['uid'], 'pid,t3ver_oid,t3ver_wsid,t3ver_state');
3536  if (is_array($newPidRec)) {
3537  $incomingPid = $newPidRec['pid'];
3538  $oid = $newPidRec['t3ver_oid'];
3539  $workspaceId = $newPidRec['t3ver_wsid'];
3540  $versionState = $newPidRec['t3ver_state'];
3541  }
3542  }
3543  if ($oid && ($ignoreWorkspaceMatch || (static::getBackendUserAuthentication() instanceof ‪BackendUserAuthentication && $workspaceId === (int)static::getBackendUserAuthentication()->workspace))) {
3544  if ($incomingPid === null) {
3545  // This can be removed, as this is the same for all versioned records
3546  $onlineRecord = ‪self::getRecord($table, $oid, 'pid');
3547  if (is_array($onlineRecord)) {
3548  $rr['_ORIG_pid'] = $onlineRecord['pid'];
3549  $rr['pid'] = $onlineRecord['pid'];
3550  }
3551  } else {
3552  // This can be removed, as this is the same for all versioned records (clearly obvious here)
3553  $rr['_ORIG_pid'] = $incomingPid;
3554  $rr['pid'] = $incomingPid;
3555  }
3556  // Use moved PID in case of move pointer
3557  if ($versionState === ‪VersionState::MOVE_POINTER) {
3558  if ($incomingPid !== null) {
3559  $movedPageIdInWorkspace = $incomingPid;
3560  } else {
3561  $versionedMovePointer = ‪self::getRecord($table, $rr['uid'], 'pid');
3562  $movedPageIdInWorkspace = $versionedMovePointer['pid'];
3563  }
3564  $rr['_ORIG_pid'] = $incomingPid;
3565  $rr['pid'] = $movedPageIdInWorkspace;
3566  }
3567  }
3568  }
3569 
3586  public static function ‪workspaceOL($table, &$row, $wsid = -99, $unsetMovePointers = false)
3587  {
3588  if (!‪ExtensionManagementUtility::isLoaded('workspaces')) {
3589  return;
3590  }
3591  // If this is FALSE the placeholder is shown raw in the backend.
3592  // I don't know if this move can be useful for users to toggle. Technically it can help debugging.
3593  $previewMovePlaceholders = true;
3594  // Initialize workspace ID
3595  if ($wsid == -99 && static::getBackendUserAuthentication() instanceof ‪BackendUserAuthentication) {
3596  $wsid = static::getBackendUserAuthentication()->workspace;
3597  }
3598  // Check if workspace is different from zero and record is set:
3599  if ($wsid !== 0 && is_array($row)) {
3600  // Check if input record is a move-placeholder and if so, find the pointed-to live record:
3601  $movePldSwap = null;
3602  $orig_uid = 0;
3603  $orig_pid = 0;
3604  if ($previewMovePlaceholders) {
3605  $orig_uid = $row['uid'];
3606  $orig_pid = $row['pid'];
3607  $movePldSwap = ‪self::movePlhOL($table, $row);
3608  }
3610  $wsid,
3611  $table,
3612  $row['uid'],
3613  implode(',', static::purgeComputedPropertyNames(array_keys($row)))
3614  );
3615  // If version was found, swap the default record with that one.
3616  if (is_array($wsAlt)) {
3617  // Check if this is in move-state:
3618  if ($previewMovePlaceholders && !$movePldSwap && static::isTableWorkspaceEnabled($table) && $unsetMovePointers) {
3619  // Only for WS ver 2... (moving)
3620  // If t3ver_state is not found, then find it... (but we like best if it is here...)
3621  if (!isset($wsAlt['t3ver_state'])) {
3622  $stateRec = ‪self::getRecord($table, $wsAlt['uid'], 't3ver_state');
3623  $versionState = ‪VersionState::cast($stateRec['t3ver_state']);
3624  } else {
3625  $versionState = ‪VersionState::cast($wsAlt['t3ver_state']);
3626  }
3627  if ($versionState->equals(‪VersionState::MOVE_POINTER)) {
3628  // @todo Same problem as frontend in versionOL(). See TODO point there.
3629  $row = false;
3630  return;
3631  }
3632  }
3633  // Always correct PID from -1 to what it should be
3634  if (isset($wsAlt['pid'])) {
3635  // Keep the old (-1) - indicates it was a version.
3636  $wsAlt['_ORIG_pid'] = $wsAlt['pid'];
3637  // Set in the online versions PID.
3638  $wsAlt['pid'] = $row['pid'];
3639  }
3640  // For versions of single elements or page+content, swap UID and PID
3641  $wsAlt['_ORIG_uid'] = $wsAlt['uid'];
3642  $wsAlt['uid'] = $row['uid'];
3643  // Backend css class:
3644  $wsAlt['_CSSCLASS'] = 'ver-element';
3645  // Changing input record to the workspace version alternative:
3646  $row = $wsAlt;
3647  }
3648  // If the original record was a move placeholder, the uid and pid of that is preserved here:
3649  if ($movePldSwap) {
3650  $row['_MOVE_PLH'] = true;
3651  $row['_MOVE_PLH_uid'] = $orig_uid;
3652  $row['_MOVE_PLH_pid'] = $orig_pid;
3653  // For display; To make the icon right for the placeholder vs. the original
3654  $row['t3ver_state'] = (string)new ‪VersionState(‪VersionState::MOVE_PLACEHOLDER);
3655  }
3656  }
3657  }
3658 
3669  public static function ‪movePlhOL($table, &$row)
3670  {
3671  if (static::isTableWorkspaceEnabled($table)) {
3672  // If t3ver_move_id or t3ver_state is not found, then find it... (but we like best if it is here...)
3673  if (!isset($row['t3ver_move_id']) || !isset($row['t3ver_state'])) {
3674  $moveIDRec = ‪self::getRecord($table, $row['uid'], 't3ver_move_id, t3ver_state');
3675  $moveID = $moveIDRec['t3ver_move_id'];
3676  $versionState = ‪VersionState::cast($moveIDRec['t3ver_state']);
3677  } else {
3678  $moveID = $row['t3ver_move_id'];
3679  $versionState = ‪VersionState::cast($row['t3ver_state']);
3680  }
3681  // Find pointed-to record.
3682  if ($versionState->equals(‪VersionState::MOVE_PLACEHOLDER) && $moveID) {
3683  if ($origRow = self::getRecord(
3684  $table,
3685  $moveID,
3686  implode(',', static::purgeComputedPropertyNames(array_keys($row)))
3687  )) {
3688  $row = $origRow;
3689  return true;
3690  }
3691  }
3692  }
3693  return false;
3694  }
3695 
3705  public static function ‪getWorkspaceVersionOfRecord($workspace, $table, $uid, ‪$fields = '*')
3706  {
3707  if (‪ExtensionManagementUtility::isLoaded('workspaces')) {
3708  if ($workspace !== 0 && self::isTableWorkspaceEnabled($table)) {
3709 
3710  // Select workspace version of record:
3711  $queryBuilder = static::getQueryBuilderForTable($table);
3712  $queryBuilder->getRestrictions()
3713  ->removeAll()
3714  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
3715 
3716  // build fields to select
3717  $queryBuilder->select(...‪GeneralUtility::trimExplode(',', ‪$fields));
3718 
3719  $row = $queryBuilder
3720  ->from($table)
3721  ->where(
3722  $queryBuilder->expr()->eq(
3723  't3ver_oid',
3724  $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
3725  ),
3726  $queryBuilder->expr()->eq(
3727  't3ver_wsid',
3728  $queryBuilder->createNamedParameter($workspace, \PDO::PARAM_INT)
3729  )
3730  )
3731  ->execute()
3732  ->fetch();
3733 
3734  return $row;
3735  }
3736  }
3737  return false;
3738  }
3739 
3748  public static function ‪getLiveVersionOfRecord($table, $uid, ‪$fields = '*')
3749  {
3750  $liveVersionId = ‪self::getLiveVersionIdOfRecord($table, $uid);
3751  if ($liveVersionId !== null) {
3752  return ‪self::getRecord($table, $liveVersionId, ‪$fields);
3753  }
3754  return null;
3755  }
3756 
3765  public static function ‪getLiveVersionIdOfRecord($table, $uid)
3766  {
3767  if (!‪ExtensionManagementUtility::isLoaded('workspaces')) {
3768  return null;
3769  }
3770  $liveVersionId = null;
3771  if (self::isTableWorkspaceEnabled($table)) {
3772  $currentRecord = ‪self::getRecord($table, $uid, 'pid,t3ver_oid');
3773  if (is_array($currentRecord) && (int)$currentRecord['t3ver_oid'] > 0) {
3774  $liveVersionId = $currentRecord['t3ver_oid'];
3775  }
3776  }
3777  return $liveVersionId;
3778  }
3779 
3788  public static function ‪versioningPlaceholderClause($table)
3789  {
3790  if (static::isTableWorkspaceEnabled($table) && static::getBackendUserAuthentication() instanceof ‪BackendUserAuthentication) {
3791  $currentWorkspace = (int)static::getBackendUserAuthentication()->workspace;
3792  return ' AND (' . $table . '.t3ver_state <= ' . new ‪VersionState(‪VersionState::DEFAULT_STATE) . ' OR ' . $table . '.t3ver_wsid = ' . $currentWorkspace . ')';
3793  }
3794  return '';
3795  }
3796 
3805  public static function ‪getWorkspaceWhereClause($table, $workspaceId = null)
3806  {
3807  $whereClause = '';
3808  if (self::isTableWorkspaceEnabled($table) && static::getBackendUserAuthentication() instanceof ‪BackendUserAuthentication) {
3809  if ($workspaceId === null) {
3810  $workspaceId = static::getBackendUserAuthentication()->workspace;
3811  }
3812  $workspaceId = (int)$workspaceId;
3813  $comparison = $workspaceId === 0 ? '=' : '>';
3814  $whereClause = ' AND ' . $table . '.t3ver_wsid=' . $workspaceId . ' AND ' . $table . '.t3ver_oid' . $comparison . '0';
3815  }
3816  return $whereClause;
3817  }
3818 
3827  public static function ‪wsMapId($table, $uid)
3828  {
3829  $wsRec = null;
3830  if (static::getBackendUserAuthentication() instanceof ‪BackendUserAuthentication) {
3832  static::getBackendUserAuthentication()->workspace,
3833  $table,
3834  $uid,
3835  'uid'
3836  );
3837  }
3838  return is_array($wsRec) ? $wsRec['uid'] : $uid;
3839  }
3840 
3851  public static function ‪getMovePlaceholder($table, $uid, ‪$fields = '*', $workspace = null)
3852  {
3853  if ($workspace === null && static::getBackendUserAuthentication() instanceof ‪BackendUserAuthentication) {
3854  $workspace = static::getBackendUserAuthentication()->workspace;
3855  }
3856  if ((int)$workspace !== 0 && static::isTableWorkspaceEnabled($table)) {
3857  // Select workspace version of record:
3858  $queryBuilder = static::getQueryBuilderForTable($table);
3859  $queryBuilder->getRestrictions()
3860  ->removeAll()
3861  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
3862 
3863  $row = $queryBuilder
3864  ->select(...‪GeneralUtility::trimExplode(',', ‪$fields, true))
3865  ->from($table)
3866  ->where(
3867  $queryBuilder->expr()->eq(
3868  't3ver_state',
3869  $queryBuilder->createNamedParameter(
3871  \PDO::PARAM_INT
3872  )
3873  ),
3874  $queryBuilder->expr()->eq(
3875  't3ver_move_id',
3876  $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
3877  ),
3878  $queryBuilder->expr()->eq(
3879  't3ver_wsid',
3880  $queryBuilder->createNamedParameter($workspace, \PDO::PARAM_INT)
3881  )
3882  )
3883  ->execute()
3884  ->fetch();
3885 
3886  return $row ?: false;
3887  }
3888  return false;
3889  }
3890 
3891  /*******************************************
3892  *
3893  * Miscellaneous
3894  *
3895  *******************************************/
3907  public static function ‪TYPO3_copyRightNotice()
3908  {
3909  trigger_error('BackendUtility::TYPO3_copyRightNotice() will be removed in TYPO3 v11.0, use the Typo3Information PHP class instead.', E_USER_DEPRECATED);
3910  $copyrightGenerator = GeneralUtility::makeInstance(Typo3Information::class, static::getLanguageService());
3911  return $copyrightGenerator->getCopyrightNotice();
3912  }
3913 
3922  public static function ‪ADMCMD_previewCmds($pageInfo, ‪Context $context)
3923  {
3924  if ($pageInfo === []) {
3925  return '';
3926  }
3927  // Initialize access restriction values from current page
3928  $access = [
3929  'fe_group' => (string)($pageInfo['fe_group'] ?? ''),
3930  'starttime' => (int)($pageInfo['starttime'] ?? 0),
3931  'endtime' => (int)($pageInfo['endtime'] ?? 0)
3932  ];
3933  // Only check rootline if the current page has not set extendToSubpages itself
3934  if (!(bool)($pageInfo['extendToSubpages'] ?? false)) {
3935  $rootline = ‪self::BEgetRootLine((int)($pageInfo['uid'] ?? 0));
3936  // remove the current page from the rootline
3937  array_shift($rootline);
3938  foreach ($rootline as $page) {
3939  // Skip root node, invalid pages and pages which do not define extendToSubpages
3940  if ((int)($page['uid'] ?? 0) <= 0 || !(bool)($page['extendToSubpages'] ?? false)) {
3941  continue;
3942  }
3943  $access['fe_group'] = (string)($page['fe_group'] ?? '');
3944  $access['starttime'] = (int)($page['starttime'] ?? 0);
3945  $access['endtime'] = (int)($page['endtime'] ?? 0);
3946  // Stop as soon as a page in the rootline has extendToSubpages set
3947  break;
3948  }
3949  }
3950  $simUser = '';
3951  $simTime = '';
3952  if ((int)$access['fe_group'] === -2) {
3953  // -2 means "show at any login". We simulate first available fe_group.
3954  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
3955  ->getQueryBuilderForTable('fe_groups');
3956  $queryBuilder->getRestrictions()
3957  ->removeAll()
3958  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
3959  ->add(GeneralUtility::makeInstance(HiddenRestriction::class));
3960 
3961  $activeFeGroupId = $queryBuilder->select('uid')
3962  ->from('fe_groups')
3963  ->execute()
3964  ->fetchColumn();
3965 
3966  if ($activeFeGroupId) {
3967  $simUser = '&ADMCMD_simUser=' . $activeFeGroupId;
3968  }
3969  } elseif (!empty($access['fe_group'])) {
3970  $simUser = '&ADMCMD_simUser=' . $access['fe_group'];
3971  }
3972  if ($access['starttime'] > ‪$GLOBALS['EXEC_TIME']) {
3973  // simulate access time to ensure PageRepository will find the page and in turn PageRouter will generate
3974  // an URL for it
3975  $dateAspect = GeneralUtility::makeInstance(DateTimeAspect::class, new \DateTimeImmutable('@' . $access['starttime']));
3976  $context->‪setAspect('date', $dateAspect);
3977  $simTime = '&ADMCMD_simTime=' . $access['starttime'];
3978  }
3979  if ($access['endtime'] < ‪$GLOBALS['EXEC_TIME'] && $access['endtime'] !== 0) {
3980  // Set access time to page's endtime subtracted one second to ensure PageRepository will find the page and
3981  // in turn PageRouter will generate an URL for it
3982  $dateAspect = GeneralUtility::makeInstance(
3983  DateTimeAspect::class,
3984  new \DateTimeImmutable('@' . ($access['endtime'] - 1))
3985  );
3986  $context->‪setAspect('date', $dateAspect);
3987  $simTime = '&ADMCMD_simTime=' . ($access['endtime'] - 1);
3988  }
3989  return $simUser . $simTime;
3990  }
3991 
3999  public static function ‪getBackendScript($interface = '')
4000  {
4001  if (!$interface) {
4002  $interface = static::getBackendUserAuthentication()->uc['interfaceSetup'];
4003  }
4004  switch ($interface) {
4005  case 'frontend':
4006  $script = '../.';
4007  break;
4008  case 'backend':
4009  default:
4010  $script = (string)GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute('main');
4011  }
4012  return $script;
4013  }
4014 
4021  public static function ‪isTableWorkspaceEnabled($table)
4022  {
4023  return !empty(‪$GLOBALS['TCA'][$table]['ctrl']['versioningWS']);
4024  }
4025 
4033  public static function ‪getTcaFieldConfiguration($table, $field)
4034  {
4035  $configuration = [];
4036  if (isset(‪$GLOBALS['TCA'][$table]['columns'][$field]['config'])) {
4037  $configuration = ‪$GLOBALS['TCA'][$table]['columns'][$field]['config'];
4038  }
4039  return $configuration;
4040  }
4041 
4050  public static function ‪isWebMountRestrictionIgnored($table)
4051  {
4052  return !empty(‪$GLOBALS['TCA'][$table]['ctrl']['security']['ignoreWebMountRestriction']);
4053  }
4054 
4063  public static function ‪isRootLevelRestrictionIgnored($table)
4064  {
4065  return !empty(‪$GLOBALS['TCA'][$table]['ctrl']['security']['ignoreRootLevelRestriction']);
4066  }
4067 
4072  protected static function ‪getConnectionForTable($table)
4073  {
4074  return GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
4075  }
4076 
4081  protected static function ‪getQueryBuilderForTable($table)
4082  {
4083  return GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
4084  }
4085 
4089  protected static function ‪getLogger()
4090  {
4091  return GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
4092  }
4093 
4097  protected static function ‪getLanguageService()
4098  {
4099  return ‪$GLOBALS['LANG'];
4100  }
4101 
4105  protected static function ‪getBackendUserAuthentication()
4106  {
4107  return ‪$GLOBALS['BE_USER'] ?? null;
4108  }
4109 }
‪TYPO3\CMS\Core\Imaging\Icon\SIZE_SMALL
‪const SIZE_SMALL
Definition: Icon.php:30
‪TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction
Definition: HiddenRestriction.php:27
‪TYPO3\CMS\Core\Database\Query\QueryHelper\getDateTimeFormats
‪static array getDateTimeFormats()
Definition: QueryHelper.php:177
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTcaFieldConfiguration
‪static array getTcaFieldConfiguration($table, $field)
Definition: BackendUtility.php:4033
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGEPREVIEW
‪const CONTEXT_IMAGEPREVIEW
Definition: ProcessedFile.php:52
‪TYPO3\CMS\Backend\Utility\BackendUtility\getBackendScript
‪static string getBackendScript($interface='')
Definition: BackendUtility.php:3999
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:24
‪TYPO3\CMS\Backend\Utility\BackendUtility\isModuleSetInTBE_MODULES
‪static bool isModuleSetInTBE_MODULES($modName)
Definition: BackendUtility.php:3287
‪TYPO3\CMS\Core\Information\Typo3Information
Definition: Typo3Information.php:26
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:74
‪TYPO3\CMS\Core\Routing\RouterInterface
Definition: RouterInterface.php:28
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordLocalization
‪static mixed getRecordLocalization($table, $uid, $language, $andWhereClause='')
Definition: BackendUtility.php:285
‪TYPO3\CMS\Backend\Utility\BackendUtility\getBackendUserAuthentication
‪static BackendUserAuthentication null getBackendUserAuthentication()
Definition: BackendUtility.php:4105
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLinkToDataHandlerAction
‪static string getLinkToDataHandlerAction($parameters, $redirectUrl='')
Definition: BackendUtility.php:2539
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:180
‪TYPO3\CMS\Core\Versioning\VersionState\NEW_PLACEHOLDER
‪const NEW_PLACEHOLDER
Definition: VersionState.php:47
‪TYPO3\CMS\Backend\Utility\BackendUtility\resolveFileReferences
‪static TYPO3 CMS Core Resource FileReference[] null resolveFileReferences($tableName, $fieldName, $element, $workspaceId=null)
Definition: BackendUtility.php:1066
‪TYPO3\CMS\Backend\Utility\BackendUtility\softRefParserObj
‪static mixed softRefParserObj($spKey)
Definition: BackendUtility.php:3225
‪TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser
Definition: TypoScriptParser.php:37
‪TYPO3\CMS\Backend\Utility\BackendUtility\datetime
‪static string datetime($value)
Definition: BackendUtility.php:989
‪TYPO3\CMS\Core\Imaging\Icon
Definition: Icon.php:26
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTSCpidCached
‪static array getTSCpidCached($table, $uid, $pid)
Definition: BackendUtility.php:3184
‪TYPO3\CMS\Backend\Utility\BackendUtility\setUpdateSignal
‪static setUpdateSignal($set='', $params='')
Definition: BackendUtility.php:2798
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:372
‪TYPO3\CMS\Core\Database\RelationHandler
Definition: RelationHandler.php:35
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGECROPSCALEMASK
‪const CONTEXT_IMAGECROPSCALEMASK
Definition: ProcessedFile.php:58
‪TYPO3\CMS\Backend\Utility\BackendUtility\getCommonSelectFields
‪static string getCommonSelectFields($table, $prefix='', $fields=[])
Definition: BackendUtility.php:2136
‪TYPO3
‪TYPO3\CMS\Backend\Utility\BackendUtility\calcAge
‪static string calcAge($seconds, $labels='min|hrs|days|yrs|min|hour|day|year')
Definition: BackendUtility.php:1017
‪TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher
Definition: ConditionMatcher.php:30
‪if
‪if(PHP_SAPI !=='cli')
Definition: splitAcceptanceTests.php:33
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SHORTCUT
‪const DOKTYPE_SHORTCUT
Definition: PageRepository.php:105
‪TYPO3\CMS\Core\Configuration\Loader\PageTsConfigLoader
Definition: PageTsConfigLoader.php:39
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_LINK
‪const DOKTYPE_LINK
Definition: PageRepository.php:104
‪TYPO3\CMS\Core\Exception\SiteNotFoundException
Definition: SiteNotFoundException.php:26
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Backend\Utility\BackendUtility\getItemLabel
‪static string getItemLabel($table, $col)
Definition: BackendUtility.php:1521
‪TYPO3\CMS\Backend\Utility\BackendUtility\purgeComputedPropertiesFromRecord
‪static array< string, mixed > purgeComputedPropertiesFromRecord(array $record)
Definition: BackendUtility.php:172
‪TYPO3\CMS\Backend\Utility\BackendUtility\purgeComputedPropertyNames
‪static array purgeComputedPropertyNames(array $propertyNames)
Definition: BackendUtility.php:190
‪$parser
‪$parser
Definition: annotationChecker.php:108
‪TYPO3\CMS\Backend\Utility\BackendUtility\getThumbnailUrl
‪static string getThumbnailUrl(int $fileId, array $configuration)
Definition: BackendUtility.php:1225
‪TYPO3\CMS\Backend\Utility\BackendUtility\getNoRecordTitle
‪static string getNoRecordTitle($prep=false)
Definition: BackendUtility.php:1635
‪TYPO3\CMS\Core\Core\Environment\getCurrentScript
‪static string getCurrentScript()
Definition: Environment.php:220
‪TYPO3\CMS\Backend\Utility\BackendUtility\cshItem
‪static string cshItem($table, $field, $_='', $wrap='')
Definition: BackendUtility.php:2306
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordIconAltText
‪static string getRecordIconAltText($row, $table='pages')
Definition: BackendUtility.php:1357
‪TYPO3\CMS\Backend\Utility\BackendUtility\lockRecords
‪static lockRecords($table='', $uid=0, $pid=0)
Definition: BackendUtility.php:2967
‪TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException
Definition: FileDoesNotExistException.php:22
‪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:1137
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:33
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLiveVersionIdOfRecord
‪static int null getLiveVersionIdOfRecord($table, $uid)
Definition: BackendUtility.php:3765
‪TYPO3\CMS\Backend\Utility\BackendUtility\daysUntil
‪static int daysUntil($tstamp)
Definition: BackendUtility.php:966
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPageForRootline
‪static array getPageForRootline($uid, $clause, $workspaceOL, array $additionalFields=[])
Definition: BackendUtility.php:418
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:654
‪TYPO3\CMS\Core\Versioning\VersionState\DELETE_PLACEHOLDER
‪const DELETE_PLACEHOLDER
Definition: VersionState.php:55
‪TYPO3\CMS\Backend\Utility\BackendUtility\getUserNames
‪static array getUserNames($fields='username, usergroup, usergroup_cached_list, uid', $where='')
Definition: BackendUtility.php:818
‪TYPO3\CMS\Core\Utility\GeneralUtility\camelCaseToLowerCaseUnderscored
‪static string camelCaseToLowerCaseUnderscored($string)
Definition: GeneralUtility.php:914
‪TYPO3\CMS\Core\Utility\PathUtility\getCanonicalPath
‪static string getCanonicalPath($path)
Definition: PathUtility.php:307
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRuntimeCache
‪static FrontendInterface getRuntimeCache()
Definition: BackendUtility.php:3239
‪TYPO3\CMS\Backend\Utility\BackendUtility\BEgetRootLine
‪static array BEgetRootLine($uid, $clause='', $workspaceOL=false, array $additionalFields=[])
Definition: BackendUtility.php:343
‪TYPO3\CMS\Core\Versioning\VersionState\MOVE_POINTER
‪const MOVE_POINTER
Definition: VersionState.php:73
‪TYPO3\CMS\Backend\Utility\BackendUtility\isRootLevelRestrictionIgnored
‪static bool isRootLevelRestrictionIgnored($table)
Definition: BackendUtility.php:4063
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPreviewUrl
‪static string getPreviewUrl( $pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', &$switchFocus=true)
Definition: BackendUtility.php:2403
‪TYPO3\CMS\Backend\Utility\BackendUtility\helpText
‪static string helpText($table, $field)
Definition: BackendUtility.php:2227
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:53
‪TYPO3\CMS\Backend\Utility\BackendUtility\wrapInHelp
‪static string wrapInHelp($table, $field, $text='', array $overloadHelpText=[])
Definition: BackendUtility.php:2260
‪TYPO3\CMS\Backend\Utility\BackendUtility\getFuncMenu
‪static string getFuncMenu( $mainParams, $elementName, $currentValue, $menuItems, $script='', $addParams='')
Definition: BackendUtility.php:2599
‪TYPO3\CMS\Backend\Utility\BackendUtility\getWorkspaceWhereClause
‪static string getWorkspaceWhereClause($table, $workspaceId=null)
Definition: BackendUtility.php:3805
‪TYPO3\CMS\Core\Utility\PathUtility\basename
‪static string basename($path)
Definition: PathUtility.php:165
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:24
‪TYPO3\CMS\Backend\Utility\BackendUtility\isWebMountRestrictionIgnored
‪static bool isWebMountRestrictionIgnored($table)
Definition: BackendUtility.php:4050
‪TYPO3\CMS\Core\Http\Uri
Definition: Uri.php:29
‪TYPO3\CMS\Core\Context\Context\setAspect
‪setAspect(string $name, AspectInterface $aspect)
Definition: Context.php:162
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:52
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:43
‪TYPO3\CMS\Backend\Utility\BackendUtility\isTableWorkspaceEnabled
‪static bool isTableWorkspaceEnabled($table)
Definition: BackendUtility.php:4021
‪TYPO3\CMS\Backend\Utility\BackendUtility\translationCount
‪static string translationCount($table, $ref, $msg='')
Definition: BackendUtility.php:3361
‪TYPO3\CMS\Backend\Utility\BackendUtility\wrapClickMenuOnIcon
‪static string wrapClickMenuOnIcon( $content, $table, $uid=0, $context='', $_addParams='', $_enDisItems='', $returnTagParameters=false)
Definition: BackendUtility.php:2510
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_MOUNTPOINT
‪const DOKTYPE_MOUNTPOINT
Definition: PageRepository.php:107
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:186
‪TYPO3\CMS\Backend\Utility\BackendUtility\fixVersioningPid
‪static fixVersioningPid($table, &$rr, $ignoreWorkspaceMatch=false)
Definition: BackendUtility.php:3511
‪TYPO3\CMS\Backend\Utility
Definition: BackendUtility.php:16
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordTitlePrep
‪static string getRecordTitlePrep($title, $titleLength=0)
Definition: BackendUtility.php:1614
‪TYPO3\CMS\Backend\Utility\BackendUtility\ADMCMD_previewCmds
‪static string ADMCMD_previewCmds($pageInfo, Context $context)
Definition: BackendUtility.php:3922
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLogger
‪static LoggerInterface getLogger()
Definition: BackendUtility.php:4089
‪TYPO3\CMS\Backend\Utility\BackendUtility\versioningPlaceholderClause
‪static string versioningPlaceholderClause($table)
Definition: BackendUtility.php:3788
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:38
‪TYPO3\CMS\Backend\Utility\BackendUtility\getDropdownMenu
‪static string getDropdownMenu( $mainParams, $elementName, $currentValue, $menuItems, $script='', $addParams='')
Definition: BackendUtility.php:2653
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:41
‪TYPO3\CMS\Core\Utility\HttpUtility\buildQueryString
‪static string buildQueryString(array $parameters, string $prependCharacter='', bool $skipEmptyParameters=false)
Definition: HttpUtility.php:163
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLiveVersionOfRecord
‪static array null getLiveVersionOfRecord($table, $uid, $fields=' *')
Definition: BackendUtility.php:3748
‪TYPO3\CMS\Backend\Utility\BackendUtility\getGroupNames
‪static array getGroupNames($fields='title, uid', $where='')
Definition: BackendUtility.php:836
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLabelFromItemListMerged
‪static string getLabelFromItemListMerged($pageId, $table, $column, $key)
Definition: BackendUtility.php:1434
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPagesTSconfig
‪static array getPagesTSconfig($id)
Definition: BackendUtility.php:698
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordToolTip
‪static string getRecordToolTip(array $row, $table='pages')
Definition: BackendUtility.php:1339
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordsSortedByTitle
‪static array getRecordsSortedByTitle(array $fields, $table, $titleField, $where='')
Definition: BackendUtility.php:857
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordTitle
‪static string getRecordTitle($table, $row, $prep=false, $forceResult=true)
Definition: BackendUtility.php:1541
‪TYPO3\CMS\Backend\Utility\BackendUtility\getModuleData
‪static array getModuleData( $MOD_MENU, $CHANGED_SETTINGS, $modName, $type='', $dontValidateList='', $setDefaultList='')
Definition: BackendUtility.php:2893
‪TYPO3\CMS\Backend\Utility\BackendUtility\getFuncCheck
‪static string getFuncCheck( $mainParams, $elementName, $currentValue, $script='', $addParams='', $tagParams='')
Definition: BackendUtility.php:2709
‪TYPO3\CMS\Backend\Utility\BackendUtility\getMovePlaceholder
‪static array bool getMovePlaceholder($table, $uid, $fields=' *', $workspace=null)
Definition: BackendUtility.php:3851
‪TYPO3\CMS\Backend\Utility\BackendUtility\titleAttribForPages
‪static string titleAttribForPages($row, $perms_clause='', $includeAttrib=true)
Definition: BackendUtility.php:1244
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:35
‪TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser\checkIncludeLines_array
‪static array checkIncludeLines_array(array $array)
Definition: TypoScriptParser.php:1190
‪TYPO3\CMS\Backend\Utility\BackendUtility\getViewDomain
‪static string getViewDomain($pageId, $rootLine=null)
Definition: BackendUtility.php:2561
‪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:2100
‪TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException
Definition: InvalidRouteArgumentsException.php:26
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Core\Configuration\Parser\PageTsConfigParser
Definition: PageTsConfigParser.php:33
‪TYPO3\CMS\Backend\Utility\BackendUtility\editOnClick
‪static string editOnClick($params, $_='', $requestUri='')
Definition: BackendUtility.php:2334
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:33
‪TYPO3\CMS\Backend\Utility\BackendUtility\BEenableFields
‪static string BEenableFields($table, $inv=false)
Definition: BackendUtility.php:225
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:75
‪TYPO3\CMS\Backend\Utility\BackendUtility\getWorkspaceVersionOfRecord
‪static array bool getWorkspaceVersionOfRecord($workspace, $table, $uid, $fields=' *')
Definition: BackendUtility.php:3705
‪TYPO3\CMS\Backend\Utility\BackendUtility\explodeSoftRefParserList
‪static array bool explodeSoftRefParserList($parserList)
Definition: BackendUtility.php:3252
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordWSOL
‪static array getRecordWSOL( $table, $uid, $fields=' *', $where='', $useDeleteClause=true, $unsetMovePointers=false)
Definition: BackendUtility.php:139
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:95
‪TYPO3\CMS\Core\Versioning\VersionState
Definition: VersionState.php:24
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static string[] trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:1059
‪TYPO3\CMS\Backend\Utility\BackendUtility\getFuncInput
‪static string getFuncInput( $mainParams, $elementName, $currentValue, $size=10, $script='', $addParams='')
Definition: BackendUtility.php:2749
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:44
‪TYPO3\CMS\Backend\Utility\BackendUtility\readPageAccess
‪static array false readPageAccess($id, $perms_clause)
Definition: BackendUtility.php:597
‪$output
‪$output
Definition: annotationChecker.php:119
‪TYPO3\CMS\Backend\Utility\BackendUtility\dateTimeAge
‪static string dateTimeAge($tstamp, $prefix=1, $date='')
Definition: BackendUtility.php:1047
‪TYPO3\CMS\Backend\Utility\BackendUtility\blindGroupNames
‪static array blindGroupNames($groups, $groupArray, $excludeBlindedFlag=false)
Definition: BackendUtility.php:936
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪TYPO3\CMS\Core\Versioning\VersionState\NEW_PLACEHOLDER_VERSION
‪const NEW_PLACEHOLDER_VERSION
Definition: VersionState.php:33
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Backend\Utility\BackendUtility\viewOnClick
‪static string viewOnClick( $pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=true)
Definition: BackendUtility.php:2359
‪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:1664
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLabelsFromItemsList
‪static string getLabelsFromItemsList($table, $column, $keyList, array $columnTsConfig=[])
Definition: BackendUtility.php:1472
‪TYPO3\CMS\Backend\Utility\BackendUtility\time
‪static string time($value, $withSeconds=true)
Definition: BackendUtility.php:1005
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTSCpid
‪static array getTSCpid($table, $uid, $pid)
Definition: BackendUtility.php:3208
‪TYPO3\CMS\Core\Configuration\Event\ModifyLoadedPageTsConfigEvent
Definition: ModifyLoadedPageTsConfigEvent.php:24
‪TYPO3\CMS\Backend\Utility\BackendUtility\isTableLocalizable
‪static bool isTableLocalizable($table)
Definition: BackendUtility.php:578
‪TYPO3\CMS\Core\Database\Query\QueryHelper\stripLogicalOperatorPrefix
‪static string stripLogicalOperatorPrefix(string $constraint)
Definition: QueryHelper.php:165
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTSconfig_pidValue
‪static int getTSconfig_pidValue($table, $uid, $pid)
Definition: BackendUtility.php:3137
‪TYPO3\CMS\Core\Versioning\VersionState\DEFAULT_STATE
‪const DEFAULT_STATE
Definition: VersionState.php:39
‪TYPO3\CMS\Backend\Utility\BackendUtility\buildScriptUrl
‪static string buildScriptUrl($mainParams, $addParams, $script='')
Definition: BackendUtility.php:2770
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪$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:3586
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\SHORTCUT_MODE_NONE
‪const SHORTCUT_MODE_NONE
Definition: PageRepository.php:115
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:30
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRawPagesTSconfig
‪static array getRawPagesTSconfig($id, array $rootLine=null)
Definition: BackendUtility.php:760
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLabelFromItemlist
‪static string getLabelFromItemlist($table, $col, $key)
Definition: BackendUtility.php:1410
‪TYPO3\CMS\Backend\Utility\BackendUtility\selectVersionsOfRecord
‪static array null selectVersionsOfRecord( $table, $uid, $fields=' *', $workspace=0, $includeDeletedRecords=false, $row=null)
Definition: BackendUtility.php:3416
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static int[] intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:988
‪TYPO3\CMS\Backend\Utility\BackendUtility\getConnectionForTable
‪static Connection getConnectionForTable($table)
Definition: BackendUtility.php:4072
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection
Definition: CropVariantCollection.php:23
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:22
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\extPath
‪static string extPath($key, $script='')
Definition: ExtensionManagementUtility.php:127
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:24
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTCEFORM_TSconfig
‪static array getTCEFORM_TSconfig($table, $row)
Definition: BackendUtility.php:3096
‪TYPO3\CMS\Core\Domain\Repository\PageRepository
Definition: PageRepository.php:52
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\ArrayUtility\sortArraysByKey
‪static array sortArraysByKey(array $arrays, $key, $ascending=true)
Definition: ArrayUtility.php:374
‪TYPO3\CMS\Core\Routing\RouterInterface\ABSOLUTE_URL
‪const ABSOLUTE_URL
Definition: RouterInterface.php:32
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordPath
‪static mixed getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit=0)
Definition: BackendUtility.php:546
‪TYPO3\CMS\Backend\Utility\BackendUtility\movePlhOL
‪static bool movePlhOL($table, &$row)
Definition: BackendUtility.php:3669
‪TYPO3\CMS\Backend\Utility\BackendUtility\getQueryBuilderForTable
‪static QueryBuilder getQueryBuilderForTable($table)
Definition: BackendUtility.php:4081
‪TYPO3\CMS\Backend\Utility\BackendUtility\blindUserNames
‪static array blindUserNames($usernames, $groupArray, $excludeBlindedFlag=false)
Definition: BackendUtility.php:901
‪TYPO3\CMS\Backend\Utility\BackendUtility\getUpdateSignalCode
‪static string getUpdateSignalCode()
Definition: BackendUtility.php:2824
‪TYPO3\CMS\Backend\Utility\BackendUtility\helpTextArray
‪static array helpTextArray($table, $field)
Definition: BackendUtility.php:2188
‪TYPO3\CMS\Backend\Utility\BackendUtility\date
‪static string date($tstamp)
Definition: BackendUtility.php:978
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection\create
‪static CropVariantCollection create(string $jsonString, array $tcaConfig=[])
Definition: CropVariantCollection.php:42
‪TYPO3\CMS\Backend\Utility\BackendUtility\openPageTree
‪static openPageTree($pid, $clearExpansion)
Definition: BackendUtility.php:505
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key)
Definition: ExtensionManagementUtility.php:114
‪TYPO3\CMS\Core\Context\DateTimeAspect
Definition: DateTimeAspect.php:35
‪TYPO3\CMS\Backend\Utility\BackendUtility\wsMapId
‪static int wsMapId($table, $uid)
Definition: BackendUtility.php:3827
‪TYPO3\CMS\Backend\Utility\BackendUtility\splitTable_Uid
‪static array splitTable_Uid($str)
Definition: BackendUtility.php:208
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLanguageService
‪static LanguageService getLanguageService()
Definition: BackendUtility.php:4097
‪TYPO3\CMS\Backend\Utility\BackendUtility\TYPO3_copyRightNotice
‪static string TYPO3_copyRightNotice()
Definition: BackendUtility.php:3907
‪TYPO3\CMS\Backend\Utility\BackendUtility\referenceCount
‪static string int referenceCount($table, $ref, $msg='', $count=null)
Definition: BackendUtility.php:3311
‪TYPO3\CMS\Backend\Utility\BackendUtility\isRecordLocked
‪static array bool isRecordLocked($table, $uid)
Definition: BackendUtility.php:3011
‪TYPO3\CMS\Core\Versioning\VersionState\MOVE_PLACEHOLDER
‪const MOVE_PLACEHOLDER
Definition: VersionState.php:72
‪TYPO3\CMS\Core\Imaging\ImageDimension
Definition: ImageDimension.php:31
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:39
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTCAtypeValue
‪static string getTCAtypeValue($table, $row)
Definition: BackendUtility.php:636