TYPO3 CMS  TYPO3_6-2
BackendUtility.php
Go to the documentation of this file.
1 <?php
3 
31 
43 
50  static protected $tcaTableTypeConfigurationCache = array();
51 
52  /*******************************************
53  *
54  * SQL-related, selecting records, searching
55  *
56  *******************************************/
71  static public function deleteClause($table, $tableAlias = '') {
72  if ($GLOBALS['TCA'][$table]['ctrl']['delete']) {
73  return ' AND ' . ($tableAlias ?: $table) . '.' . $GLOBALS['TCA'][$table]['ctrl']['delete'] . '=0';
74  } else {
75  return '';
76  }
77  }
78 
93  static public function getRecord($table, $uid, $fields = '*', $where = '', $useDeleteClause = TRUE) {
94  // Ensure we have a valid uid (not 0 and not NEWxxxx) and a valid TCA
95  if ((int)$uid && !empty($GLOBALS['TCA'][$table])) {
97  $db = $GLOBALS['TYPO3_DB'];
98  $where = 'uid=' . (int)$uid . ($useDeleteClause ? self::deleteClause($table) : '') . $where;
99  $row = $db->exec_SELECTgetSingleRow($fields, $table, $where);
100  if ($row) {
101  return $row;
102  }
103  }
104  return NULL;
105  }
106 
118  static public function getRecordWSOL($table, $uid, $fields = '*', $where = '', $useDeleteClause = TRUE, $unsetMovePointers = FALSE) {
119  if ($fields !== '*') {
120  $internalFields = GeneralUtility::uniqueList($fields . ',uid,pid');
121  $row = self::getRecord($table, $uid, $internalFields, $where, $useDeleteClause);
122  self::workspaceOL($table, $row, -99, $unsetMovePointers);
123  if (is_array($row)) {
124  foreach ($row as $key => $_) {
125  if (!GeneralUtility::inList($fields, $key) && $key[0] !== '_') {
126  unset($row[$key]);
127  }
128  }
129  }
130  } else {
131  $row = self::getRecord($table, $uid, $fields, $where, $useDeleteClause);
132  self::workspaceOL($table, $row, -99, $unsetMovePointers);
133  }
134  return $row;
135  }
136 
149  static public function getRecordRaw($table, $where = '', $fields = '*') {
150  $row = FALSE;
151  if (FALSE !== ($res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $table, $where, '', '', '1'))) {
152  $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
153  $GLOBALS['TYPO3_DB']->sql_free_result($res);
154  }
155  return $row;
156  }
157 
173  static public function getRecordsByField($theTable, $theField, $theValue, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '', $useDeleteClause = TRUE) {
174  if (is_array($GLOBALS['TCA'][$theTable])) {
175  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
176  '*',
177  $theTable,
178  $theField . '=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($theValue, $theTable) .
179  ($useDeleteClause ? self::deleteClause($theTable) . ' ' : '') .
180  self::versioningPlaceholderClause($theTable) . ' ' .
181  $whereClause,
182  $groupBy,
183  $orderBy,
184  $limit
185  );
186  $rows = array();
187  while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
188  $rows[] = $row;
189  }
190  $GLOBALS['TYPO3_DB']->sql_free_result($res);
191  if (count($rows)) {
192  return $rows;
193  }
194  }
195  }
196 
204  static public function splitTable_Uid($str) {
205  list($uid, $table) = explode('_', strrev($str), 2);
206  return array(strrev($table), strrev($uid));
207  }
208 
218  static public function getSQLselectableList($in_list, $tablename, $default_tablename) {
219  $list = array();
220  if ((string) trim($in_list) != '') {
221  $tempItemArray = explode(',', trim($in_list));
222  foreach ($tempItemArray as $key => $val) {
223  $val = strrev($val);
224  $parts = explode('_', $val, 2);
225  if ((string) trim($parts[0]) != '') {
226  $theID = (int)strrev($parts[0]);
227  $theTable = trim($parts[1]) ? strrev(trim($parts[1])) : $default_tablename;
228  if ($theTable == $tablename) {
229  $list[] = $theID;
230  }
231  }
232  }
233  }
234  return implode(',', $list);
235  }
236 
247  static public function BEenableFields($table, $inv = 0) {
248  $ctrl = $GLOBALS['TCA'][$table]['ctrl'];
249  $query = array();
250  $invQuery = array();
251  if (is_array($ctrl)) {
252  if (is_array($ctrl['enablecolumns'])) {
253  if ($ctrl['enablecolumns']['disabled']) {
254  $field = $table . '.' . $ctrl['enablecolumns']['disabled'];
255  $query[] = $field . '=0';
256  $invQuery[] = $field . '<>0';
257  }
258  if ($ctrl['enablecolumns']['starttime']) {
259  $field = $table . '.' . $ctrl['enablecolumns']['starttime'];
260  $query[] = '(' . $field . '<=' . $GLOBALS['SIM_ACCESS_TIME'] . ')';
261  $invQuery[] = '(' . $field . '<>0 AND ' . $field . '>' . $GLOBALS['SIM_ACCESS_TIME'] . ')';
262  }
263  if ($ctrl['enablecolumns']['endtime']) {
264  $field = $table . '.' . $ctrl['enablecolumns']['endtime'];
265  $query[] = '(' . $field . '=0 OR ' . $field . '>' . $GLOBALS['SIM_ACCESS_TIME'] . ')';
266  $invQuery[] = '(' . $field . '<>0 AND ' . $field . '<=' . $GLOBALS['SIM_ACCESS_TIME'] . ')';
267  }
268  }
269  }
270  $outQ = $inv ? '(' . implode(' OR ', $invQuery) . ')' : implode(' AND ', $query);
271  return $outQ ? ' AND ' . $outQ : '';
272  }
273 
283  static public function getRecordLocalization($table, $uid, $language, $andWhereClause = '') {
284  $recordLocalization = FALSE;
285  if (self::isTableLocalizable($table)) {
286  $tcaCtrl = $GLOBALS['TCA'][$table]['ctrl'];
287  $recordLocalization = self::getRecordsByField($table, $tcaCtrl['transOrigPointerField'], $uid, 'AND ' . $tcaCtrl['languageField'] . '=' . (int)$language . ($andWhereClause ? ' ' . $andWhereClause : ''), '', '', '1');
288  }
289  return $recordLocalization;
290  }
291 
292  /*******************************************
293  *
294  * Page tree, TCA related
295  *
296  *******************************************/
307  static public function BEgetRootLine($uid, $clause = '', $workspaceOL = FALSE) {
308  static $BEgetRootLine_cache = array();
309  $output = array();
310  $pid = $uid;
311  $ident = $pid . '-' . $clause . '-' . $workspaceOL;
312  if (is_array($BEgetRootLine_cache[$ident])) {
313  $output = $BEgetRootLine_cache[$ident];
314  } else {
315  $loopCheck = 100;
316  $theRowArray = array();
317  while ($uid != 0 && $loopCheck) {
318  $loopCheck--;
319  $row = self::getPageForRootline($uid, $clause, $workspaceOL);
320  if (is_array($row)) {
321  $uid = $row['pid'];
322  $theRowArray[] = $row;
323  } else {
324  break;
325  }
326  }
327  if ($uid == 0) {
328  $theRowArray[] = array('uid' => 0, 'title' => '');
329  }
330  $c = count($theRowArray);
331  foreach ($theRowArray as $val) {
332  $c--;
333  $output[$c] = array(
334  'uid' => $val['uid'],
335  'pid' => $val['pid'],
336  'title' => $val['title'],
337  'TSconfig' => $val['TSconfig'],
338  'is_siteroot' => $val['is_siteroot'],
339  'storage_pid' => $val['storage_pid'],
340  't3ver_oid' => $val['t3ver_oid'],
341  't3ver_wsid' => $val['t3ver_wsid'],
342  't3ver_state' => $val['t3ver_state'],
343  't3ver_stage' => $val['t3ver_stage'],
344  'backend_layout_next_level' => $val['backend_layout_next_level']
345  );
346  if (isset($val['_ORIG_pid'])) {
347  $output[$c]['_ORIG_pid'] = $val['_ORIG_pid'];
348  }
349  }
350  $BEgetRootLine_cache[$ident] = $output;
351  }
352  return $output;
353  }
354 
364  static protected function getPageForRootline($uid, $clause, $workspaceOL) {
365  static $getPageForRootline_cache = array();
366  $ident = $uid . '-' . $clause . '-' . $workspaceOL;
367  if (is_array($getPageForRootline_cache[$ident])) {
368  $row = $getPageForRootline_cache[$ident];
369  } else {
370  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('pid,uid,title,TSconfig,is_siteroot,storage_pid,t3ver_oid,t3ver_wsid,t3ver_state,t3ver_stage,backend_layout_next_level', 'pages', 'uid=' . (int)$uid . ' ' . self::deleteClause('pages') . ' ' . $clause);
371  $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
372  if ($row) {
373  $newLocation = FALSE;
374  if ($workspaceOL) {
375  self::workspaceOL('pages', $row);
376  $newLocation = self::getMovePlaceholder('pages', $row['uid'], 'pid');
377  }
378  if (is_array($row)) {
379  if ($newLocation !== FALSE) {
380  $row['pid'] = $newLocation['pid'];
381  } else {
382  self::fixVersioningPid('pages', $row);
383  }
384  $getPageForRootline_cache[$ident] = $row;
385  }
386  }
387  $GLOBALS['TYPO3_DB']->sql_free_result($res);
388  }
389  return $row;
390  }
391 
399  static public function openPageTree($pid, $clearExpansion) {
400  // Get current expansion data:
401  if ($clearExpansion) {
402  $expandedPages = array();
403  } else {
404  $expandedPages = unserialize($GLOBALS['BE_USER']->uc['browseTrees']['browsePages']);
405  }
406  // Get rootline:
407  $rL = self::BEgetRootLine($pid);
408  // First, find out what mount index to use (if more than one DB mount exists):
409  $mountIndex = 0;
410  $mountKeys = array_flip($GLOBALS['BE_USER']->returnWebmounts());
411  foreach ($rL as $rLDat) {
412  if (isset($mountKeys[$rLDat['uid']])) {
413  $mountIndex = $mountKeys[$rLDat['uid']];
414  break;
415  }
416  }
417  // Traverse rootline and open paths:
418  foreach ($rL as $rLDat) {
419  $expandedPages[$mountIndex][$rLDat['uid']] = 1;
420  }
421  // Write back:
422  $GLOBALS['BE_USER']->uc['browseTrees']['browsePages'] = serialize($expandedPages);
423  $GLOBALS['BE_USER']->writeUC();
424  }
425 
437  static public function getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit = 0) {
438  if (!$titleLimit) {
439  $titleLimit = 1000;
440  }
441  $loopCheck = 100;
442  $output = ($fullOutput = '/');
443  $clause = trim($clause);
444  if ($clause !== '' && substr($clause, 0, 3) !== 'AND') {
445  $clause = 'AND ' . $clause;
446  }
447  $data = self::BEgetRootLine($uid, $clause);
448  foreach ($data as $record) {
449  if ($record['uid'] === 0) {
450  continue;
451  }
452  $output = '/' . GeneralUtility::fixed_lgd_cs(strip_tags($record['title']), $titleLimit) . $output;
453  if ($fullTitleLimit) {
454  $fullOutput = '/' . GeneralUtility::fixed_lgd_cs(strip_tags($record['title']), $fullTitleLimit) . $fullOutput;
455  }
456  }
457  if ($fullTitleLimit) {
458  return array($output, $fullOutput);
459  } else {
460  return $output;
461  }
462  }
463 
470  static public function getExcludeFields() {
471  $finalExcludeArray = array();
472 
473  // Fetch translations for table names
474  $tableToTranslation = array();
475  // All TCA keys
476  foreach ($GLOBALS['TCA'] as $table => $conf) {
477  $tableToTranslation[$table] = $GLOBALS['LANG']->sl($conf['ctrl']['title']);
478  }
479  // Sort by translations
480  asort($tableToTranslation);
481  foreach ($tableToTranslation as $table => $translatedTable) {
482  $excludeArrayTable = array();
483 
484  // All field names configured and not restricted to admins
485  if (is_array($GLOBALS['TCA'][$table]['columns'])
486  && empty($GLOBALS['TCA'][$table]['ctrl']['adminOnly'])
487  && (empty($GLOBALS['TCA'][$table]['ctrl']['rootLevel']) || !empty($GLOBALS['TCA'][$table]['ctrl']['security']['ignoreRootLevelRestriction']))
488  ) {
489  foreach ($GLOBALS['TCA'][$table]['columns'] as $field => $_) {
490  if ($GLOBALS['TCA'][$table]['columns'][$field]['exclude']) {
491  // Get human readable names of fields
492  $translatedField = $GLOBALS['LANG']->sl($GLOBALS['TCA'][$table]['columns'][$field]['label']);
493  // Add entry
494  $excludeArrayTable[] = array($translatedTable . ': ' . $translatedField, $table . ':' . $field);
495  }
496  }
497  }
498  // All FlexForm fields
499  $flexFormArray = static::getRegisteredFlexForms($table);
500  foreach ($flexFormArray as $tableField => $flexForms) {
501  // Prefix for field label, e.g. "Plugin Options:"
502  $labelPrefix = '';
503  if (!empty($GLOBALS['TCA'][$table]['columns'][$tableField]['label'])) {
504  $labelPrefix = $GLOBALS['LANG']->sl($GLOBALS['TCA'][$table]['columns'][$tableField]['label']);
505  }
506  // Get all sheets and title
507  foreach ($flexForms as $extIdent => $extConf) {
508  $extTitle = $GLOBALS['LANG']->sl($extConf['title']);
509  // Get all fields in sheet
510  foreach ($extConf['ds']['sheets'] as $sheetName => $sheet) {
511  if (empty($sheet['ROOT']['el']) || !is_array($sheet['ROOT']['el'])) {
512  continue;
513  }
514  foreach ($sheet['ROOT']['el'] as $fieldName => $field) {
515  // Use only excludeable fields
516  if (empty($field['TCEforms']['exclude'])) {
517  continue;
518  }
519  $fieldLabel = !empty($field['TCEforms']['label']) ? $GLOBALS['LANG']->sl($field['TCEforms']['label']) : $fieldName;
520  $fieldIdent = $table . ':' . $tableField . ';' . $extIdent . ';' . $sheetName . ';' . $fieldName;
521  $excludeArrayTable[] = array(trim(($labelPrefix . ' ' . $extTitle), ': ') . ': ' . $fieldLabel, $fieldIdent);
522  }
523  }
524  }
525  }
526  // Sort fields by the translated value
527  if (count($excludeArrayTable) > 0) {
528  usort($excludeArrayTable, array('TYPO3\\CMS\\Backend\\Form\\FlexFormsHelper', 'compareArraysByFirstValue'));
529  $finalExcludeArray = array_merge($finalExcludeArray, $excludeArrayTable);
530  }
531  }
532 
533  return $finalExcludeArray;
534  }
535 
542  static public function getExplicitAuthFieldValues() {
543  // Initialize:
544  $adLabel = array(
545  'ALLOW' => $GLOBALS['LANG']->sl('LLL:EXT:lang/locallang_core.xlf:labels.allow'),
546  'DENY' => $GLOBALS['LANG']->sl('LLL:EXT:lang/locallang_core.xlf:labels.deny')
547  );
548  // All TCA keys:
549  $allowDenyOptions = array();
550  foreach ($GLOBALS['TCA'] as $table => $_) {
551  // All field names configured:
552  if (is_array($GLOBALS['TCA'][$table]['columns'])) {
553  foreach ($GLOBALS['TCA'][$table]['columns'] as $field => $_) {
554  $fCfg = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
555  if ($fCfg['type'] == 'select' && $fCfg['authMode']) {
556  // Check for items:
557  if (is_array($fCfg['items'])) {
558  // Get Human Readable names of fields and table:
559  $allowDenyOptions[$table . ':' . $field]['tableFieldLabel'] = $GLOBALS['LANG']->sl($GLOBALS['TCA'][$table]['ctrl']['title']) . ': ' . $GLOBALS['LANG']->sl($GLOBALS['TCA'][$table]['columns'][$field]['label']);
560  // Check for items:
561  foreach ($fCfg['items'] as $iVal) {
562  // Values '' is not controlled by this setting.
563  if ((string)$iVal[1] !== '') {
564  // Find iMode
565  $iMode = '';
566  switch ((string) $fCfg['authMode']) {
567  case 'explicitAllow':
568  $iMode = 'ALLOW';
569  break;
570  case 'explicitDeny':
571  $iMode = 'DENY';
572  break;
573  case 'individual':
574  if ($iVal[4] === 'EXPL_ALLOW') {
575  $iMode = 'ALLOW';
576  } elseif ($iVal[4] === 'EXPL_DENY') {
577  $iMode = 'DENY';
578  }
579  break;
580  }
581  // Set iMode
582  if ($iMode) {
583  $allowDenyOptions[$table . ':' . $field]['items'][$iVal[1]] = array($iMode, $GLOBALS['LANG']->sl($iVal[0]), $adLabel[$iMode]);
584  }
585  }
586  }
587  }
588  }
589  }
590  }
591  }
592  return $allowDenyOptions;
593  }
594 
605  static public function getSystemLanguages() {
606  $languages = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Configuration\\TranslationConfigurationProvider')->getSystemLanguages();
607  $sysLanguages = array();
608  foreach ($languages as $language) {
609  if ($language['uid'] !== -1) {
610  $sysLanguages[] = array(
611  0 => htmlspecialchars($language['title']) . ' [' . $language['uid'] . ']',
612  1 => $language['uid'],
613  2 => $language['flagIcon']
614  );
615  }
616  }
617  return $sysLanguages;
618  }
619 
627  static public function getOriginalTranslationTable($table) {
628  if (!empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'])) {
629  $table = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'];
630  }
631 
632  return $table;
633  }
634 
641  static public function isTableLocalizable($table) {
642  $isLocalizable = FALSE;
643  if (isset($GLOBALS['TCA'][$table]['ctrl']) && is_array($GLOBALS['TCA'][$table]['ctrl'])) {
644  $tcaCtrl = $GLOBALS['TCA'][$table]['ctrl'];
645  $isLocalizable = isset($tcaCtrl['languageField']) && $tcaCtrl['languageField'] && isset($tcaCtrl['transOrigPointerField']) && $tcaCtrl['transOrigPointerField'];
646  }
647  return $isLocalizable;
648  }
649 
659  static public function getInlineLocalizationMode($table, $fieldOrConfig) {
660  $localizationMode = FALSE;
661  if (is_array($fieldOrConfig) && count($fieldOrConfig)) {
662  $config = $fieldOrConfig;
663  } elseif (is_string($fieldOrConfig) && isset($GLOBALS['TCA'][$table]['columns'][$fieldOrConfig]['config'])) {
664  $config = $GLOBALS['TCA'][$table]['columns'][$fieldOrConfig]['config'];
665  }
666  if (is_array($config) && isset($config['type']) && $config['type'] == 'inline' && self::isTableLocalizable($table)) {
667  $localizationMode = isset($config['behaviour']['localizationMode']) && $config['behaviour']['localizationMode'] ? $config['behaviour']['localizationMode'] : 'select';
668  // The mode 'select' is not possible when child table is not localizable at all:
669  if ($localizationMode == 'select' && !self::isTableLocalizable($config['foreign_table'])) {
670  $localizationMode = FALSE;
671  }
672  }
673  return $localizationMode;
674  }
675 
685  static public function readPageAccess($id, $perms_clause) {
686  if ((string) $id != '') {
687  $id = (int)$id;
688  if (!$id) {
689  if ($GLOBALS['BE_USER']->isAdmin()) {
690  $path = '/';
691  $pageinfo['_thePath'] = $path;
692  return $pageinfo;
693  }
694  } else {
695  $pageinfo = self::getRecord('pages', $id, '*', $perms_clause ? ' AND ' . $perms_clause : '');
696  if ($pageinfo['uid'] && $GLOBALS['BE_USER']->isInWebMount($id, $perms_clause)) {
697  self::workspaceOL('pages', $pageinfo);
698  if (is_array($pageinfo)) {
699  self::fixVersioningPid('pages', $pageinfo);
700  list($pageinfo['_thePath'], $pageinfo['_thePathFull']) = self::getRecordPath((int)$pageinfo['uid'], $perms_clause, 15, 1000);
701  return $pageinfo;
702  }
703  }
704  }
705  }
706  return FALSE;
707  }
708 
717  static public function getTCAtypes($table, $rec, $useFieldNameAsKey = 0) {
718  if ($GLOBALS['TCA'][$table]) {
719  // Get type value:
720  $fieldValue = self::getTCAtypeValue($table, $rec);
721  $cacheIdentifier = $table . '-type-' . $fieldValue . '-fnk-' . $useFieldNameAsKey;
722 
723  // Fetch from first-level-cache if available
724  if (isset(self::$tcaTableTypeConfigurationCache[$cacheIdentifier])) {
725  return self::$tcaTableTypeConfigurationCache[$cacheIdentifier];
726  }
727 
728  // Get typesConf
729  $typesConf = $GLOBALS['TCA'][$table]['types'][$fieldValue];
730  // Get fields list and traverse it
731  $fieldList = explode(',', $typesConf['showitem']);
732 
733  // Add subtype fields e.g. for a valid RTE transformation
734  // The RTE runs the DB -> RTE transformation only, if the RTE field is part of the getTCAtypes array
735  if (isset($typesConf['subtype_value_field'])) {
736  $subType = $rec[$typesConf['subtype_value_field']];
737  if (isset($typesConf['subtypes_addlist'][$subType])) {
738  $subFields = GeneralUtility::trimExplode(',', $typesConf['subtypes_addlist'][$subType], TRUE);
739  $fieldList = array_merge($fieldList, $subFields);
740  }
741  }
742 
743  $altFieldList = array();
744  // Traverse fields in types config and parse the configuration into a nice array:
745  foreach ($fieldList as $k => $v) {
746  list($pFieldName, $pAltTitle, $pPalette, $pSpec) = GeneralUtility::trimExplode(';', $v);
747  $defaultExtras = is_array($GLOBALS['TCA'][$table]['columns'][$pFieldName]) ? $GLOBALS['TCA'][$table]['columns'][$pFieldName]['defaultExtras'] : '';
748  $specConfParts = self::getSpecConfParts($pSpec, $defaultExtras);
749  $fieldList[$k] = array(
750  'field' => $pFieldName,
751  'title' => $pAltTitle,
752  'palette' => $pPalette,
753  'spec' => $specConfParts,
754  'origString' => $v
755  );
756  if ($useFieldNameAsKey) {
757  $altFieldList[$fieldList[$k]['field']] = $fieldList[$k];
758  }
759  }
760  if ($useFieldNameAsKey) {
761  $fieldList = $altFieldList;
762  }
763 
764  // Add to first-level-cache
765  self::$tcaTableTypeConfigurationCache[$cacheIdentifier] = $fieldList;
766 
767  // Return array:
768  return $fieldList;
769  }
770  }
771 
788  static public function getTCAtypeValue($table, $row) {
789  $typeNum = 0;
790  if ($GLOBALS['TCA'][$table]) {
791  $field = $GLOBALS['TCA'][$table]['ctrl']['type'];
792  if (strpos($field, ':') !== FALSE) {
793  list($pointerField, $foreignTableTypeField) = explode(':', $field);
794  // Get field value from database if field is not in the $row array
795  if (!isset($row[$pointerField])) {
796  $localRow = self::getRecord($table, $row['uid'], $pointerField);
797  $foreignUid = $localRow[$pointerField];
798  } else {
799  $foreignUid = $row[$pointerField];
800  }
801  if ($foreignUid) {
802  $fieldConfig = $GLOBALS['TCA'][$table]['columns'][$pointerField]['config'];
803  $relationType = $fieldConfig['type'];
804  if ($relationType === 'select') {
805  $foreignTable = $fieldConfig['foreign_table'];
806  } elseif ($relationType === 'group') {
807  $allowedTables = explode(',', $fieldConfig['allowed']);
808  $foreignTable = $allowedTables[0];
809  } else {
810  throw new \RuntimeException('TCA foreign field pointer fields are only allowed to be used with group or select field types.', 1325862240);
811  }
812  $foreignRow = self::getRecord($foreignTable, $foreignUid, $foreignTableTypeField);
813  if ($foreignRow[$foreignTableTypeField]) {
814  $typeNum = $foreignRow[$foreignTableTypeField];
815  }
816  }
817  } else {
818  $typeNum = $row[$field];
819  }
820  // If that value is an empty string, set it to "0" (zero)
821  if (empty($typeNum)) {
822  $typeNum = 0;
823  }
824  }
825  // If current typeNum doesn't exist, set it to 0 (or to 1 for historical reasons, if 0 doesn't exist)
826  if (!$GLOBALS['TCA'][$table]['types'][$typeNum]) {
827  $typeNum = $GLOBALS['TCA'][$table]['types']['0'] ? 0 : 1;
828  }
829  // Force to string. Necessary for eg '-1' to be recognized as a type value.
830  $typeNum = (string) $typeNum;
831  return $typeNum;
832  }
833 
843  static public function getSpecConfParts($str, $defaultExtras) {
844  // Add defaultExtras:
845  $specConfParts = GeneralUtility::trimExplode(':', $defaultExtras . ':' . $str, TRUE);
846  $reg = array();
847  if (count($specConfParts)) {
848  foreach ($specConfParts as $k2 => $v2) {
849  unset($specConfParts[$k2]);
850  if (preg_match('/(.*)\\[(.*)\\]/', $v2, $reg)) {
851  $specConfParts[trim($reg[1])] = array(
852  'parameters' => GeneralUtility::trimExplode('|', $reg[2], TRUE)
853  );
854  } else {
855  $specConfParts[trim($v2)] = 1;
856  }
857  }
858  } else {
859  $specConfParts = array();
860  }
861  return $specConfParts;
862  }
863 
871  static public function getSpecConfParametersFromArray($pArr) {
872  $out = array();
873  if (is_array($pArr)) {
874  foreach ($pArr as $k => $v) {
875  $parts = explode('=', $v, 2);
876  if (count($parts) == 2) {
877  $out[trim($parts[0])] = trim($parts[1]);
878  } else {
879  $out[$k] = $v;
880  }
881  }
882  }
883  return $out;
884  }
885 
914  static public function getFlexFormDS($conf, $row, $table, $fieldName = '', $WSOL = TRUE, $newRecordPidValue = 0) {
915  // Get pointer field etc from TCA-config:
916  $ds_pointerField = $conf['ds_pointerField'];
917  $ds_array = $conf['ds'];
918  $ds_tableField = $conf['ds_tableField'];
919  $ds_searchParentField = $conf['ds_pointerField_searchParent'];
920  // Find source value:
921  $dataStructArray = '';
922  // If there is a data source array, that takes precedence
923  if (is_array($ds_array)) {
924  // If a pointer field is set, take the value from that field in the $row array and use as key.
925  if ($ds_pointerField) {
926  // Up to two pointer fields can be specified in a comma separated list.
927  $pointerFields = GeneralUtility::trimExplode(',', $ds_pointerField);
928  // If we have two pointer fields, the array keys should contain both field values separated by comma. The asterisk "*" catches all values. For backwards compatibility, it's also possible to specify only the value of the first defined ds_pointerField.
929  if (count($pointerFields) == 2) {
930  if ($ds_array[$row[$pointerFields[0]] . ',' . $row[$pointerFields[1]]]) {
931  // Check if we have a DS for the combination of both pointer fields values
932  $srcPointer = $row[$pointerFields[0]] . ',' . $row[$pointerFields[1]];
933  } elseif ($ds_array[$row[$pointerFields[1]] . ',*']) {
934  // Check if we have a DS for the value of the first pointer field suffixed with ",*"
935  $srcPointer = $row[$pointerFields[1]] . ',*';
936  } elseif ($ds_array['*,' . $row[$pointerFields[1]]]) {
937  // Check if we have a DS for the value of the second pointer field prefixed with "*,"
938  $srcPointer = '*,' . $row[$pointerFields[1]];
939  } elseif ($ds_array[$row[$pointerFields[0]]]) {
940  // Check if we have a DS for just the value of the first pointer field (mainly for backwards compatibility)
941  $srcPointer = $row[$pointerFields[0]];
942  }
943  } else {
944  $srcPointer = $row[$pointerFields[0]];
945  }
946  $srcPointer = isset($ds_array[$srcPointer]) ? $srcPointer : 'default';
947  } else {
948  $srcPointer = 'default';
949  }
950  // Get Data Source: Detect if it's a file reference and in that case read the file and parse as XML. Otherwise the value is expected to be XML.
951  if (substr($ds_array[$srcPointer], 0, 5) == 'FILE:') {
952  $file = GeneralUtility::getFileAbsFileName(substr($ds_array[$srcPointer], 5));
953  if ($file && @is_file($file)) {
954  $dataStructArray = GeneralUtility::xml2array(GeneralUtility::getUrl($file));
955  } else {
956  $dataStructArray = 'The file "' . substr($ds_array[$srcPointer], 5) . '" in ds-array key "' . $srcPointer . '" was not found ("' . $file . '")';
957  }
958  } else {
959  $dataStructArray = GeneralUtility::xml2array($ds_array[$srcPointer]);
960  }
961  } elseif ($ds_pointerField) {
962  // If pointer field AND possibly a table/field is set:
963  // Value of field pointed to:
964  $srcPointer = $row[$ds_pointerField];
965  // Searching recursively back if 'ds_pointerField_searchParent' is defined (typ. a page rootline, or maybe a tree-table):
966  if ($ds_searchParentField && !$srcPointer) {
967  $rr = self::getRecord($table, $row['uid'], 'uid,' . $ds_searchParentField);
968  // Get the "pid" field - we cannot know that it is in the input record! ###NOTE_A###
969  if ($WSOL) {
970  self::workspaceOL($table, $rr);
971  self::fixVersioningPid($table, $rr, TRUE);
972  }
973  $uidAcc = array();
974  // Used to avoid looping, if any should happen.
975  $subFieldPointer = $conf['ds_pointerField_searchParent_subField'];
976  while (!$srcPointer) {
977  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,' . $ds_pointerField . ',' . $ds_searchParentField . ($subFieldPointer ? ',' . $subFieldPointer : ''), $table, 'uid=' . (int)($newRecordPidValue ?: $rr[$ds_searchParentField]) . self::deleteClause($table));
978  $newRecordPidValue = 0;
979  $rr = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
980  $GLOBALS['TYPO3_DB']->sql_free_result($res);
981  // Break if no result from SQL db or if looping...
982  if (!is_array($rr) || isset($uidAcc[$rr['uid']])) {
983  break;
984  }
985  $uidAcc[$rr['uid']] = 1;
986  if ($WSOL) {
987  self::workspaceOL($table, $rr);
988  self::fixVersioningPid($table, $rr, TRUE);
989  }
990  $srcPointer = $subFieldPointer && $rr[$subFieldPointer] ? $rr[$subFieldPointer] : $rr[$ds_pointerField];
991  }
992  }
993  // If there is a srcPointer value:
994  if ($srcPointer) {
995  if (MathUtility::canBeInterpretedAsInteger($srcPointer)) {
996  // If integer, then its a record we will look up:
997  list($tName, $fName) = explode(':', $ds_tableField, 2);
998  if ($tName && $fName && is_array($GLOBALS['TCA'][$tName])) {
999  $dataStructRec = self::getRecord($tName, $srcPointer);
1000  if ($WSOL) {
1001  self::workspaceOL($tName, $dataStructRec);
1002  }
1003  if (strpos($dataStructRec[$fName], '<') === FALSE) {
1004  if (is_file(PATH_site . $dataStructRec[$fName])) {
1005  // The value is a pointer to a file
1006  $dataStructArray = GeneralUtility::xml2array(GeneralUtility::getUrl(PATH_site . $dataStructRec[$fName]));
1007  } else {
1008  $dataStructArray = sprintf('File \'%s\' was not found', $dataStructRec[$fName]);
1009  }
1010  } else {
1011  // No file pointer, handle as being XML (default behaviour)
1012  $dataStructArray = GeneralUtility::xml2array($dataStructRec[$fName]);
1013  }
1014  } else {
1015  $dataStructArray = 'No tablename (' . $tName . ') or fieldname (' . $fName . ') was found an valid!';
1016  }
1017  } else {
1018  // Otherwise expect it to be a file:
1019  $file = GeneralUtility::getFileAbsFileName($srcPointer);
1020  if ($file && @is_file($file)) {
1021  $dataStructArray = GeneralUtility::xml2array(GeneralUtility::getUrl($file));
1022  } else {
1023  // Error message.
1024  $dataStructArray = 'The file "' . $srcPointer . '" was not found ("' . $file . '")';
1025  }
1026  }
1027  } else {
1028  // Error message.
1029  $dataStructArray = 'No source value in fieldname "' . $ds_pointerField . '"';
1030  }
1031  } else {
1032  $dataStructArray = 'No proper configuration!';
1033  }
1034  // Hook for post-processing the Flexform DS. Introduces the possibility to configure Flexforms via TSConfig
1035  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['getFlexFormDSClass'])) {
1036  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['getFlexFormDSClass'] as $classRef) {
1037  $hookObj = GeneralUtility::getUserObj($classRef);
1038  if (method_exists($hookObj, 'getFlexFormDS_postProcessDS')) {
1039  $hookObj->getFlexFormDS_postProcessDS($dataStructArray, $conf, $row, $table, $fieldName);
1040  }
1041  }
1042  }
1043  return $dataStructArray;
1044  }
1045 
1053  static public function getRegisteredFlexForms($table = 'tt_content') {
1054  if (empty($table) || empty($GLOBALS['TCA'][$table]['columns'])) {
1055  return array();
1056  }
1057  $flexForms = array();
1058  foreach ($GLOBALS['TCA'][$table]['columns'] as $tableField => $fieldConf) {
1059  if (!empty($fieldConf['config']['type']) && !empty($fieldConf['config']['ds']) && $fieldConf['config']['type'] == 'flex') {
1060  $flexForms[$tableField] = array();
1061  unset($fieldConf['config']['ds']['default']);
1062  // Get pointer fields
1063  $pointerFields = !empty($fieldConf['config']['ds_pointerField']) ? $fieldConf['config']['ds_pointerField'] : 'list_type,CType';
1064  $pointerFields = GeneralUtility::trimExplode(',', $pointerFields);
1065  // Get FlexForms
1066  foreach ($fieldConf['config']['ds'] as $flexFormKey => $dataStruct) {
1067  // Get extension identifier (uses second value if it's not empty, "list" or "*", else first one)
1068  $identFields = GeneralUtility::trimExplode(',', $flexFormKey);
1069  $extIdent = $identFields[0];
1070  if (!empty($identFields[1]) && $identFields[1] != 'list' && $identFields[1] != '*') {
1071  $extIdent = $identFields[1];
1072  }
1073  // Load external file references
1074  if (!is_array($dataStruct)) {
1075  $file = GeneralUtility::getFileAbsFileName(str_ireplace('FILE:', '', $dataStruct));
1076  if ($file && @is_file($file)) {
1077  $dataStruct = GeneralUtility::getUrl($file);
1078  }
1079  $dataStruct = GeneralUtility::xml2array($dataStruct);
1080  if (!is_array($dataStruct)) {
1081  continue;
1082  }
1083  }
1084  // Get flexform content
1085  $dataStruct = GeneralUtility::resolveAllSheetsInDS($dataStruct);
1086  if (empty($dataStruct['sheets']) || !is_array($dataStruct['sheets'])) {
1087  continue;
1088  }
1089  // Use DS pointer to get extension title from TCA
1090  $title = $extIdent;
1091  $keyFields = GeneralUtility::trimExplode(',', $flexFormKey);
1092  foreach ($pointerFields as $pointerKey => $pointerName) {
1093  if (empty($keyFields[$pointerKey]) || $keyFields[$pointerKey] == '*' || $keyFields[$pointerKey] == 'list') {
1094  continue;
1095  }
1096  if (!empty($GLOBALS['TCA'][$table]['columns'][$pointerName]['config']['items'])) {
1097  $items = $GLOBALS['TCA'][$table]['columns'][$pointerName]['config']['items'];
1098  if (!is_array($items)) {
1099  continue;
1100  }
1101  foreach ($items as $itemConf) {
1102  if (!empty($itemConf[0]) && !empty($itemConf[1]) && $itemConf[1] == $keyFields[$pointerKey]) {
1103  $title = $itemConf[0];
1104  break 2;
1105  }
1106  }
1107  }
1108  }
1109  $flexForms[$tableField][$extIdent] = array(
1110  'title' => $title,
1111  'ds' => $dataStruct
1112  );
1113  }
1114  }
1115  }
1116  return $flexForms;
1117  }
1118 
1119  /*******************************************
1120  *
1121  * Caching related
1122  *
1123  *******************************************/
1135  static public function storeHash($hash, $data, $ident) {
1136  GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager')->getCache('cache_hash')->set($hash, $data, array('ident_' . $ident), 0);
1137  }
1138 
1149  static public function getHash($hash, $expTime = 0) {
1150  $hashContent = NULL;
1151  $cacheEntry = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager')->getCache('cache_hash')->get($hash);
1152  if ($cacheEntry) {
1153  $hashContent = $cacheEntry;
1154  }
1155  return $hashContent;
1156  }
1157 
1158  /*******************************************
1159  *
1160  * TypoScript related
1161  *
1162  *******************************************/
1172  static public function getPagesTSconfig($id, $rootLine = NULL, $returnPartArray = FALSE) {
1173  static $pagesTSconfig_cacheReference = array();
1174  static $combinedTSconfig_cache = array();
1175 
1176  $id = (int)$id;
1177  if ($returnPartArray === FALSE
1178  && $rootLine === NULL
1179  && isset($pagesTSconfig_cacheReference[$id])
1180  ) {
1181  return $combinedTSconfig_cache[$pagesTSconfig_cacheReference[$id]];
1182  } else {
1183  $TSconfig = array();
1184  if (!is_array($rootLine)) {
1185  $useCacheForCurrentPageId = TRUE;
1186  $rootLine = self::BEgetRootLine($id, '', TRUE);
1187  } else {
1188  $useCacheForCurrentPageId = FALSE;
1189  }
1190 
1191  // Order correctly
1192  ksort($rootLine);
1193  $TSdataArray = array();
1194  // Setting default configuration
1195  $TSdataArray['defaultPageTSconfig'] = $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'];
1196  foreach ($rootLine as $k => $v) {
1197  $TSdataArray['uid_' . $v['uid']] = $v['TSconfig'];
1198  }
1199  $TSdataArray = static::emitGetPagesTSconfigPreIncludeSignal($TSdataArray, $id, $rootLine, $returnPartArray);
1200  $TSdataArray = TypoScriptParser::checkIncludeLines_array($TSdataArray);
1201  if ($returnPartArray) {
1202  return $TSdataArray;
1203  }
1204  // Parsing the page TS-Config
1205  $pageTS = implode(LF . '[GLOBAL]' . LF, $TSdataArray);
1206  /* @var $parseObj \TYPO3\CMS\Backend\Configuration\TsConfigParser */
1207  $parseObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Configuration\\TsConfigParser');
1208  $res = $parseObj->parseTSconfig($pageTS, 'PAGES', $id, $rootLine);
1209  if ($res) {
1210  $TSconfig = $res['TSconfig'];
1211  }
1212  $cacheHash = $res['hash'];
1213  // Get User TSconfig overlay
1214  $userTSconfig = $GLOBALS['BE_USER']->userTS['page.'];
1215  if (is_array($userTSconfig)) {
1217  $cacheHash .= '_user' . $GLOBALS['BE_USER']->user['uid'];
1218  }
1219 
1220  if ($useCacheForCurrentPageId) {
1221  if (!isset($combinedTSconfig_cache[$cacheHash])) {
1222  $combinedTSconfig_cache[$cacheHash] = $TSconfig;
1223  }
1224  $pagesTSconfig_cacheReference[$id] = $cacheHash;
1225  }
1226  }
1227  return $TSconfig;
1228  }
1229 
1237  static public function implodeTSParams($p, $k = '') {
1238  $implodeParams = array();
1239  if (is_array($p)) {
1240  foreach ($p as $kb => $val) {
1241  if (is_array($val)) {
1242  $implodeParams = array_merge($implodeParams, self::implodeTSParams($val, $k . $kb));
1243  } else {
1244  $implodeParams[$k . $kb] = $val;
1245  }
1246  }
1247  }
1248  return $implodeParams;
1249  }
1250 
1251  /*******************************************
1252  *
1253  * Users / Groups related
1254  *
1255  *******************************************/
1264  static public function getUserNames($fields = 'username,usergroup,usergroup_cached_list,uid', $where = '') {
1265  return self::getRecordsSortedByTitle(
1266  GeneralUtility::trimExplode(',', $fields, TRUE),
1267  'be_users',
1268  'username',
1269  'AND pid=0 ' . $where
1270  );
1271  }
1272 
1280  static public function getGroupNames($fields = 'title,uid', $where = '') {
1281  return self::getRecordsSortedByTitle(
1282  GeneralUtility::trimExplode(',', $fields, TRUE),
1283  'be_groups',
1284  'title',
1285  'AND pid=0 ' . $where
1286  );
1287  }
1288 
1300  static protected function getRecordsSortedByTitle(array $fields, $table, $titleField, $where = '') {
1301  $fieldsIndex = array_flip($fields);
1302  // Make sure the titleField is amongst the fields when getting sorted
1303  $fieldsIndex[$titleField] = 1;
1304 
1305  $result = array();
1306  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, '1=1 ' . $where . self::deleteClause($table));
1307  while ($record = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
1308  // store the uid, because it might be unset if it's not among the requested $fields
1309  $recordId = $record['uid'];
1310  $record[$titleField] = self::getRecordTitle($table, $record);
1311 
1312  // include only the requested fields in the result
1313  $result[$recordId] = array_intersect_key($record, $fieldsIndex);
1314  }
1315  $GLOBALS['TYPO3_DB']->sql_free_result($res);
1316 
1317  // sort records by $sortField. This is not done in the query because the title might have been overwritten by
1318  // self::getRecordTitle();
1319  return \TYPO3\CMS\Core\Utility\ArrayUtility::sortArraysByKey($result, $titleField);
1320  }
1321 
1329  static public function getListGroupNames($fields = 'title, uid') {
1330  $exQ = ' AND hide_in_lists=0';
1331  if (!$GLOBALS['BE_USER']->isAdmin()) {
1332  $exQ .= ' AND uid IN (' . ($GLOBALS['BE_USER']->user['usergroup_cached_list'] ?: 0) . ')';
1333  }
1334  return self::getGroupNames($fields, $exQ);
1335  }
1336 
1347  static public function blindUserNames($usernames, $groupArray, $excludeBlindedFlag = 0) {
1348  if (is_array($usernames) && is_array($groupArray)) {
1349  foreach ($usernames as $uid => $row) {
1350  $userN = $uid;
1351  $set = 0;
1352  if ($row['uid'] != $GLOBALS['BE_USER']->user['uid']) {
1353  foreach ($groupArray as $v) {
1354  if ($v && GeneralUtility::inList($row['usergroup_cached_list'], $v)) {
1355  $userN = $row['username'];
1356  $set = 1;
1357  }
1358  }
1359  } else {
1360  $userN = $row['username'];
1361  $set = 1;
1362  }
1363  $usernames[$uid]['username'] = $userN;
1364  if ($excludeBlindedFlag && !$set) {
1365  unset($usernames[$uid]);
1366  }
1367  }
1368  }
1369  return $usernames;
1370  }
1371 
1380  static public function blindGroupNames($groups, $groupArray, $excludeBlindedFlag = 0) {
1381  if (is_array($groups) && is_array($groupArray)) {
1382  foreach ($groups as $uid => $row) {
1383  $groupN = $uid;
1384  $set = 0;
1385  if (GeneralUtility::inArray($groupArray, $uid)) {
1386  $groupN = $row['title'];
1387  $set = 1;
1388  }
1389  $groups[$uid]['title'] = $groupN;
1390  if ($excludeBlindedFlag && !$set) {
1391  unset($groups[$uid]);
1392  }
1393  }
1394  }
1395  return $groups;
1396  }
1397 
1398  /*******************************************
1399  *
1400  * Output related
1401  *
1402  *******************************************/
1409  static public function daysUntil($tstamp) {
1410  $delta_t = $tstamp - $GLOBALS['EXEC_TIME'];
1411  return ceil($delta_t / (3600 * 24));
1412  }
1413 
1420  static public function date($tstamp) {
1421  return date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], (int)$tstamp);
1422  }
1423 
1430  static public function datetime($value) {
1431  return date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'], $value);
1432  }
1433 
1442  static public function time($value, $withSeconds = TRUE) {
1443  $hh = floor($value / 3600);
1444  $min = floor(($value - $hh * 3600) / 60);
1445  $sec = $value - $hh * 3600 - $min * 60;
1446  $l = sprintf('%02d', $hh) . ':' . sprintf('%02d', $min);
1447  if ($withSeconds) {
1448  $l .= ':' . sprintf('%02d', $sec);
1449  }
1450  return $l;
1451  }
1452 
1460  static public function calcAge($seconds, $labels = ' min| hrs| days| yrs| min| hour| day| year') {
1461  $labelArr = explode('|', $labels);
1462  $absSeconds = abs($seconds);
1463  $sign = $seconds < 0 ? -1 : 1;
1464  if ($absSeconds < 3600) {
1465  $val = round($absSeconds / 60);
1466  $seconds = $sign * $val . ($val == 1 ? $labelArr[4] : $labelArr[0]);
1467  } elseif ($absSeconds < 24 * 3600) {
1468  $val = round($absSeconds / 3600);
1469  $seconds = $sign * $val . ($val == 1 ? $labelArr[5] : $labelArr[1]);
1470  } elseif ($absSeconds < 365 * 24 * 3600) {
1471  $val = round($absSeconds / (24 * 3600));
1472  $seconds = $sign * $val . ($val == 1 ? $labelArr[6] : $labelArr[2]);
1473  } else {
1474  $val = round($absSeconds / (365 * 24 * 3600));
1475  $seconds = $sign * $val . ($val == 1 ? $labelArr[7] : $labelArr[3]);
1476  }
1477  return $seconds;
1478  }
1479 
1489  static public function dateTimeAge($tstamp, $prefix = 1, $date = '') {
1490  return $tstamp ? ($date == 'date' ? self::date($tstamp) : self::datetime($tstamp)) . ' (' . self::calcAge($prefix * ($GLOBALS['EXEC_TIME'] - $tstamp), $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysYears')) . ')' : '';
1491  }
1492 
1499  static public function titleAltAttrib($content) {
1500  $out = '';
1501  $out .= ' alt="' . htmlspecialchars($content) . '"';
1502  $out .= ' title="' . htmlspecialchars($content) . '"';
1503  return $out;
1504  }
1505 
1515  static public function resolveFileReferences($tableName, $fieldName, $element, $workspaceId = NULL) {
1516  if (empty($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config'])) {
1517  return NULL;
1518  }
1519  $configuration = $GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config'];
1520  if (empty($configuration['type']) || $configuration['type'] !== 'inline'
1521  || empty($configuration['foreign_table']) || $configuration['foreign_table'] !== 'sys_file_reference') {
1522  return NULL;
1523  }
1524 
1525  $fileReferences = array();
1527  $relationHandler = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\RelationHandler');
1528  if ($workspaceId !== NULL) {
1529  $relationHandler->setWorkspaceId($workspaceId);
1530  }
1531  $relationHandler->start($element[$fieldName], $configuration['foreign_table'], $configuration['MM'], $element['uid'], $tableName, $configuration);
1532  $relationHandler->processDeletePlaceholder();
1533  $referenceUids = $relationHandler->tableArray[$configuration['foreign_table']];
1534 
1535  foreach ($referenceUids as $referenceUid) {
1536  try {
1537  $fileReference = ResourceFactory::getInstance()->getFileReferenceObject($referenceUid, array(), ($workspaceId === 0));
1538  $fileReferences[$fileReference->getUid()] = $fileReference;
1539  } catch (\TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException $e) {
1544  }
1545  }
1546 
1547  return $fileReferences;
1548  }
1549 
1567  static public function thumbCode($row, $table, $field, $backPath, $thumbScript = '', $uploaddir = NULL, $abs = 0, $tparams = '', $size = '', $linkInfoPopup = TRUE) {
1568  // Check and parse the size parameter
1569  $sizeParts = array(64, 64);
1570  if ($size = trim($size)) {
1571  $sizeParts = explode('x', $size . 'x' . $size);
1572  if (!(int)$sizeParts[0]) {
1573  $size = '';
1574  }
1575  }
1576  $thumbData = '';
1577  $fileReferences = static::resolveFileReferences($table, $field, $row);
1578  // FAL references
1579  if ($fileReferences !== NULL) {
1580  foreach ($fileReferences as $fileReferenceObject) {
1581  $fileObject = $fileReferenceObject->getOriginalFile();
1582 
1583  // Skip the resource if it's not of type AbstractFile. One case where this can happen if the
1584  // storage has been externally modified and the field value now points to a folder
1585  // instead of a file.
1586  if (!$fileObject instanceof AbstractFile) {
1587  continue;
1588  }
1589  if ($fileObject->isMissing()) {
1590  $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject);
1591  $thumbData .= $flashMessage->render();
1592  continue;
1593  }
1594 
1595  // Web image
1596  if (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileReferenceObject->getExtension())) {
1597  $imageUrl = $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array(
1598  'width' => $sizeParts[0],
1599  'height' => $sizeParts[1]
1600  ))->getPublicUrl(TRUE);
1601  $imgTag = '<img src="' . $imageUrl . '" alt="' . htmlspecialchars($fileReferenceObject->getName()) . '" />';
1602  } else {
1603  // Icon
1604  $imgTag = IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileObject->getName()));
1605  }
1606  if ($linkInfoPopup) {
1607  $onClick = 'top.launchView(\'_FILE\',\'' . $fileObject->getUid() . '\',\'' . $backPath . '\'); return false;';
1608  $thumbData .= '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $imgTag . '</a> ';
1609  } else {
1610  $thumbData .= $imgTag;
1611  }
1612  }
1613  } else {
1614  // Find uploaddir automatically
1615  if (is_null($uploaddir)) {
1616  $uploaddir = $GLOBALS['TCA'][$table]['columns'][$field]['config']['uploadfolder'];
1617  }
1618  $uploaddir = rtrim($uploaddir, '/');
1619  // Traverse files:
1620  $thumbs = GeneralUtility::trimExplode(',', $row[$field], TRUE);
1621  $thumbData = '';
1622  foreach ($thumbs as $theFile) {
1623  if ($theFile) {
1624  $fileName = trim($uploaddir . '/' . $theFile, '/');
1625  try {
1627  $fileObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($fileName);
1628  if ($fileObject->isMissing()) {
1629  $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject);
1630  $thumbData .= $flashMessage->render();
1631  continue;
1632  }
1633  } catch (\TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException $exception) {
1635  $flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
1636  htmlspecialchars($exception->getMessage()),
1637  $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.file_missing', TRUE),
1638  \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
1639  );
1640  $thumbData .= $flashMessage->render();
1641  continue;
1642  }
1643 
1644  $fileExtension = $fileObject->getExtension();
1645  if ($fileExtension == 'ttf' || GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileExtension)) {
1646  $imageUrl = $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array(
1647  'width' => $sizeParts[0],
1648  'height' => $sizeParts[1]
1649  ))->getPublicUrl(TRUE);
1650  $image = '<img src="' . htmlspecialchars($imageUrl) . '" hspace="2" border="0" title="' . htmlspecialchars($fileObject->getName()) . '"' . $tparams . ' alt="" />';
1651  if ($linkInfoPopup) {
1652  $onClick = 'top.launchView(\'_FILE\', \'' . $fileName . '\',\'\',\'' . $backPath . '\');return false;';
1653  $thumbData .= '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $image . '</a> ';
1654  } else {
1655  $thumbData .= $image;
1656  }
1657  } else {
1658  // Gets the icon
1659  $fileIcon = IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileObject->getName()));
1660  if ($linkInfoPopup) {
1661  $onClick = 'top.launchView(\'_FILE\', \'' . $fileName . '\',\'\',\'' . $backPath . '\'); return false;';
1662  $thumbData .= '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $fileIcon . '</a> ';
1663  } else {
1664  $thumbData .= $fileIcon;
1665  }
1666  }
1667  }
1668  }
1669  }
1670  return $thumbData;
1671  }
1672 
1682  static public function getThumbNail($thumbScript, $theFile, $tparams = '', $size = '') {
1683  $check = basename($theFile) . ':' . filemtime($theFile) . ':' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'];
1684  $params = '&file=' . rawurlencode($theFile);
1685  $params .= trim($size) ? '&size=' . trim($size) : '';
1686  $params .= '&md5sum=' . md5($check);
1687  $url = $thumbScript . '?' . $params;
1688  $th = '<img src="' . htmlspecialchars($url) . '" title="' . trim(basename($theFile)) . '"' . ($tparams ? ' ' . $tparams : '') . ' alt="" />';
1689  return $th;
1690  }
1691 
1700  static public function titleAttribForPages($row, $perms_clause = '', $includeAttrib = 1) {
1701  $parts = array();
1702  $parts[] = 'id=' . $row['uid'];
1703  if ($row['alias']) {
1704  $parts[] = $GLOBALS['LANG']->sL($GLOBALS['TCA']['pages']['columns']['alias']['label']) . ' ' . $row['alias'];
1705  }
1706  if ($row['pid'] < 0) {
1707  $parts[] = 'v#1.' . $row['t3ver_id'];
1708  }
1709  switch (VersionState::cast($row['t3ver_state'])) {
1710  case new VersionState(VersionState::NEW_PLACEHOLDER):
1711  $parts[] = 'PLH WSID#' . $row['t3ver_wsid'];
1712  break;
1713  case new VersionState(VersionState::DELETE_PLACEHOLDER):
1714  $parts[] = 'Deleted element!';
1715  break;
1716  case new VersionState(VersionState::MOVE_PLACEHOLDER):
1717  $parts[] = 'NEW LOCATION (PLH) WSID#' . $row['t3ver_wsid'];
1718  break;
1719  case new VersionState(VersionState::MOVE_POINTER):
1720  $parts[] = 'OLD LOCATION (PNT) WSID#' . $row['t3ver_wsid'];
1721  break;
1722  case new VersionState(VersionState::NEW_PLACEHOLDER_VERSION):
1723  $parts[] = 'New element!';
1724  break;
1725  }
1726  if ($row['doktype'] == PageRepository::DOKTYPE_LINK) {
1727  $parts[] = $GLOBALS['LANG']->sL($GLOBALS['TCA']['pages']['columns']['url']['label']) . ' ' . $row['url'];
1728  } elseif ($row['doktype'] == PageRepository::DOKTYPE_SHORTCUT) {
1729  if ($perms_clause) {
1730  $label = self::getRecordPath((int)$row['shortcut'], $perms_clause, 20);
1731  } else {
1732  $row['shortcut'] = (int)$row['shortcut'];
1733  $lRec = self::getRecordWSOL('pages', $row['shortcut'], 'title');
1734  $label = $lRec['title'] . ' (id=' . $row['shortcut'] . ')';
1735  }
1736  if ($row['shortcut_mode'] != PageRepository::SHORTCUT_MODE_NONE) {
1737  $label .= ', ' . $GLOBALS['LANG']->sL($GLOBALS['TCA']['pages']['columns']['shortcut_mode']['label']) . ' ' . $GLOBALS['LANG']->sL(self::getLabelFromItemlist('pages', 'shortcut_mode', $row['shortcut_mode']));
1738  }
1739  $parts[] = $GLOBALS['LANG']->sL($GLOBALS['TCA']['pages']['columns']['shortcut']['label']) . ' ' . $label;
1740  } elseif ($row['doktype'] == PageRepository::DOKTYPE_MOUNTPOINT) {
1741  if ($perms_clause) {
1742  $label = self::getRecordPath((int)$row['mount_pid'], $perms_clause, 20);
1743  } else {
1744  $lRec = self::getRecordWSOL('pages', (int)$row['mount_pid'], 'title');
1745  $label = $lRec['title'] . ' (id=' . $row['mount_pid'] . ')';
1746  }
1747  $parts[] = $GLOBALS['LANG']->sL($GLOBALS['TCA']['pages']['columns']['mount_pid']['label']) . ' ' . $label;
1748  if ($row['mount_pid_ol']) {
1749  $parts[] = $GLOBALS['LANG']->sL($GLOBALS['TCA']['pages']['columns']['mount_pid_ol']['label']);
1750  }
1751  }
1752  if ($row['nav_hide']) {
1753  $parts[] = rtrim($GLOBALS['LANG']->sL($GLOBALS['TCA']['pages']['columns']['nav_hide']['label']), ':');
1754  }
1755  if ($row['hidden']) {
1756  $parts[] = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.hidden');
1757  }
1758  if ($row['starttime']) {
1759  $parts[] = $GLOBALS['LANG']->sL($GLOBALS['TCA']['pages']['columns']['starttime']['label']) . ' ' . self::dateTimeAge($row['starttime'], -1, 'date');
1760  }
1761  if ($row['endtime']) {
1762  $parts[] = $GLOBALS['LANG']->sL($GLOBALS['TCA']['pages']['columns']['endtime']['label']) . ' ' . self::dateTimeAge($row['endtime'], -1, 'date');
1763  }
1764  if ($row['fe_group']) {
1765  $fe_groups = array();
1766  foreach (GeneralUtility::intExplode(',', $row['fe_group']) as $fe_group) {
1767  if ($fe_group < 0) {
1768  $fe_groups[] = $GLOBALS['LANG']->sL(self::getLabelFromItemlist('pages', 'fe_group', $fe_group));
1769  } else {
1770  $lRec = self::getRecordWSOL('fe_groups', $fe_group, 'title');
1771  $fe_groups[] = $lRec['title'];
1772  }
1773  }
1774  $label = implode(', ', $fe_groups);
1775  $parts[] = $GLOBALS['LANG']->sL($GLOBALS['TCA']['pages']['columns']['fe_group']['label']) . ' ' . $label;
1776  }
1777  $out = htmlspecialchars(implode(' - ', $parts));
1778  return $includeAttrib ? 'title="' . $out . '"' : $out;
1779  }
1780 
1790  static public function getRecordIconAltText($row, $table = 'pages') {
1791  if ($table == 'pages') {
1792  $out = self::titleAttribForPages($row, '', 0);
1793  } else {
1794  $ctrl = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
1795  // Uid is added
1796  $out = 'id=' . $row['uid'];
1797  if ($table == 'pages' && $row['alias']) {
1798  $out .= ' / ' . $row['alias'];
1799  }
1800  if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS'] && $row['pid'] < 0) {
1801  $out .= ' - v#1.' . $row['t3ver_id'];
1802  }
1803  if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
1804  switch (VersionState::cast($row['t3ver_state'])) {
1805  case new VersionState(VersionState::NEW_PLACEHOLDER):
1806  $out .= ' - PLH WSID#' . $row['t3ver_wsid'];
1807  break;
1808  case new VersionState(VersionState::DELETE_PLACEHOLDER):
1809  $out .= ' - Deleted element!';
1810  break;
1811  case new VersionState(VersionState::MOVE_PLACEHOLDER):
1812  $out .= ' - NEW LOCATION (PLH) WSID#' . $row['t3ver_wsid'];
1813  break;
1814  case new VersionState(VersionState::MOVE_POINTER):
1815  $out .= ' - OLD LOCATION (PNT) WSID#' . $row['t3ver_wsid'];
1816  break;
1817  case new VersionState(VersionState::NEW_PLACEHOLDER_VERSION):
1818  $out .= ' - New element!';
1819  break;
1820  }
1821  }
1822  // Hidden
1823  if ($ctrl['disabled']) {
1824  $out .= $row[$ctrl['disabled']] ? ' - ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.hidden') : '';
1825  }
1826  if ($ctrl['starttime']) {
1827  if ($row[$ctrl['starttime']] > $GLOBALS['EXEC_TIME']) {
1828  $out .= ' - ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.starttime') . ':' . self::date($row[$ctrl['starttime']]) . ' (' . self::daysUntil($row[$ctrl['starttime']]) . ' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.days') . ')';
1829  }
1830  }
1831  if ($row[$ctrl['endtime']]) {
1832  $out .= ' - ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.endtime') . ': ' . self::date($row[$ctrl['endtime']]) . ' (' . self::daysUntil($row[$ctrl['endtime']]) . ' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.days') . ')';
1833  }
1834  }
1835  return htmlspecialchars($out);
1836  }
1837 
1846  static public function getLabelFromItemlist($table, $col, $key) {
1847  // Check, if there is an "items" array:
1848  if (is_array($GLOBALS['TCA'][$table]) && is_array($GLOBALS['TCA'][$table]['columns'][$col]) && is_array($GLOBALS['TCA'][$table]['columns'][$col]['config']['items'])) {
1849  // Traverse the items-array...
1850  foreach ($GLOBALS['TCA'][$table]['columns'][$col]['config']['items'] as $k => $v) {
1851  // ... and return the first found label where the value was equal to $key
1852  if ((string)$v[1] === (string)$key) {
1853  return $v[0];
1854  }
1855  }
1856  }
1857  }
1858 
1868  static public function getLabelFromItemListMerged($pageId, $table, $column, $key) {
1869  $pageTsConfig = static::getPagesTSconfig($pageId);
1870  $label = '';
1871  if (is_array($pageTsConfig['TCEFORM.']) && is_array($pageTsConfig['TCEFORM.'][$table . '.']) && is_array($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.'])) {
1872  if (is_array($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['addItems.']) && isset($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['addItems.'][$key])) {
1873  $label = $pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['addItems.'][$key];
1874  } elseif (is_array($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['altLabels.']) && isset($pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['altLabels.'][$key])) {
1875  $label = $pageTsConfig['TCEFORM.'][$table . '.'][$column . '.']['altLabels.'][$key];
1876  }
1877  }
1878  if (empty($label)) {
1879  $tcaValue = self::getLabelFromItemlist($table, $column, $key);
1880  if (!empty($tcaValue)) {
1881  $label = $tcaValue;
1882  }
1883  }
1884  return $label;
1885  }
1886 
1896  static public function getLabelsFromItemsList($table, $column, $key) {
1897  $labels = array();
1898  $values = GeneralUtility::trimExplode(',', $key, TRUE);
1899  if (count($values) > 0) {
1900  // Check if there is an "items" array
1901  if (is_array($GLOBALS['TCA'][$table]) && is_array($GLOBALS['TCA'][$table]['columns'][$column]) && is_array($GLOBALS['TCA'][$table]['columns'][$column]['config']['items'])) {
1902  // Loop on all selected values
1903  foreach ($values as $aValue) {
1904  foreach ($GLOBALS['TCA'][$table]['columns'][$column]['config']['items'] as $itemConfiguration) {
1905  // Loop on all available items
1906  // Keep matches and move on to next value
1907  if ((string)$aValue === (string)$itemConfiguration[1]) {
1908  $labels[] = $GLOBALS['LANG']->sL($itemConfiguration[0]);
1909  break;
1910  }
1911  }
1912  }
1913  }
1914  }
1915  return implode(', ', $labels);
1916  }
1917 
1927  static public function getItemLabel($table, $col, $printAllWrap = '') {
1928  // Check if column exists
1929  if (is_array($GLOBALS['TCA'][$table]) && is_array($GLOBALS['TCA'][$table]['columns'][$col])) {
1930  return $GLOBALS['TCA'][$table]['columns'][$col]['label'];
1931  }
1932  if ($printAllWrap) {
1933  GeneralUtility::deprecationLog('The third parameter of getItemLabel() is deprecated with TYPO3 CMS 6.2 and will be removed two versions later.');
1934  $parts = explode('|', $printAllWrap);
1935  return $parts[0] . $col . $parts[1];
1936  }
1937 
1938  return NULL;
1939  }
1940 
1949  static protected function replaceL10nModeFields($table, array $row) {
1950  $originalUidField = isset($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'])
1951  ? $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']
1952  : '';
1953  if (empty($row[$originalUidField])) {
1954  return $row;
1955  }
1956 
1957  $originalTable = self::getOriginalTranslationTable($table);
1958  $originalRow = self::getRecord($originalTable, $row[$originalUidField]);
1959  foreach ($row as $field => $_) {
1960  $l10n_mode = isset($GLOBALS['TCA'][$originalTable]['columns'][$field]['l10n_mode'])
1961  ? $GLOBALS['TCA'][$originalTable]['columns'][$field]['l10n_mode']
1962  : '';
1963  if ($l10n_mode === 'exclude' || ($l10n_mode === 'mergeIfNotBlank' && trim($row[$field]) === '')) {
1964  $row[$field] = $originalRow[$field];
1965  }
1966  }
1967  return $row;
1968  }
1969 
1980  static public function getRecordTitle($table, $row, $prep = FALSE, $forceResult = TRUE) {
1981  if (is_array($GLOBALS['TCA'][$table])) {
1982  // If configured, call userFunc
1983  if ($GLOBALS['TCA'][$table]['ctrl']['label_userFunc']) {
1984  $params['table'] = $table;
1985  $params['row'] = $row;
1986  $params['title'] = '';
1987  $params['options'] = isset($GLOBALS['TCA'][$table]['ctrl']['label_userFunc_options']) ? $GLOBALS['TCA'][$table]['ctrl']['label_userFunc_options'] : array();
1988 
1989  // Create NULL-reference
1990  $null = NULL;
1991  GeneralUtility::callUserFunction($GLOBALS['TCA'][$table]['ctrl']['label_userFunc'], $params, $null);
1992  $t = $params['title'];
1993  } else {
1994  if (is_array($row)) {
1995  $row = self::replaceL10nModeFields($table, $row);
1996  }
1997 
1998  // No userFunc: Build label
1999  $t = self::getProcessedValue($table, $GLOBALS['TCA'][$table]['ctrl']['label'], $row[$GLOBALS['TCA'][$table]['ctrl']['label']], 0, 0, FALSE, $row['uid'], $forceResult);
2000  if ($GLOBALS['TCA'][$table]['ctrl']['label_alt'] && ($GLOBALS['TCA'][$table]['ctrl']['label_alt_force'] || (string)$t === '')) {
2001  $altFields = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['label_alt'], TRUE);
2002  $tA = array();
2003  if (!empty($t)) {
2004  $tA[] = $t;
2005  }
2006  foreach ($altFields as $fN) {
2007  $t = trim(strip_tags($row[$fN]));
2008  if ((string)$t !== '') {
2009  $t = self::getProcessedValue($table, $fN, $t, 0, 0, FALSE, $row['uid']);
2010  if (!$GLOBALS['TCA'][$table]['ctrl']['label_alt_force']) {
2011  break;
2012  }
2013  $tA[] = $t;
2014  }
2015  }
2016  if ($GLOBALS['TCA'][$table]['ctrl']['label_alt_force']) {
2017  $t = implode(', ', $tA);
2018  }
2019  }
2020  }
2021  // If the current result is empty, set it to '[No title]' (localized) and prepare for output if requested
2022  if ($prep || $forceResult) {
2023  if ($prep) {
2024  $t = self::getRecordTitlePrep($t);
2025  }
2026  if (trim($t) === '') {
2027  $t = self::getNoRecordTitle($prep);
2028  }
2029  }
2030  return $t;
2031  }
2032  }
2033 
2042  static public function getRecordTitlePrep($title, $titleLength = 0) {
2043  // If $titleLength is not a valid positive integer, use BE_USER->uc['titleLen']:
2044  if (!$titleLength || !MathUtility::canBeInterpretedAsInteger($titleLength) || $titleLength < 0) {
2045  $titleLength = $GLOBALS['BE_USER']->uc['titleLen'];
2046  }
2047  $titleOrig = htmlspecialchars($title);
2048  $title = htmlspecialchars(GeneralUtility::fixed_lgd_cs($title, $titleLength));
2049  // If title was cropped, offer a tooltip:
2050  if ($titleOrig != $title) {
2051  $title = '<span title="' . $titleOrig . '">' . $title . '</span>';
2052  }
2053  return $title;
2054  }
2055 
2062  static public function getNoRecordTitle($prep = FALSE) {
2063  $noTitle = '[' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.no_title', TRUE) . ']';
2064  if ($prep) {
2065  $noTitle = '<em>' . $noTitle . '</em>';
2066  }
2067  return $noTitle;
2068  }
2069 
2086  static public function getProcessedValue($table, $col, $value, $fixed_lgd_chars = 0, $defaultPassthrough = 0, $noRecordLookup = FALSE, $uid = 0, $forceResult = TRUE) {
2087  if ($col == 'uid') {
2088  // No need to load TCA as uid is not in TCA-array
2089  return $value;
2090  }
2091  // Check if table and field is configured:
2092  if (is_array($GLOBALS['TCA'][$table]) && is_array($GLOBALS['TCA'][$table]['columns'][$col])) {
2093  // Depending on the fields configuration, make a meaningful output value.
2094  $theColConf = $GLOBALS['TCA'][$table]['columns'][$col]['config'];
2095  /*****************
2096  *HOOK: pre-processing the human readable output from a record
2097  ****************/
2098  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['preProcessValue'])) {
2099  // Create NULL-reference
2100  $null = NULL;
2101  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['preProcessValue'] as $_funcRef) {
2102  GeneralUtility::callUserFunction($_funcRef, $theColConf, $null);
2103  }
2104  }
2105  $l = '';
2106  switch ((string) $theColConf['type']) {
2107  case 'radio':
2108  $l = self::getLabelFromItemlist($table, $col, $value);
2109  $l = $GLOBALS['LANG']->sL($l);
2110  break;
2111  case 'inline':
2112  case 'select':
2113  if ($theColConf['MM']) {
2114  if ($uid) {
2115  // Display the title of MM related records in lists
2116  if ($noRecordLookup) {
2117  $MMfield = $theColConf['foreign_table'] . '.uid';
2118  } else {
2119  $MMfields = array($theColConf['foreign_table'] . '.' . $GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label']);
2120  foreach (GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label_alt'], TRUE) as $f) {
2121  $MMfields[] = $theColConf['foreign_table'] . '.' . $f;
2122  }
2123  $MMfield = join(',', $MMfields);
2124  }
2126  $dbGroup = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\RelationHandler');
2127  $dbGroup->start($value, $theColConf['foreign_table'], $theColConf['MM'], $uid, $table, $theColConf);
2128  $selectUids = $dbGroup->tableArray[$theColConf['foreign_table']];
2129  if (is_array($selectUids) && count($selectUids) > 0) {
2130  $MMres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid, ' . $MMfield, $theColConf['foreign_table'], 'uid IN (' . implode(',', $selectUids) . ')' . self::deleteClause($theColConf['foreign_table']));
2131  $mmlA = array();
2132  while ($MMrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($MMres)) {
2133  // Keep sorting of $selectUids
2134  $mmlA[array_search($MMrow['uid'], $selectUids)] = $noRecordLookup ?
2135  $MMrow['uid'] :
2136  static::getRecordTitle($theColConf['foreign_table'], $MMrow, FALSE, $forceResult);
2137  }
2138  $GLOBALS['TYPO3_DB']->sql_free_result($MMres);
2139  if (!empty($mmlA)) {
2140  ksort($mmlA);
2141  $l = implode('; ', $mmlA);
2142  } else {
2143  $l = 'N/A';
2144  }
2145  } else {
2146  $l = 'N/A';
2147  }
2148  } else {
2149  $l = 'N/A';
2150  }
2151  } else {
2152  $l = self::getLabelsFromItemsList($table, $col, $value);
2153  if ($theColConf['foreign_table'] && !$l && $GLOBALS['TCA'][$theColConf['foreign_table']]) {
2154  if ($noRecordLookup) {
2155  $l = $value;
2156  } else {
2157  $rParts = array();
2158  if ($uid && isset($theColConf['foreign_field']) && $theColConf['foreign_field'] !== '') {
2159  $whereClause = '';
2160  if (!empty($theColConf['foreign_table_field'])) {
2161  $whereClause .= ' AND ' . $theColConf['foreign_table_field'] . ' = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($table, $theColConf['foreign_table']);
2162  }
2163  // Add additional where clause if foreign_match_fields are defined
2164  $foreignMatchFields = is_array($theColConf['foreign_match_fields']) ? $theColConf['foreign_match_fields'] : array();
2165  foreach ($foreignMatchFields as $matchField => $matchValue) {
2166  $whereClause .= ' AND ' . $matchField . '=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($matchValue, $theColConf['foreign_table']);
2167  }
2168  $records = self::getRecordsByField($theColConf['foreign_table'], $theColConf['foreign_field'], $uid, $whereClause);
2169  if (!empty($records)) {
2170  foreach ($records as $record) {
2171  $rParts[] = $record['uid'];
2172  }
2173  }
2174  }
2175  if (empty($rParts)) {
2176  $rParts = GeneralUtility::trimExplode(',', $value, TRUE);
2177  }
2178  $lA = array();
2179  foreach ($rParts as $rVal) {
2180  $rVal = (int)$rVal;
2181  if ($rVal > 0) {
2182  $r = self::getRecordWSOL($theColConf['foreign_table'], $rVal);
2183  } else {
2184  $r = self::getRecordWSOL($theColConf['neg_foreign_table'], -$rVal);
2185  }
2186  if (is_array($r)) {
2187  $lA[] = $GLOBALS['LANG']->sL(($rVal > 0 ? $theColConf['foreign_table_prefix'] : $theColConf['neg_foreign_table_prefix'])) . self::getRecordTitle(($rVal > 0 ? $theColConf['foreign_table'] : $theColConf['neg_foreign_table']), $r, FALSE, $forceResult);
2188  } else {
2189  $lA[] = $rVal ? '[' . $rVal . '!]' : '';
2190  }
2191  }
2192  $l = implode(', ', $lA);
2193  }
2194  }
2195  if (empty($l) && !empty($value)) {
2196  // Use plain database value when label is empty
2197  $l = $value;
2198  }
2199  }
2200  break;
2201  case 'group':
2202  // resolve the titles for DB records
2203  if ($theColConf['internal_type'] === 'db') {
2204  if ($theColConf['MM']) {
2205  if ($uid) {
2206  // Display the title of MM related records in lists
2207  if ($noRecordLookup) {
2208  $MMfield = $theColConf['foreign_table'] . '.uid';
2209  } else {
2210  $MMfields = array($theColConf['foreign_table'] . '.' . $GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label']);
2211  $altLabelFields = explode(',', $GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label_alt']);
2212  foreach ($altLabelFields as $f) {
2213  $f = trim($f);
2214  if ($f !== '') {
2215  $MMfields[] = $theColConf['foreign_table'] . '.' . $f;
2216  }
2217  }
2218  $MMfield = join(',', $MMfields);
2219  }
2221  $dbGroup = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\RelationHandler');
2222  $dbGroup->start($value, $theColConf['foreign_table'], $theColConf['MM'], $uid, $table, $theColConf);
2223  $selectUids = $dbGroup->tableArray[$theColConf['foreign_table']];
2224  if (!empty($selectUids) && is_array($selectUids)) {
2225  $MMres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
2226  'uid, ' . $MMfield,
2227  $theColConf['foreign_table'],
2228  'uid IN (' . implode(',', $selectUids) . ')' . static::deleteClause($theColConf['foreign_table'])
2229  );
2230  $mmlA = array();
2231  while ($MMrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($MMres)) {
2232  // Keep sorting of $selectUids
2233  $mmlA[array_search($MMrow['uid'], $selectUids)] = $noRecordLookup
2234  ? $MMrow['uid']
2235  : static::getRecordTitle($theColConf['foreign_table'], $MMrow, FALSE, $forceResult);
2236  }
2237  $GLOBALS['TYPO3_DB']->sql_free_result($MMres);
2238  if (!empty($mmlA)) {
2239  ksort($mmlA);
2240  $l = implode('; ', $mmlA);
2241  } else {
2242  $l = 'N/A';
2243  }
2244  } else {
2245  $l = 'N/A';
2246  }
2247  } else {
2248  $l = 'N/A';
2249  }
2250  } else {
2251  $finalValues = array();
2252  $relationTableName = $theColConf['allowed'];
2253  $explodedValues = GeneralUtility::trimExplode(',', $value, TRUE);
2254 
2255  foreach ($explodedValues as $explodedValue) {
2256 
2257  if (MathUtility::canBeInterpretedAsInteger($explodedValue)) {
2258  $relationTableNameForField = $relationTableName;
2259  } else {
2260  list($relationTableNameForField, $explodedValue) = self::splitTable_Uid($explodedValue);
2261  }
2262 
2263  $relationRecord = static::getRecordWSOL($relationTableNameForField, $explodedValue);
2264  $finalValues[] = static::getRecordTitle($relationTableNameForField, $relationRecord);
2265  }
2266 
2267  $l = implode(', ', $finalValues);
2268  }
2269  } else {
2270  $l = implode(', ', GeneralUtility::trimExplode(',', $value, TRUE));
2271  }
2272  break;
2273  case 'check':
2274  if (!is_array($theColConf['items']) || count($theColConf['items']) == 1) {
2275  $l = $value ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xlf:yes') : $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xlf:no');
2276  } else {
2277  $lA = array();
2278  foreach ($theColConf['items'] as $key => $val) {
2279  if ($value & pow(2, $key)) {
2280  $lA[] = $GLOBALS['LANG']->sL($val[0]);
2281  }
2282  }
2283  $l = implode(', ', $lA);
2284  }
2285  break;
2286  case 'input':
2287  // Hide value 0 for dates, but show it for everything else
2288  if (isset($value)) {
2289  if (GeneralUtility::inList($theColConf['eval'], 'date')) {
2290  // Handle native date field
2291  if (isset($theColConf['dbType']) && $theColConf['dbType'] === 'date') {
2292  $dateTimeFormats = $GLOBALS['TYPO3_DB']->getDateTimeFormats($table);
2293  $emptyValue = $dateTimeFormats['date']['empty'];
2294  $value = $value !== $emptyValue ? strtotime($value) : 0;
2295  }
2296  if (!empty($value)) {
2297  $l = self::date($value) . ' (' . ($GLOBALS['EXEC_TIME'] - $value > 0 ? '-' : '') . self::calcAge(abs(($GLOBALS['EXEC_TIME'] - $value)), $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysYears')) . ')';
2298  }
2299  } elseif (GeneralUtility::inList($theColConf['eval'], 'time')) {
2300  if (!empty($value)) {
2301  $l = self::time($value, FALSE);
2302  }
2303  } elseif (GeneralUtility::inList($theColConf['eval'], 'timesec')) {
2304  if (!empty($value)) {
2305  $l = self::time($value);
2306  }
2307  } elseif (GeneralUtility::inList($theColConf['eval'], 'datetime')) {
2308  // Handle native date/time field
2309  if (isset($theColConf['dbType']) && $theColConf['dbType'] === 'datetime') {
2310  $dateTimeFormats = $GLOBALS['TYPO3_DB']->getDateTimeFormats($table);
2311  $emptyValue = $dateTimeFormats['datetime']['empty'];
2312  $value = $value !== $emptyValue ? strtotime($value) : 0;
2313  }
2314  if (!empty($value)) {
2315  $l = self::datetime($value);
2316  }
2317  } else {
2318  $l = $value;
2319  }
2320  }
2321  break;
2322  case 'flex':
2323  $l = strip_tags($value);
2324  break;
2325  default:
2326  if ($defaultPassthrough) {
2327  $l = $value;
2328  } elseif ($theColConf['MM']) {
2329  $l = 'N/A';
2330  } elseif ($value) {
2331  $l = GeneralUtility::fixed_lgd_cs(strip_tags($value), 200);
2332  }
2333  }
2334  // If this field is a password field, then hide the password by changing it to a random number of asterisk (*)
2335  if (stristr($theColConf['eval'], 'password')) {
2336  $l = '';
2337  $randomNumber = rand(5, 12);
2338  for ($i = 0; $i < $randomNumber; $i++) {
2339  $l .= '*';
2340  }
2341  }
2342  /*****************
2343  *HOOK: post-processing the human readable output from a record
2344  ****************/
2345  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['postProcessValue'])) {
2346  // Create NULL-reference
2347  $null = NULL;
2348  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['postProcessValue'] as $_funcRef) {
2349  $params = array(
2350  'value' => $l,
2351  'colConf' => $theColConf
2352  );
2353  $l = GeneralUtility::callUserFunction($_funcRef, $params, $null);
2354  }
2355  }
2356  if ($fixed_lgd_chars) {
2357  return GeneralUtility::fixed_lgd_cs($l, $fixed_lgd_chars);
2358  } else {
2359  return $l;
2360  }
2361  }
2362  }
2363 
2376  static public function getProcessedValueExtra($table, $fN, $fV, $fixed_lgd_chars = 0, $uid = 0, $forceResult = TRUE) {
2377  $fVnew = self::getProcessedValue($table, $fN, $fV, $fixed_lgd_chars, 1, 0, $uid, $forceResult);
2378  if (!isset($fVnew)) {
2379  if (is_array($GLOBALS['TCA'][$table])) {
2380  if ($fN == $GLOBALS['TCA'][$table]['ctrl']['tstamp'] || $fN == $GLOBALS['TCA'][$table]['ctrl']['crdate']) {
2381  $fVnew = self::datetime($fV);
2382  } elseif ($fN == 'pid') {
2383  // Fetches the path with no regard to the users permissions to select pages.
2384  $fVnew = self::getRecordPath($fV, '1=1', 20);
2385  } else {
2386  $fVnew = $fV;
2387  }
2388  }
2389  }
2390  return $fVnew;
2391  }
2392 
2399  static public function getFileIcon($ext) {
2400  return $GLOBALS['FILEICONS'][$ext] ?: $GLOBALS['FILEICONS']['default'];
2401  }
2402 
2413  static public function getCommonSelectFields($table, $prefix = '', $fields = array()) {
2414  $fields[] = $prefix . 'uid';
2415  if (isset($GLOBALS['TCA'][$table]['ctrl']['label']) && $GLOBALS['TCA'][$table]['ctrl']['label'] != '') {
2416  $fields[] = $prefix . $GLOBALS['TCA'][$table]['ctrl']['label'];
2417  }
2418  if ($GLOBALS['TCA'][$table]['ctrl']['label_alt']) {
2419  $secondFields = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['label_alt'], TRUE);
2420  foreach ($secondFields as $fieldN) {
2421  $fields[] = $prefix . $fieldN;
2422  }
2423  }
2424  if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
2425  $fields[] = $prefix . 't3ver_id';
2426  $fields[] = $prefix . 't3ver_state';
2427  $fields[] = $prefix . 't3ver_wsid';
2428  $fields[] = $prefix . 't3ver_count';
2429  }
2430  if ($GLOBALS['TCA'][$table]['ctrl']['selicon_field']) {
2431  $fields[] = $prefix . $GLOBALS['TCA'][$table]['ctrl']['selicon_field'];
2432  }
2433  if ($GLOBALS['TCA'][$table]['ctrl']['typeicon_column']) {
2434  $fields[] = $prefix . $GLOBALS['TCA'][$table]['ctrl']['typeicon_column'];
2435  }
2436  if (is_array($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
2437  if ($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled']) {
2438  $fields[] = $prefix . $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'];
2439  }
2440  if ($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['starttime']) {
2441  $fields[] = $prefix . $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['starttime'];
2442  }
2443  if ($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime']) {
2444  $fields[] = $prefix . $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime'];
2445  }
2446  if ($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['fe_group']) {
2447  $fields[] = $prefix . $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['fe_group'];
2448  }
2449  }
2450  return implode(',', array_unique($fields));
2451  }
2452 
2465  static public function makeConfigForm($configArray, $defaults, $dataPrefix) {
2466  $params = $defaults;
2467  if (is_array($configArray)) {
2468  $lines = array();
2469  foreach ($configArray as $fname => $config) {
2470  if (is_array($config)) {
2471  $lines[$fname] = '<strong>' . htmlspecialchars($config[1]) . '</strong><br />';
2472  $lines[$fname] .= $config[2] . '<br />';
2473  switch ($config[0]) {
2474  case 'string':
2475 
2476  case 'short':
2477  $formEl = '<input type="text" name="' . $dataPrefix . '[' . $fname . ']" value="' . $params[$fname] . '"' . $GLOBALS['TBE_TEMPLATE']->formWidth(($config[0] == 'short' ? 24 : 48)) . ' />';
2478  break;
2479  case 'check':
2480  $formEl = '<input type="hidden" name="' . $dataPrefix . '[' . $fname . ']" value="0" /><input type="checkbox" name="' . $dataPrefix . '[' . $fname . ']" value="1"' . ($params[$fname] ? ' checked="checked"' : '') . ' />';
2481  break;
2482  case 'comment':
2483  $formEl = '';
2484  break;
2485  case 'select':
2486  $opt = array();
2487  foreach ($config[3] as $k => $v) {
2488  $opt[] = '<option value="' . htmlspecialchars($k) . '"' . ($params[$fname] == $k ? ' selected="selected"' : '') . '>' . htmlspecialchars($v) . '</option>';
2489  }
2490  $formEl = '<select name="' . $dataPrefix . '[' . $fname . ']">' . implode('', $opt) . '</select>';
2491  break;
2492  default:
2493  debug($config);
2494  }
2495  $lines[$fname] .= $formEl;
2496  $lines[$fname] .= '<br /><br />';
2497  } else {
2498  $lines[$fname] = '<hr />';
2499  if ($config) {
2500  $lines[$fname] .= '<strong>' . strtoupper(htmlspecialchars($config)) . '</strong><br />';
2501  }
2502  if ($config) {
2503  $lines[$fname] .= '<br />';
2504  }
2505  }
2506  }
2507  }
2508  $out = implode('', $lines);
2509  $out .= '<input type="submit" name="submit" value="Update configuration" />';
2510  return $out;
2511  }
2512 
2513  /*******************************************
2514  *
2515  * Backend Modules API functions
2516  *
2517  *******************************************/
2534  static public function helpTextIcon($table, $field, $BACK_PATH, $force = 0) {
2535  if (is_array($GLOBALS['TCA_DESCR'][$table]) && is_array($GLOBALS['TCA_DESCR'][$table]['columns'][$field]) && (isset($GLOBALS['BE_USER']->uc['edit_showFieldHelp']) || $force)) {
2536  return self::wrapInHelp($table, $field);
2537  }
2538  }
2539 
2547  static public function helpTextArray($table, $field) {
2548  if (!isset($GLOBALS['TCA_DESCR'][$table]['columns'])) {
2549  $GLOBALS['LANG']->loadSingleTableDescription($table);
2550  }
2551  $output = array(
2552  'description' => NULL,
2553  'title' => NULL,
2554  'moreInfo' => FALSE
2555  );
2556  if (is_array($GLOBALS['TCA_DESCR'][$table]) && is_array($GLOBALS['TCA_DESCR'][$table]['columns'][$field])) {
2557  $data = $GLOBALS['TCA_DESCR'][$table]['columns'][$field];
2558  // Add alternative title, if defined
2559  if ($data['alttitle']) {
2560  $output['title'] = $data['alttitle'];
2561  }
2562  // If we have more information to show
2563  if ($data['image_descr'] || $data['seeAlso'] || $data['details'] || $data['syntax']) {
2564  $output['moreInfo'] = TRUE;
2565  }
2566  // Add description
2567  if ($data['description']) {
2568  $output['description'] = $data['description'];
2569  }
2570  }
2571  return $output;
2572  }
2573 
2582  static public function helpText($table, $field) {
2583  $helpTextArray = self::helpTextArray($table, $field);
2584  $output = '';
2585  $arrow = '';
2586  // Put header before the rest of the text
2587  if ($helpTextArray['title'] !== NULL) {
2588  $output .= '<h2 class="t3-row-header">' . $helpTextArray['title'] . '</h2>';
2589  }
2590  // Add see also arrow if we have more info
2591  if ($helpTextArray['moreInfo']) {
2592  $arrow = IconUtility::getSpriteIcon('actions-view-go-forward');
2593  }
2594  // Wrap description and arrow in p tag
2595  if ($helpTextArray['description'] !== NULL || $arrow) {
2596  $output .= '<p class="t3-help-short">' . nl2br(htmlspecialchars($helpTextArray['description'])) . $arrow . '</p>';
2597  }
2598  return $output;
2599  }
2600 
2613  static public function wrapInHelp($table, $field, $text = '', array $overloadHelpText = array()) {
2614  // Initialize some variables
2615  $helpText = '';
2616  $abbrClassAdd = '';
2617  $wrappedText = $text;
2618  $hasHelpTextOverload = count($overloadHelpText) > 0;
2619  // Get the help text that should be shown on hover
2620  if (!$hasHelpTextOverload) {
2621  $helpText = self::helpText($table, $field);
2622  }
2623  // If there's a help text or some overload information, proceed with preparing an output
2624  if (!empty($helpText) || $hasHelpTextOverload) {
2625  // If no text was given, just use the regular help icon
2626  if ($text == '') {
2627  $text = IconUtility::getSpriteIcon('actions-system-help-open');
2628  $abbrClassAdd = '-icon';
2629  }
2630  $text = '<abbr class="t3-help-teaser' . $abbrClassAdd . '">' . $text . '</abbr>';
2631  $wrappedText = '<span class="t3-help-link" href="#" data-table="' . $table . '" data-field="' . $field . '"';
2632  // The overload array may provide a title and a description
2633  // If either one is defined, add them to the "data" attributes
2634  if ($hasHelpTextOverload) {
2635  if (isset($overloadHelpText['title'])) {
2636  $wrappedText .= ' data-title="' . htmlspecialchars($overloadHelpText['title']) . '"';
2637  }
2638  if (isset($overloadHelpText['description'])) {
2639  $wrappedText .= ' data-description="' . htmlspecialchars($overloadHelpText['description']) . '"';
2640  }
2641  }
2642  $wrappedText .= '>' . $text . '</span>';
2643  }
2644  return $wrappedText;
2645  }
2646 
2660  static public function cshItem($table, $field, $BACK_PATH, $wrap = '', $onlyIconMode = FALSE, $styleAttrib = '') {
2661  if (!$GLOBALS['BE_USER']->uc['edit_showFieldHelp']) {
2662  return '';
2663  }
2664  $GLOBALS['LANG']->loadSingleTableDescription($table);
2665  if (is_array($GLOBALS['TCA_DESCR'][$table])) {
2666  // Creating CSH icon and short description:
2667  $output = self::helpTextIcon($table, $field, $BACK_PATH);
2668  if ($output && $wrap) {
2669  $wrParts = explode('|', $wrap);
2670  $output = $wrParts[0] . $output . $wrParts[1];
2671  }
2672  return $output;
2673  }
2674  }
2675 
2686  static public function editOnClick($params, $backPath = '', $requestUri = '') {
2687  $retUrl = 'returnUrl=' . ($requestUri == -1 ? '\'+T3_THIS_LOCATION+\'' : rawurlencode(($requestUri ? $requestUri : GeneralUtility::getIndpEnv('REQUEST_URI'))));
2688  return 'window.location.href=\'' . $backPath . 'alt_doc.php?' . $retUrl . $params . '\'; return false;';
2689  }
2690 
2705  static public function viewOnClick($pageUid, $backPath = '', $rootLine = '', $anchorSection = '', $alternativeUrl = '', $additionalGetVars = '', $switchFocus = TRUE) {
2706  $viewScript = '/index.php?id=';
2707  if ($alternativeUrl) {
2708  $viewScript = $alternativeUrl;
2709  }
2710 
2711  if (
2712  isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['viewOnClickClass'])
2713  && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['viewOnClickClass'])
2714  ) {
2715  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['viewOnClickClass'] as $funcRef) {
2716  $hookObj = GeneralUtility::getUserObj($funcRef);
2717  if (method_exists($hookObj, 'preProcess')) {
2718  $hookObj->preProcess($pageUid, $backPath, $rootLine, $anchorSection, $viewScript, $additionalGetVars, $switchFocus);
2719  }
2720  }
2721  }
2722 
2723  if ($alternativeUrl) {
2724  $previewUrl = $viewScript;
2725  } else {
2726  $previewUrl = self::createPreviewUrl($pageUid, $rootLine, $anchorSection, $additionalGetVars, $viewScript);
2727  }
2728 
2729  $onclickCode = 'var previewWin = window.open(\'' . $previewUrl . '\',\'newTYPO3frontendWindow\');' . ($switchFocus ? 'previewWin.focus();' : '');
2730  return $onclickCode;
2731  }
2732 
2744  static protected function createPreviewUrl($pageUid, $rootLine, $anchorSection, $additionalGetVars, $viewScript) {
2745  // Look if a fixed preview language should be added:
2746  $viewLanguageOrder = $GLOBALS['BE_USER']->getTSConfigVal('options.view.languageOrder');
2747 
2748  if (strlen($viewLanguageOrder) > 0) {
2749  $suffix = '';
2750  // Find allowed languages (if none, all are allowed!)
2751  if (!$GLOBALS['BE_USER']->user['admin'] && strlen($GLOBALS['BE_USER']->groupData['allowed_languages'])) {
2752  $allowedLanguages = array_flip(explode(',', $GLOBALS['BE_USER']->groupData['allowed_languages']));
2753  }
2754  // Traverse the view order, match first occurence:
2755  $languageOrder = GeneralUtility::intExplode(',', $viewLanguageOrder);
2756  foreach ($languageOrder as $langUid) {
2757  if (is_array($allowedLanguages) && count($allowedLanguages)) {
2758  // Choose if set.
2759  if (isset($allowedLanguages[$langUid])) {
2760  $suffix = '&L=' . $langUid;
2761  break;
2762  }
2763  } else {
2764  // All allowed since no lang. are listed.
2765  $suffix = '&L=' . $langUid;
2766  break;
2767  }
2768  }
2769  // Add it
2770  $additionalGetVars .= $suffix;
2771  }
2772 
2773  // Check a mount point needs to be previewed
2774  $sys_page = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
2775  $sys_page->init(FALSE);
2776  $mountPointInfo = $sys_page->getMountPointInfo($pageUid);
2777 
2778  if ($mountPointInfo && $mountPointInfo['overlay']) {
2779  $pageUid = $mountPointInfo['mount_pid'];
2780  $additionalGetVars .= '&MP=' . $mountPointInfo['MPvar'];
2781  }
2782  $viewDomain = self::getViewDomain($pageUid, $rootLine);
2783 
2784  return $viewDomain . $viewScript . $pageUid . $additionalGetVars . $anchorSection;
2785  }
2786 
2796  static public function getViewDomain($pageId, $rootLine = NULL) {
2797  $domain = rtrim(GeneralUtility::getIndpEnv('TYPO3_SITE_URL'), '/');
2798  if (!is_array($rootLine)) {
2799  $rootLine = self::BEgetRootLine($pageId);
2800  }
2801  // Checks alternate domains
2802  if (count($rootLine) > 0) {
2803  $urlParts = parse_url($domain);
2805  $sysPage = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
2806  $page = (array) $sysPage->getPage($pageId);
2807  $protocol = 'http';
2808  if ($page['url_scheme'] == \TYPO3\CMS\Core\Utility\HttpUtility::SCHEME_HTTPS || $page['url_scheme'] == 0 && GeneralUtility::getIndpEnv('TYPO3_SSL')) {
2809  $protocol = 'https';
2810  }
2811  $previewDomainConfig = $GLOBALS['BE_USER']->getTSConfig('TCEMAIN.previewDomain', self::getPagesTSconfig($pageId));
2812  if ($previewDomainConfig['value']) {
2813  if (strpos($previewDomainConfig['value'], '://') !== FALSE) {
2814  list($protocol, $domainName) = explode('://', $previewDomainConfig['value']);
2815  } else {
2816  $domainName = $previewDomainConfig['value'];
2817  }
2818  } else {
2819  $domainName = self::firstDomainRecord($rootLine);
2820  }
2821  if ($domainName) {
2822  $domain = $domainName;
2823  } else {
2824  $domainRecord = self::getDomainStartPage($urlParts['host'], $urlParts['path']);
2825  $domain = $domainRecord['domainName'];
2826  }
2827  if ($domain) {
2828  $domain = $protocol . '://' . $domain;
2829  } else {
2830  $domain = rtrim(GeneralUtility::getIndpEnv('TYPO3_SITE_URL'), '/');
2831  }
2832  // Append port number if lockSSLPort is not the standard port 443
2833  $portNumber = (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSLPort'];
2834  if ($portNumber > 0 && $portNumber !== 443 && $portNumber < 65536 && $protocol === 'https') {
2835  $domain .= ':' . strval($portNumber);
2836  }
2837  }
2838  return $domain;
2839  }
2840 
2849  static public function getModTSconfig($id, $TSref) {
2850  $pageTS_modOptions = $GLOBALS['BE_USER']->getTSConfig($TSref, static::getPagesTSconfig($id));
2851  $BE_USER_modOptions = $GLOBALS['BE_USER']->getTSConfig($TSref);
2852  if (is_null($BE_USER_modOptions['value'])) {
2853  unset($BE_USER_modOptions['value']);
2854  }
2855  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($pageTS_modOptions, $BE_USER_modOptions);
2856  return $pageTS_modOptions;
2857  }
2858 
2872  static public function getFuncMenu($mainParams, $elementName, $currentValue, $menuItems, $script = '', $addparams = '') {
2873  if (!is_array($menuItems) || count($menuItems) <= 1) {
2874  return '';
2875  }
2876  $scriptUrl = self::buildScriptUrl($mainParams, $addparams, $script);
2877  $options = array();
2878  foreach ($menuItems as $value => $label) {
2879  $options[] = '<option value="' . htmlspecialchars($value) . '"' . ((string)$currentValue === (string)$value ? ' selected="selected"' : '') . '>' . htmlspecialchars($label, ENT_COMPAT, 'UTF-8', FALSE) . '</option>';
2880  }
2881  if (count($options)) {
2882  $onChange = 'jumpToUrl(' . GeneralUtility::quoteJSvalue($scriptUrl . '&' . $elementName . '=') . '+this.options[this.selectedIndex].value,this);';
2883  return '
2884 
2885  <!-- Function Menu of module -->
2886  <select name="' . $elementName . '" onchange="' . htmlspecialchars($onChange) . '">
2887  ' . implode('
2888  ', $options) . '
2889  </select>
2890  ';
2891  }
2892  }
2893 
2907  static public function getFuncCheck($mainParams, $elementName, $currentValue, $script = '', $addParams = '', $tagParams = '') {
2908  $scriptUrl = self::buildScriptUrl($mainParams, $addParams, $script);
2909  $onClick = 'jumpToUrl(' . GeneralUtility::quoteJSvalue($scriptUrl . '&' . $elementName . '=') . '+(this.checked?1:0),this);';
2910 
2911  return
2912  '<input' .
2913  ' type="checkbox"' .
2914  ' class="checkbox"' .
2915  ' name="' . $elementName . '"' .
2916  ($currentValue ? ' checked="checked"' : '') .
2917  ' onclick="' . htmlspecialchars($onClick) . '"' .
2918  ($tagParams ? ' ' . $tagParams : '') .
2919  ' value="1"' .
2920  ' />';
2921  }
2922 
2936  static public function getFuncInput($mainParams, $elementName, $currentValue, $size = 10, $script = '', $addParams = '') {
2937  $scriptUrl = self::buildScriptUrl($mainParams, $addParams, $script);
2938  $onChange = 'jumpToUrl(' . GeneralUtility::quoteJSvalue($scriptUrl . '&' . $elementName . '=') . '+escape(this.value),this);';
2939  return '<input type="text"' . $GLOBALS['TBE_TEMPLATE']->formWidth($size) . ' name="' . $elementName . '" value="' . htmlspecialchars($currentValue) . '" onchange="' . htmlspecialchars($onChange) . '" />';
2940  }
2941 
2950  protected static function buildScriptUrl($mainParams, $addParams, $script = '') {
2951  if (!is_array($mainParams)) {
2952  $mainParams = array('id' => $mainParams);
2953  }
2954  if (!$script) {
2955  $script = basename(PATH_thisScript);
2956  }
2957  if ($script === 'mod.php' && GeneralUtility::_GET('M')) {
2958  $scriptUrl = self::getModuleUrl(GeneralUtility::_GET('M'), $mainParams) . $addParams;
2959  } else {
2960  $scriptUrl = $script . '?' . GeneralUtility::implodeArrayForUrl('', $mainParams) . $addParams;
2961  }
2962 
2963  return $scriptUrl;
2964  }
2965 
2975  static public function unsetMenuItems($modTSconfig, $itemArray, $TSref) {
2976  // Getting TS-config options for this module for the Backend User:
2977  $conf = $GLOBALS['BE_USER']->getTSConfig($TSref, $modTSconfig);
2978  if (is_array($conf['properties'])) {
2979  foreach ($conf['properties'] as $key => $val) {
2980  if (!$val) {
2981  unset($itemArray[$key]);
2982  }
2983  }
2984  }
2985  return $itemArray;
2986  }
2987 
2997  static public function setUpdateSignal($set = '', $params = '') {
2998  $modData = $GLOBALS['BE_USER']->getModuleData('TYPO3\\CMS\\Backend\\Utility\\BackendUtility::getUpdateSignal', 'ses');
2999  if ($set) {
3000  $modData[$set] = array(
3001  'set' => $set,
3002  'parameter' => $params
3003  );
3004  } else {
3005  // clear the module data
3006  $modData = array();
3007  }
3008  $GLOBALS['BE_USER']->pushModuleData('TYPO3\\CMS\\Backend\\Utility\\BackendUtility::getUpdateSignal', $modData);
3009  }
3010 
3019  static public function getUpdateSignalCode() {
3020  $signals = array();
3021  $modData = $GLOBALS['BE_USER']->getModuleData('TYPO3\\CMS\\Backend\\Utility\\BackendUtility::getUpdateSignal', 'ses');
3022  if (!count($modData)) {
3023  return '';
3024  }
3025  // Hook: Allows to let TYPO3 execute your JS code
3026  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['updateSignalHook'])) {
3027  $updateSignals = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['updateSignalHook'];
3028  } else {
3029  $updateSignals = array();
3030  }
3031  // Loop through all setUpdateSignals and get the JS code
3032  foreach ($modData as $set => $val) {
3033  if (isset($updateSignals[$set])) {
3034  $params = array('set' => $set, 'parameter' => $val['parameter'], 'JScode' => '');
3035  $ref = NULL;
3036  GeneralUtility::callUserFunction($updateSignals[$set], $params, $ref);
3037  $signals[] = $params['JScode'];
3038  } else {
3039  switch ($set) {
3040  case 'updatePageTree':
3041  $signals[] = '
3042  if (top && top.TYPO3.Backend.NavigationContainer.PageTree) {
3043  top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
3044  }
3045  ';
3046  break;
3047  case 'updateFolderTree':
3048  $signals[] = '
3049  if (top && top.TYPO3.Backend.NavigationIframe) {
3050  top.TYPO3.Backend.NavigationIframe.refresh();
3051  }';
3052  break;
3053  case 'updateModuleMenu':
3054  $signals[] = '
3055  if (top && top.TYPO3.ModuleMenu.App) {
3056  top.TYPO3.ModuleMenu.App.refreshMenu();
3057  }';
3058  }
3059  }
3060  }
3061  $content = implode(LF, $signals);
3062  // For backwards compatibility, should be replaced
3063  self::setUpdateSignal();
3064  return $content;
3065  }
3066 
3081  static public function getModuleData($MOD_MENU, $CHANGED_SETTINGS, $modName, $type = '', $dontValidateList = '', $setDefaultList = '') {
3082  if ($modName && is_string($modName)) {
3083  // Getting stored user-data from this module:
3084  $settings = $GLOBALS['BE_USER']->getModuleData($modName, $type);
3085  $changed = 0;
3086  if (!is_array($settings)) {
3087  $changed = 1;
3088  $settings = array();
3089  }
3090  if (is_array($MOD_MENU)) {
3091  foreach ($MOD_MENU as $key => $var) {
3092  // If a global var is set before entering here. eg if submitted, then it's substituting the current value the array.
3093  if (is_array($CHANGED_SETTINGS) && isset($CHANGED_SETTINGS[$key])) {
3094  if (is_array($CHANGED_SETTINGS[$key])) {
3095  $serializedSettings = serialize($CHANGED_SETTINGS[$key]);
3096  if ((string)$settings[$key] !== $serializedSettings) {
3097  $settings[$key] = $serializedSettings;
3098  $changed = 1;
3099  }
3100  } else {
3101  if ((string)$settings[$key] !== (string)$CHANGED_SETTINGS[$key]) {
3102  $settings[$key] = $CHANGED_SETTINGS[$key];
3103  $changed = 1;
3104  }
3105  }
3106  }
3107  // If the $var is an array, which denotes the existence of a menu, we check if the value is permitted
3108  if (is_array($var) && (!$dontValidateList || !GeneralUtility::inList($dontValidateList, $key))) {
3109  // If the setting is an array or not present in the menu-array, MOD_MENU, then the default value is inserted.
3110  if (is_array($settings[$key]) || !isset($MOD_MENU[$key][$settings[$key]])) {
3111  $settings[$key] = (string) key($var);
3112  $changed = 1;
3113  }
3114  }
3115  // Sets default values (only strings/checkboxes, not menus)
3116  if ($setDefaultList && !is_array($var)) {
3117  if (GeneralUtility::inList($setDefaultList, $key) && !isset($settings[$key])) {
3118  $settings[$key] = (string) $var;
3119  }
3120  }
3121  }
3122  } else {
3123  die('No menu!');
3124  }
3125  if ($changed) {
3126  $GLOBALS['BE_USER']->pushModuleData($modName, $settings);
3127  }
3128  return $settings;
3129  } else {
3130  die('Wrong module name: "' . $modName . '"');
3131  }
3132  }
3133 
3143  static public function getModuleUrl($moduleName, $urlParameters = array(), $backPathOverride = FALSE, $returnAbsoluteUrl = FALSE) {
3144  if ($backPathOverride === FALSE) {
3145  $backPath = isset($GLOBALS['BACK_PATH']) ? $GLOBALS['BACK_PATH'] : '';
3146  } else {
3147  $backPath = $backPathOverride;
3148  }
3149  $urlParameters = array(
3150  'M' => $moduleName,
3151  'moduleToken' => \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get()->generateToken('moduleCall', $moduleName)
3152  ) + $urlParameters;
3153  $url = 'mod.php?' . ltrim(GeneralUtility::implodeArrayForUrl('', $urlParameters, '', TRUE, TRUE), '&');
3154  if ($returnAbsoluteUrl) {
3155  return GeneralUtility::getIndpEnv('TYPO3_REQUEST_DIR') . $url;
3156  } else {
3157  return $backPath . $url;
3158  }
3159  }
3160 
3174  static public function getAjaxUrl($ajaxIdentifier, array $urlParameters = array(), $backPathOverride = FALSE, $returnAbsoluteUrl = FALSE) {
3175  if ($backPathOverride) {
3176  $backPath = $backPathOverride;
3177  } else {
3178  $backPath = isset($GLOBALS['BACK_PATH']) ? $GLOBALS['BACK_PATH'] : '';
3179  }
3180  $additionalUrlParameters = array(
3181  'ajaxID' => $ajaxIdentifier
3182  );
3183  if (!empty($GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'][$ajaxIdentifier]['csrfTokenCheck'])) {
3184  $additionalUrlParameters['ajaxToken'] = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get()->generateToken('ajaxCall', $ajaxIdentifier);
3185  }
3186  $url = 'ajax.php?' . ltrim(GeneralUtility::implodeArrayForUrl('', ($additionalUrlParameters + $urlParameters), '', TRUE, TRUE), '&');
3187  if ($returnAbsoluteUrl) {
3188  return GeneralUtility::getIndpEnv('TYPO3_REQUEST_DIR') . $url;
3189  } else {
3190  return $backPath . $url;
3191  }
3192  }
3193 
3202  static public function getListViewLink($urlParameters = array(), $linkTitle = '', $linkText = '') {
3203  $url = self::getModuleUrl('web_list', $urlParameters);
3204  if ($url === FALSE) {
3205  return '';
3206  } else {
3207  return '<a href="' . htmlspecialchars($url) . '" title="' . htmlspecialchars($linkTitle) . '">' . IconUtility::getSpriteIcon('actions-system-list-open') . htmlspecialchars($linkText) . '</a>';
3208  }
3209  }
3210 
3218  static public function getUrlToken($formName = 'securityToken', $tokenName = 'formToken') {
3220  return '&' . $tokenName . '=' . $formprotection->generateToken($formName);
3221  }
3222 
3223  /*******************************************
3224  *
3225  * Core
3226  *
3227  *******************************************/
3238  static public function lockRecords($table = '', $uid = 0, $pid = 0) {
3239  if (isset($GLOBALS['BE_USER']->user['uid'])) {
3240  $user_id = (int)$GLOBALS['BE_USER']->user['uid'];
3241  if ($table && $uid) {
3242  $fields_values = array(
3243  'userid' => $user_id,
3244  'feuserid' => 0,
3245  'tstamp' => $GLOBALS['EXEC_TIME'],
3246  'record_table' => $table,
3247  'record_uid' => $uid,
3248  'username' => $GLOBALS['BE_USER']->user['username'],
3249  'record_pid' => $pid
3250  );
3251  $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_lockedrecords', $fields_values);
3252  } else {
3253  $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_lockedrecords', 'userid=' . (int)$user_id);
3254  }
3255  }
3256  }
3257 
3268  static public function isRecordLocked($table, $uid) {
3269  if (!is_array($GLOBALS['LOCKED_RECORDS'])) {
3270  $GLOBALS['LOCKED_RECORDS'] = array();
3271  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_lockedrecords', 'sys_lockedrecords.userid<>' . (int)$GLOBALS['BE_USER']->user['uid'] . '
3272  AND sys_lockedrecords.tstamp > ' . ($GLOBALS['EXEC_TIME'] - 2 * 3600));
3273  while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
3274  // Get the type of the user that locked this record:
3275  if ($row['userid']) {
3276  $userTypeLabel = 'beUser';
3277  } elseif ($row['feuserid']) {
3278  $userTypeLabel = 'feUser';
3279  } else {
3280  $userTypeLabel = 'user';
3281  }
3282  $userType = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.' . $userTypeLabel);
3283  // Get the username (if available):
3284  if ($row['username']) {
3285  $userName = $row['username'];
3286  } else {
3287  $userName = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.unknownUser');
3288  }
3289  $GLOBALS['LOCKED_RECORDS'][$row['record_table'] . ':' . $row['record_uid']] = $row;
3290  $GLOBALS['LOCKED_RECORDS'][$row['record_table'] . ':' . $row['record_uid']]['msg'] = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.lockedRecordUser'), $userType, $userName, self::calcAge($GLOBALS['EXEC_TIME'] - $row['tstamp'], $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysYears')));
3291  if ($row['record_pid'] && !isset($GLOBALS['LOCKED_RECORDS'][($row['record_table'] . ':' . $row['record_pid'])])) {
3292  $GLOBALS['LOCKED_RECORDS']['pages:' . $row['record_pid']]['msg'] = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.lockedRecordUser_content'), $userType, $userName, self::calcAge($GLOBALS['EXEC_TIME'] - $row['tstamp'], $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysYears')));
3293  }
3294  }
3295  $GLOBALS['TYPO3_DB']->sql_free_result($res);
3296  }
3297  return $GLOBALS['LOCKED_RECORDS'][$table . ':' . $uid];
3298  }
3299 
3310  static public function exec_foreign_table_where_query($fieldValue, $field = '', $TSconfig = array(), $prefix = '') {
3311  $foreign_table = $fieldValue['config'][$prefix . 'foreign_table'];
3312  $rootLevel = $GLOBALS['TCA'][$foreign_table]['ctrl']['rootLevel'];
3313  $fTWHERE = $fieldValue['config'][$prefix . 'foreign_table_where'];
3314  $fTWHERE = static::replaceMarkersInWhereClause($fTWHERE, $foreign_table, $field, $TSconfig);
3315  $wgolParts = $GLOBALS['TYPO3_DB']->splitGroupOrderLimit($fTWHERE);
3316  // rootLevel = -1 means that elements can be on the rootlevel OR on any page (pid!=-1)
3317  // rootLevel = 0 means that elements are not allowed on root level
3318  // rootLevel = 1 means that elements are only on the root level (pid=0)
3319  if ($rootLevel == 1 || $rootLevel == -1) {
3320  $pidWhere = $foreign_table . '.pid' . (($rootLevel == -1) ? '<>-1' : '=0');
3321  $queryParts = array(
3322  'SELECT' => self::getCommonSelectFields($foreign_table, $foreign_table . '.'),
3323  'FROM' => $foreign_table,
3324  'WHERE' => $pidWhere . ' ' . self::deleteClause($foreign_table) . ' ' . $wgolParts['WHERE'],
3325  'GROUPBY' => $wgolParts['GROUPBY'],
3326  'ORDERBY' => $wgolParts['ORDERBY'],
3327  'LIMIT' => $wgolParts['LIMIT']
3328  );
3329  } else {
3330  $pageClause = $GLOBALS['BE_USER']->getPagePermsClause(1);
3331  if ($foreign_table != 'pages') {
3332  $queryParts = array(
3333  'SELECT' => self::getCommonSelectFields($foreign_table, $foreign_table . '.'),
3334  'FROM' => $foreign_table . ', pages',
3335  'WHERE' => 'pages.uid=' . $foreign_table . '.pid
3336  AND pages.deleted=0 ' . self::deleteClause($foreign_table) . ' AND ' . $pageClause . ' ' . $wgolParts['WHERE'],
3337  'GROUPBY' => $wgolParts['GROUPBY'],
3338  'ORDERBY' => $wgolParts['ORDERBY'],
3339  'LIMIT' => $wgolParts['LIMIT']
3340  );
3341  } else {
3342  $queryParts = array(
3343  'SELECT' => self::getCommonSelectFields($foreign_table, $foreign_table . '.'),
3344  'FROM' => 'pages',
3345  'WHERE' => 'pages.deleted=0
3346  AND ' . $pageClause . ' ' . $wgolParts['WHERE'],
3347  'GROUPBY' => $wgolParts['GROUPBY'],
3348  'ORDERBY' => $wgolParts['ORDERBY'],
3349  'LIMIT' => $wgolParts['LIMIT']
3350  );
3351  }
3352  }
3353  return $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts);
3354  }
3355 
3375  static public function replaceMarkersInWhereClause($whereClause, $table, $field = '', $tsConfig = array()) {
3376  if (strstr($whereClause, '###REC_FIELD_')) {
3377  $whereClauseParts = explode('###REC_FIELD_', $whereClause);
3378  foreach ($whereClauseParts as $key => $value) {
3379  if ($key) {
3380  $whereClauseSubarts = explode('###', $value, 2);
3381  if (substr($whereClauseParts[0], -1) === '\'' && $whereClauseSubarts[1][0] === '\'') {
3382  $whereClauseParts[$key] = $GLOBALS['TYPO3_DB']->quoteStr($tsConfig['_THIS_ROW'][$whereClauseSubarts[0]], $table) . $whereClauseSubarts[1];
3383  } else {
3384  $whereClauseParts[$key] = $GLOBALS['TYPO3_DB']->fullQuoteStr($tsConfig['_THIS_ROW'][$whereClauseSubarts[0]], $table) . $whereClauseSubarts[1];
3385  }
3386  }
3387  }
3388  $whereClause = implode('', $whereClauseParts);
3389  }
3390  return str_replace (
3391  array (
3392  '###CURRENT_PID###',
3393  '###THIS_UID###',
3394  '###THIS_CID###',
3395  '###STORAGE_PID###',
3396  '###SITEROOT###',
3397  '###PAGE_TSCONFIG_ID###',
3398  '###PAGE_TSCONFIG_IDLIST###',
3399  '###PAGE_TSCONFIG_STR###'
3400  ),
3401  array(
3402  (int)$tsConfig['_CURRENT_PID'],
3403  (int)$tsConfig['_THIS_UID'],
3404  (int)$tsConfig['_THIS_CID'],
3405  (int)$tsConfig['_STORAGE_PID'],
3406  (int)$tsConfig['_SITEROOT'],
3407  (int)$tsConfig[$field]['PAGE_TSCONFIG_ID'],
3408  $GLOBALS['TYPO3_DB']->cleanIntList($tsConfig[$field]['PAGE_TSCONFIG_IDLIST']),
3409  $GLOBALS['TYPO3_DB']->quoteStr($tsConfig[$field]['PAGE_TSCONFIG_STR'], $table)
3410  ),
3411  $whereClause
3412  );
3413  }
3414 
3423  static public function getTCEFORM_TSconfig($table, $row) {
3424  self::fixVersioningPid($table, $row);
3425  $res = array();
3426  $typeVal = self::getTCAtypeValue($table, $row);
3427  // Get main config for the table
3428  list($TScID, $cPid) = self::getTSCpid($table, $row['uid'], $row['pid']);
3429  if ($TScID >= 0) {
3430  $tempConf = $GLOBALS['BE_USER']->getTSConfig('TCEFORM.' . $table, self::getPagesTSconfig($TScID));
3431  if (is_array($tempConf['properties'])) {
3432  foreach ($tempConf['properties'] as $key => $val) {
3433  if (is_array($val)) {
3434  $fieldN = substr($key, 0, -1);
3435  $res[$fieldN] = $val;
3436  unset($res[$fieldN]['types.']);
3437  if ((string)$typeVal !== '' && is_array($val['types.'][$typeVal . '.'])) {
3438  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($res[$fieldN], $val['types.'][$typeVal . '.']);
3439  }
3440  }
3441  }
3442  }
3443  }
3444  $res['_CURRENT_PID'] = $cPid;
3445  $res['_THIS_UID'] = $row['uid'];
3446  $res['_THIS_CID'] = $row['cid'];
3447  // So the row will be passed to foreign_table_where_query()
3448  $res['_THIS_ROW'] = $row;
3449  $rootLine = self::BEgetRootLine($TScID, '', TRUE);
3450  foreach ($rootLine as $rC) {
3451  if (!$res['_STORAGE_PID']) {
3452  $res['_STORAGE_PID'] = (int)$rC['storage_pid'];
3453  }
3454  if (!$res['_SITEROOT']) {
3455  $res['_SITEROOT'] = $rC['is_siteroot'] ? (int)$rC['uid'] : 0;
3456  }
3457  }
3458  return $res;
3459  }
3460 
3474  static public function getTSconfig_pidValue($table, $uid, $pid) {
3475  // If pid is an integer this takes precedence in our lookup.
3477  $thePidValue = (int)$pid;
3478  // If ref to another record, look that record up.
3479  if ($thePidValue < 0) {
3480  $pidRec = self::getRecord($table, abs($thePidValue), 'pid');
3481  $thePidValue = is_array($pidRec) ? $pidRec['pid'] : -2;
3482  }
3483  } else {
3484  // Try to fetch the record pid from uid. If the uid is 'NEW...' then this will of course return nothing
3485  $rr = self::getRecord($table, $uid);
3486  if (is_array($rr)) {
3487  // First check if the pid is -1 which means it is a workspaced element. Get the "real" record:
3488  if ($rr['pid'] == '-1') {
3489  $rr = self::getRecord($table, $rr['t3ver_oid'], 'pid');
3490  if (is_array($rr)) {
3491  $thePidValue = $rr['pid'];
3492  }
3493  } else {
3494  // Returning the "pid" of the record
3495  $thePidValue = $rr['pid'];
3496  }
3497  }
3498  if (!$thePidValue) {
3499  // Returns -1 if the record with this pid was not found.
3500  $thePidValue = -1;
3501  }
3502  }
3503  return $thePidValue;
3504  }
3505 
3516  static public function getPidForModTSconfig($table, $uid, $pid) {
3517  $retVal = $table == 'pages' && MathUtility::canBeInterpretedAsInteger($uid) ? $uid : $pid;
3518  return $retVal;
3519  }
3520 
3531  static public function getTSCpid($table, $uid, $pid) {
3532  // If pid is negative (referring to another record) the pid of the other record is fetched and returned.
3533  $cPid = self::getTSconfig_pidValue($table, $uid, $pid);
3534  // $TScID is the id of $table = pages, else it's the pid of the record.
3535  $TScID = self::getPidForModTSconfig($table, $uid, $cPid);
3536  return array($TScID, $cPid);
3537  }
3538 
3545  static public function firstDomainRecord($rootLine) {
3546  foreach ($rootLine as $row) {
3547  $dRec = self::getRecordsByField('sys_domain', 'pid', $row['uid'], ' AND redirectTo=\'\' AND hidden=0', '', 'sorting');
3548  if (is_array($dRec)) {
3549  $dRecord = reset($dRec);
3550  return rtrim($dRecord['domainName'], '/');
3551  }
3552  }
3553  return NULL;
3554  }
3555 
3563  static public function getDomainStartPage($domain, $path = '') {
3564  $domain = explode(':', $domain);
3565  $domain = strtolower(preg_replace('/\\.$/', '', $domain[0]));
3566  // Path is calculated.
3567  $path = trim(preg_replace('/\\/[^\\/]*$/', '', $path));
3568  // Stuff
3569  $domain .= $path;
3570  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('sys_domain.*', 'pages,sys_domain', '
3571  pages.uid=sys_domain.pid
3572  AND sys_domain.hidden=0
3573  AND (sys_domain.domainName=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($domain, 'sys_domain') . ' OR sys_domain.domainName=' . $GLOBALS['TYPO3_DB']->fullQuoteStr(($domain . '/'), 'sys_domain') . ')' . self::deleteClause('pages'), '', '', '1');
3574  $result = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
3575  $GLOBALS['TYPO3_DB']->sql_free_result($res);
3576  return $result;
3577  }
3578 
3589  static public function RTEsetup($RTEprop, $table, $field, $type = '') {
3590  $thisConfig = is_array($RTEprop['default.']) ? $RTEprop['default.'] : array();
3591  $thisFieldConf = $RTEprop['config.'][$table . '.'][$field . '.'];
3592  if (is_array($thisFieldConf)) {
3593  unset($thisFieldConf['types.']);
3595  }
3596  if ($type && is_array($RTEprop['config.'][$table . '.'][$field . '.']['types.'][$type . '.'])) {
3597  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($thisConfig, $RTEprop['config.'][$table . '.'][$field . '.']['types.'][$type . '.']);
3598  }
3599  return $thisConfig;
3600  }
3601 
3608  static public function &RTEgetObj() {
3609  // If no RTE object has been set previously, try to create it:
3610  if (!isset($GLOBALS['T3_VAR']['RTEobj'])) {
3611  // Set the object string to blank by default:
3612  $GLOBALS['T3_VAR']['RTEobj'] = array();
3613  // Traverse registered RTEs:
3614  if (is_array($GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_reg'])) {
3615  foreach ($GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_reg'] as $extKey => $rteObjCfg) {
3616  $rteObj = GeneralUtility::getUserObj($rteObjCfg['objRef']);
3617  if (is_object($rteObj)) {
3618  if ($rteObj->isAvailable()) {
3619  $GLOBALS['T3_VAR']['RTEobj'] = $rteObj;
3620  break;
3621  } else {
3622  $GLOBALS['T3_VAR']['RTEobj'] = array_merge($GLOBALS['T3_VAR']['RTEobj'], $rteObj->errorLog);
3623  }
3624  }
3625  }
3626  }
3627  if (!count($GLOBALS['T3_VAR']['RTEobj'])) {
3628  $GLOBALS['T3_VAR']['RTEobj'][] = 'No RTEs configured at all';
3629  }
3630  }
3631  // Return RTE object (if any!)
3632  return $GLOBALS['T3_VAR']['RTEobj'];
3633  }
3634 
3642  static public function &softRefParserObj($spKey) {
3643  // If no softRef parser object has been set previously, try to create it:
3644  if (!isset($GLOBALS['T3_VAR']['softRefParser'][$spKey])) {
3645  // Set the object string to blank by default:
3646  $GLOBALS['T3_VAR']['softRefParser'][$spKey] = '';
3647  // Now, try to create parser object:
3648  $objRef = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser'][$spKey]
3649  ? $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser'][$spKey]
3650  : $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser_GL'][$spKey];
3651  if ($objRef) {
3652  $softRefParserObj = GeneralUtility::getUserObj($objRef, '');
3653  if (is_object($softRefParserObj)) {
3654  $GLOBALS['T3_VAR']['softRefParser'][$spKey] = $softRefParserObj;
3655  }
3656  }
3657  }
3658  // Return RTE object (if any!)
3659  return $GLOBALS['T3_VAR']['softRefParser'][$spKey];
3660  }
3661 
3667  static protected function getRuntimeCache() {
3668  return GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager')->getCache('cache_runtime');
3669  }
3670 
3677  static public function explodeSoftRefParserList($parserList) {
3678  $runtimeCache = self::getRuntimeCache();
3679  $cacheId = 'backend-softRefList-' . md5($parserList);
3680  if ($runtimeCache->has($cacheId)) {
3681  return $runtimeCache->get($cacheId);
3682  }
3683 
3684  // Looking for global parsers:
3685  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser_GL']) && !empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser_GL'])) {
3686  $parserList = implode(',', array_keys($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser_GL'])) . ',' . $parserList;
3687  }
3688 
3689  // Return immediately if list is blank:
3690  if ($parserList === '') {
3691  $runtimeCache->set($cacheId, FALSE);
3692  return FALSE;
3693  }
3694 
3695  // Otherwise parse the list:
3696  $keyList = GeneralUtility::trimExplode(',', $parserList, TRUE);
3697  $output = array();
3698  foreach ($keyList as $val) {
3699  $reg = array();
3700  if (preg_match('/^([[:alnum:]_-]+)\\[(.*)\\]$/', $val, $reg)) {
3701  $output[$reg[1]] = GeneralUtility::trimExplode(';', $reg[2], TRUE);
3702  } else {
3703  $output[$val] = '';
3704  }
3705  }
3706  $runtimeCache->set($cacheId, $output);
3707  return $output;
3708  }
3709 
3716  static public function isModuleSetInTBE_MODULES($modName) {
3717  $loaded = array();
3718  foreach ($GLOBALS['TBE_MODULES'] as $mkey => $list) {
3719  $loaded[$mkey] = 1;
3720  if (!is_array($list) && trim($list)) {
3721  $subList = GeneralUtility::trimExplode(',', $list, TRUE);
3722  foreach ($subList as $skey) {
3723  $loaded[$mkey . '_' . $skey] = 1;
3724  }
3725  }
3726  }
3727  return $modName && isset($loaded[$modName]);
3728  }
3729 
3739  static public function referenceCount($table, $ref, $msg = '', $count = NULL) {
3740  if ($count === NULL) {
3741  // Look up the path:
3742  if ($table == '_FILE') {
3743  if (GeneralUtility::isFirstPartOfStr($ref, PATH_site)) {
3745  $condition = 'ref_string=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($ref, 'sys_refindex');
3746  } else {
3747  return '';
3748  }
3749  } else {
3750  $condition = 'ref_uid=' . (int)$ref;
3751  if ($table === 'sys_file') {
3752  $condition .= ' AND tablename != ' . $GLOBALS['TYPO3_DB']->fullQuoteStr('sys_file_metadata', $table);
3753  }
3754  }
3755  $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'sys_refindex', 'ref_table=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($table, 'sys_refindex') . ' AND ' . $condition . ' AND deleted=0');
3756  }
3757  return $count ? ($msg ? sprintf($msg, $count) : $count) : '';
3758  }
3759 
3768  static public function translationCount($table, $ref, $msg = '') {
3769  if (empty($GLOBALS['TCA'][$table]['ctrl']['transForeignTable']) && $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] && !$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable']) {
3770  $where = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . '=' . (int)$ref . ' AND ' . $GLOBALS['TCA'][$table]['ctrl']['languageField'] . '<>0';
3771  if (!empty($GLOBALS['TCA'][$table]['ctrl']['delete'])) {
3772  $where .= ' AND ' . $GLOBALS['TCA'][$table]['ctrl']['delete'] . '=0';
3773  }
3774  $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', $table, $where);
3775  }
3776  return $count ? ($msg ? sprintf($msg, $count) : $count) : '';
3777  }
3778 
3779  /*******************************************
3780  *
3781  * Workspaces / Versioning
3782  *
3783  *******************************************/
3795  static public function selectVersionsOfRecord($table, $uid, $fields = '*', $workspace = 0, $includeDeletedRecords = FALSE, $row = NULL) {
3796  $realPid = 0;
3797  $outputRows = array();
3798  if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
3799  if (is_array($row) && !$includeDeletedRecords) {
3800  $row['_CURRENT_VERSION'] = TRUE;
3801  $realPid = $row['pid'];
3802  $outputRows[] = $row;
3803  } else {
3804  // Select UID version:
3805  $row = BackendUtility::getRecord($table, $uid, $fields, '', !$includeDeletedRecords);
3806  // Add rows to output array:
3807  if ($row) {
3808  $row['_CURRENT_VERSION'] = TRUE;
3809  $realPid = $row['pid'];
3810  $outputRows[] = $row;
3811  }
3812  }
3813  $workspaceSqlPart = '';
3814  if ($workspace === 0) {
3815  // Only in Live WS
3816  $workspaceSqlPart = ' AND t3ver_wsid=0';
3817  } elseif ($workspace !== NULL) {
3818  // In Live WS and Workspace with given ID
3819  $workspaceSqlPart = ' AND t3ver_wsid IN (0,' . (int)$workspace . ')';
3820  }
3821  // Select all offline versions of record:
3822  $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
3823  $fields,
3824  $table,
3825  'pid=-1 AND uid<>' . (int)$uid . ' AND t3ver_oid=' . (int)$uid
3826  . $workspaceSqlPart
3827  . ($includeDeletedRecords ? '' : self::deleteClause($table)),
3828  '',
3829  't3ver_id DESC'
3830  );
3831  // Add rows to output array:
3832  if (is_array($rows)) {
3833  $outputRows = array_merge($outputRows, $rows);
3834  }
3835  // Set real-pid:
3836  foreach ($outputRows as $idx => $oRow) {
3837  $outputRows[$idx]['_REAL_PID'] = $realPid;
3838  }
3839  return $outputRows;
3840  }
3841  }
3842 
3856  static public function fixVersioningPid($table, &$rr, $ignoreWorkspaceMatch = FALSE) {
3857  if (ExtensionManagementUtility::isLoaded('version')) {
3858  // Check that the input record is an offline version from a table that supports versioning:
3859  if (is_array($rr) && $rr['pid'] == -1 && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
3860  // Check values for t3ver_oid and t3ver_wsid:
3861  if (isset($rr['t3ver_oid']) && isset($rr['t3ver_wsid'])) {
3862  // If "t3ver_oid" is already a field, just set this:
3863  $oid = $rr['t3ver_oid'];
3864  $wsid = $rr['t3ver_wsid'];
3865  } else {
3866  // Otherwise we have to expect "uid" to be in the record and look up based on this:
3867  $newPidRec = self::getRecord($table, $rr['uid'], 't3ver_oid,t3ver_wsid');
3868  if (is_array($newPidRec)) {
3869  $oid = $newPidRec['t3ver_oid'];
3870  $wsid = $newPidRec['t3ver_wsid'];
3871  }
3872  }
3873  // If ID of current online version is found, look up the PID value of that:
3874  if ($oid && ($ignoreWorkspaceMatch || (int)$wsid === (int)$GLOBALS['BE_USER']->workspace)) {
3875  $oidRec = self::getRecord($table, $oid, 'pid');
3876  if (is_array($oidRec)) {
3877  $rr['_ORIG_pid'] = $rr['pid'];
3878  $rr['pid'] = $oidRec['pid'];
3879  }
3880  }
3881  // Use target PID in case of move pointer
3882  if (
3883  !isset($rr['t3ver_state'])
3884  || VersionState::cast($rr['t3ver_state'])->equals(VersionState::MOVE_POINTER)
3885  ) {
3886  $movePlaceholder = self::getMovePlaceholder($table, $oid, 'pid');
3887  if ($movePlaceholder) {
3888  $rr['_ORIG_pid'] = $rr['pid'];
3889  $rr['pid'] = $movePlaceholder['pid'];
3890  }
3891  }
3892  }
3893  }
3894  }
3895 
3913  static public function workspaceOL($table, &$row, $wsid = -99, $unsetMovePointers = FALSE) {
3914  if (ExtensionManagementUtility::isLoaded('version')) {
3915  // If this is FALSE the placeholder is shown raw in the backend.
3916  // I don't know if this move can be useful for users to toggle. Technically it can help debugging.
3917  $previewMovePlaceholders = TRUE;
3918  // Initialize workspace ID
3919  if ($wsid == -99) {
3920  $wsid = $GLOBALS['BE_USER']->workspace;
3921  }
3922  // Check if workspace is different from zero and record is set:
3923  if ($wsid !== 0 && is_array($row)) {
3924  // Check if input record is a move-placeholder and if so, find the pointed-to live record:
3925  if ($previewMovePlaceholders) {
3926  $orig_uid = $row['uid'];
3927  $orig_pid = $row['pid'];
3928  $movePldSwap = self::movePlhOL($table, $row);
3929  }
3930  $wsAlt = self::getWorkspaceVersionOfRecord($wsid, $table, $row['uid'], implode(',', array_keys($row)));
3931  // If version was found, swap the default record with that one.
3932  if (is_array($wsAlt)) {
3933  // Check if this is in move-state:
3934  if ($previewMovePlaceholders && !$movePldSwap && ($table == 'pages' || (int)$GLOBALS['TCA'][$table]['ctrl']['versioningWS'] >= 2) && $unsetMovePointers) {
3935  // Only for WS ver 2... (moving)
3936  // If t3ver_state is not found, then find it... (but we like best if it is here...)
3937  if (!isset($wsAlt['t3ver_state'])) {
3938  $stateRec = self::getRecord($table, $wsAlt['uid'], 't3ver_state');
3939  $versionState = VersionState::cast($stateRec['t3ver_state']);
3940  } else {
3941  $versionState = VersionState::cast($wsAlt['t3ver_state']);
3942  }
3943  if ($versionState->equals(VersionState::MOVE_POINTER)) {
3944  // TODO: Same problem as frontend in versionOL(). See TODO point there.
3945  $row = FALSE;
3946  return;
3947  }
3948  }
3949  // Always correct PID from -1 to what it should be
3950  if (isset($wsAlt['pid'])) {
3951  // Keep the old (-1) - indicates it was a version.
3952  $wsAlt['_ORIG_pid'] = $wsAlt['pid'];
3953  // Set in the online versions PID.
3954  $wsAlt['pid'] = $row['pid'];
3955  }
3956  // For versions of single elements or page+content, swap UID and PID
3957  $wsAlt['_ORIG_uid'] = $wsAlt['uid'];
3958  $wsAlt['uid'] = $row['uid'];
3959  // Backend css class:
3960  $wsAlt['_CSSCLASS'] = 'ver-element';
3961  // Changing input record to the workspace version alternative:
3962  $row = $wsAlt;
3963  }
3964  // If the original record was a move placeholder, the uid and pid of that is preserved here:
3965  if ($movePldSwap) {
3966  $row['_MOVE_PLH'] = TRUE;
3967  $row['_MOVE_PLH_uid'] = $orig_uid;
3968  $row['_MOVE_PLH_pid'] = $orig_pid;
3969  // For display; To make the icon right for the placeholder vs. the original
3970  $row['t3ver_state'] = (string)new VersionState(VersionState::MOVE_PLACEHOLDER);
3971  }
3972  }
3973  }
3974  }
3975 
3985  static public function movePlhOL($table, &$row) {
3986  // Only for WS ver 2... (moving)
3987  if ($table == 'pages' || (int)$GLOBALS['TCA'][$table]['ctrl']['versioningWS'] >= 2) {
3988  // If t3ver_move_id or t3ver_state is not found, then find it... (but we like best if it is here...)
3989  if (!isset($row['t3ver_move_id']) || !isset($row['t3ver_state'])) {
3990  $moveIDRec = self::getRecord($table, $row['uid'], 't3ver_move_id, t3ver_state');
3991  $moveID = $moveIDRec['t3ver_move_id'];
3992  $versionState = VersionState::cast($moveIDRec['t3ver_state']);
3993  } else {
3994  $moveID = $row['t3ver_move_id'];
3995  $versionState = VersionState::cast($row['t3ver_state']);
3996  }
3997  // Find pointed-to record.
3998  if ($versionState->equals(VersionState::MOVE_PLACEHOLDER) && $moveID) {
3999  if ($origRow = self::getRecord($table, $moveID, implode(',', array_keys($row)))) {
4000  $row = $origRow;
4001  return TRUE;
4002  }
4003  }
4004  }
4005  return FALSE;
4006  }
4007 
4017  static public function getWorkspaceVersionOfRecord($workspace, $table, $uid, $fields = '*') {
4018  if (ExtensionManagementUtility::isLoaded('version')) {
4019  if ($workspace !== 0 && $GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
4020  // Select workspace version of record:
4021  $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow($fields, $table, 'pid=-1 AND ' . 't3ver_oid=' . (int)$uid . ' AND ' . 't3ver_wsid=' . (int)$workspace . self::deleteClause($table));
4022  if (is_array($row)) {
4023  return $row;
4024  }
4025  }
4026  }
4027  return FALSE;
4028  }
4029 
4038  static public function getLiveVersionOfRecord($table, $uid, $fields = '*') {
4039  $liveVersionId = self::getLiveVersionIdOfRecord($table, $uid);
4040  if (is_null($liveVersionId) === FALSE) {
4041  return self::getRecord($table, $liveVersionId, $fields);
4042  }
4043  }
4044 
4052  static public function getLiveVersionIdOfRecord($table, $uid) {
4053  $liveVersionId = NULL;
4054  if (self::isTableWorkspaceEnabled($table)) {
4055  $currentRecord = self::getRecord($table, $uid, 'pid,t3ver_oid');
4056  if (is_array($currentRecord) && $currentRecord['pid'] == -1) {
4057  $liveVersionId = $currentRecord['t3ver_oid'];
4058  }
4059  }
4060  return $liveVersionId;
4061  }
4062 
4070  static public function versioningPlaceholderClause($table) {
4071  if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
4072  $currentWorkspace = (int)$GLOBALS['BE_USER']->workspace;
4073  return ' AND (' . $table . '.t3ver_state <= ' . new VersionState(VersionState::DEFAULT_STATE) . ' OR ' . $table . '.t3ver_wsid = ' . $currentWorkspace . ')';
4074  }
4075  }
4076 
4084  static public function getWorkspaceWhereClause($table, $workspaceId = NULL) {
4085  $whereClause = '';
4086  if (self::isTableWorkspaceEnabled($table)) {
4087  if (is_null($workspaceId)) {
4088  $workspaceId = $GLOBALS['BE_USER']->workspace;
4089  }
4090  $workspaceId = (int)$workspaceId;
4091  $pidOperator = $workspaceId === 0 ? '!=' : '=';
4092  $whereClause = ' AND ' . $table . '.t3ver_wsid=' . $workspaceId . ' AND ' . $table . '.pid' . $pidOperator . '-1';
4093  }
4094  return $whereClause;
4095  }
4096 
4104  static public function countVersionsOfRecordsOnPage($workspace, $pageId) {
4105  $output = array();
4106  if ($workspace != 0) {
4107  foreach ($GLOBALS['TCA'] as $tableName => $cfg) {
4108  if ($tableName != 'pages' && $cfg['ctrl']['versioningWS']) {
4109  $joinStatement = 'A.t3ver_oid=B.uid';
4110  // Consider records that are moved to a different page
4111  if (self::isTableMovePlaceholderAware($tableName)) {
4112  $movePointer = new VersionState(VersionState::MOVE_POINTER);
4113  $joinStatement = '(A.t3ver_oid=B.uid AND A.t3ver_state<>' . $movePointer
4114  . ' OR A.t3ver_oid=B.t3ver_move_id AND A.t3ver_state=' . $movePointer . ')';
4115  }
4116  // Select all records from this table in the database from the workspace
4117  // This joins the online version with the offline version as tables A and B
4118  $output[$tableName] = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
4119  'B.uid as live_uid, A.uid as offline_uid',
4120  $tableName . ' A,' . $tableName . ' B',
4121  'A.pid=-1' . ' AND B.pid=' . (int)$pageId
4122  . ' AND A.t3ver_wsid=' . (int)$workspace . ' AND ' . $joinStatement
4123  . self::deleteClause($tableName, 'A') . self::deleteClause($tableName, 'B')
4124  );
4125  if (!is_array($output[$tableName]) || !count($output[$tableName])) {
4126  unset($output[$tableName]);
4127  }
4128  }
4129  }
4130  }
4131  return $output;
4132  }
4133 
4141  static public function wsMapId($table, $uid) {
4142  if ($wsRec = self::getWorkspaceVersionOfRecord($GLOBALS['BE_USER']->workspace, $table, $uid, 'uid')) {
4143  return $wsRec['uid'];
4144  } else {
4145  return $uid;
4146  }
4147  }
4148 
4158  static public function getMovePlaceholder($table, $uid, $fields = '*', $workspace = NULL) {
4159  if ($workspace === NULL) {
4160  $workspace = $GLOBALS['BE_USER']->workspace;
4161  }
4162  if ((int)$workspace !== 0 && $GLOBALS['TCA'][$table] && (int)$GLOBALS['TCA'][$table]['ctrl']['versioningWS'] >= 2) {
4163  // Select workspace version of record:
4164  $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
4165  $fields,
4166  $table,
4167  'pid<>-1 AND t3ver_state=' . new VersionState(VersionState::MOVE_PLACEHOLDER) . ' AND t3ver_move_id='
4168  . (int)$uid . ' AND t3ver_wsid=' . (int)$workspace . self::deleteClause($table)
4169  );
4170  if (is_array($row)) {
4171  return $row;
4172  }
4173  }
4174  return FALSE;
4175  }
4176 
4177  /*******************************************
4178  *
4179  * Miscellaneous
4180  *
4181  *******************************************/
4193  static public function TYPO3_copyRightNotice($showVersionNumber = TRUE) {
4194  // Copyright Notice
4195  $loginCopyrightWarrantyProvider = strip_tags(trim($GLOBALS['TYPO3_CONF_VARS']['SYS']['loginCopyrightWarrantyProvider']));
4196  $loginCopyrightWarrantyURL = strip_tags(trim($GLOBALS['TYPO3_CONF_VARS']['SYS']['loginCopyrightWarrantyURL']));
4197 
4198  $versionNumber = $showVersionNumber ?
4199  ' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_login.xlf:version.short') . ' ' .
4200  htmlspecialchars(TYPO3_version) : '';
4201 
4202  if (strlen($loginCopyrightWarrantyProvider) >= 2 && strlen($loginCopyrightWarrantyURL) >= 10) {
4203  $warrantyNote = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_login.xlf:warranty.by'), htmlspecialchars($loginCopyrightWarrantyProvider), '<a href="' . htmlspecialchars($loginCopyrightWarrantyURL) . '" target="_blank">', '</a>');
4204  } else {
4205  $warrantyNote = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_login.xlf:no.warranty'), '<a href="' . TYPO3_URL_LICENSE . '" target="_blank">', '</a>');
4206  }
4207  $cNotice = '<a href="' . TYPO3_URL_GENERAL . '" target="_blank">' .
4208  '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/loginlogo_transp.gif', 'width="75" height="24" vspace="2" hspace="4"') . ' alt="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_login.xlf:typo3.logo') . '" align="left" />' .
4209  $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_login.xlf:typo3.cms') . $versionNumber . '</a>. ' .
4210  $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_login.xlf:copyright') . ' &copy; ' . htmlspecialchars(TYPO3_copyright_year) . ' Kasper Sk&aring;rh&oslash;j. ' .
4211  $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_login.xlf:extension.copyright') . ' ' .
4212  sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_login.xlf:details.link'), ('<a href="' . TYPO3_URL_GENERAL . '" target="_blank">' . TYPO3_URL_GENERAL . '</a>')) . ' ' .
4213  strip_tags($warrantyNote, '<a>') . ' ' .
4214  sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_login.xlf:free.software'), ('<a href="' . TYPO3_URL_LICENSE . '" target="_blank">'), '</a> ') .
4215  $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_login.xlf:keep.notice');
4216  return $cNotice;
4217  }
4218 
4227  static public function displayWarningMessages() {
4229  return '';
4230  }
4231 
4238  static public function getPathType_web_nonweb($path) {
4239  return GeneralUtility::isFirstPartOfStr($path, GeneralUtility::getIndpEnv('TYPO3_DOCUMENT_ROOT')) ? 'web' : '';
4240  }
4241 
4249  static public function ADMCMD_previewCmds($pageinfo) {
4250  $simUser = '';
4251  $simTime = '';
4252  if ($pageinfo['fe_group'] > 0) {
4253  $simUser = '&ADMCMD_simUser=' . $pageinfo['fe_group'];
4254  } elseif ((int)$pageinfo['fe_group'] === -2) {
4255  // -2 means "show at any login". We simulate first available fe_group.
4257  $sysPage = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
4258  $activeFeGroupRow = BackendUtility::getRecordRaw('fe_groups', '1=1' . $sysPage->enableFields('fe_groups'), 'uid');
4259  if (!empty($activeFeGroupRow)) {
4260  $simUser = '&ADMCMD_simUser=' . $activeFeGroupRow['uid'];
4261  }
4262  }
4263  if ($pageinfo['starttime'] > $GLOBALS['EXEC_TIME']) {
4264  $simTime = '&ADMCMD_simTime=' . $pageinfo['starttime'];
4265  }
4266  if ($pageinfo['endtime'] < $GLOBALS['EXEC_TIME'] && $pageinfo['endtime'] != 0) {
4267  $simTime = '&ADMCMD_simTime=' . ($pageinfo['endtime'] - 1);
4268  }
4269  return $simUser . $simTime;
4270  }
4271 
4280  static public function processParams($params) {
4281  $paramArr = array();
4282  $lines = explode(LF, $params);
4283  foreach ($lines as $val) {
4284  $val = trim($val);
4285  if ($val) {
4286  $pair = explode('=', $val, 2);
4287  $paramArr[trim($pair[0])] = trim($pair[1]);
4288  }
4289  }
4290  return $paramArr;
4291  }
4292 
4299  static public function getBackendScript($interface = '') {
4300  if (!$interface) {
4301  $interface = $GLOBALS['BE_USER']->uc['interfaceSetup'];
4302  }
4303  switch ($interface) {
4304  case 'frontend':
4305  $script = '../.';
4306  break;
4307  case 'backend':
4308 
4309  default:
4310  $script = 'backend.php';
4311  }
4312  return $script;
4313  }
4314 
4321  static public function isTableWorkspaceEnabled($table) {
4322  return !empty($GLOBALS['TCA'][$table]['ctrl']['versioningWS']);
4323  }
4324 
4332  static public function isTableMovePlaceholderAware($table) {
4333  return (self::isTableWorkspaceEnabled($table) && (int)$GLOBALS['TCA'][$table]['ctrl']['versioningWS'] === 2);
4334  }
4335 
4343  static public function getTcaFieldConfiguration($table, $field) {
4344  $configuration = array();
4345  if (isset($GLOBALS['TCA'][$table]['columns'][$field]['config'])) {
4346  $configuration = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
4347  }
4348  return $configuration;
4349  }
4350 
4359  static public function isWebMountRestrictionIgnored($table) {
4360  return !empty($GLOBALS['TCA'][$table]['ctrl']['security']['ignoreWebMountRestriction']);
4361  }
4362 
4371  static public function isRootLevelRestrictionIgnored($table) {
4372  return !empty($GLOBALS['TCA'][$table]['ctrl']['security']['ignoreRootLevelRestriction']);
4373  }
4374 
4380  static protected function getSignalSlotDispatcher() {
4381  return GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher');
4382  }
4383 
4393  static protected function emitGetPagesTSconfigPreIncludeSignal(array $TSdataArray, $id, array $rootLine, $returnPartArray) {
4394  $signalArguments = static::getSignalSlotDispatcher()->dispatch(__CLASS__, 'getPagesTSconfigPreInclude', array($TSdataArray, $id, $rootLine, $returnPartArray));
4395  return $signalArguments[0];
4396  }
4397 }
static referenceCount($table, $ref, $msg='', $count=NULL)
static translationCount($table, $ref, $msg='')
static getTSconfig_pidValue($table, $uid, $pid)
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=TRUE, $includeEmptyValues=TRUE, $enableUnsetFeature=TRUE)
static uniqueList($in_list, $secondParameter=NULL)
static blindUserNames($usernames, $groupArray, $excludeBlindedFlag=0)
static skinImg($backPath, $src, $wHattribs='', $outputMode=0)
static getFuncCheck($mainParams, $elementName, $currentValue, $script='', $addParams='', $tagParams='')
static getRecordWSOL($table, $uid, $fields=' *', $where='', $useDeleteClause=TRUE, $unsetMovePointers=FALSE)
static readPageAccess($id, $perms_clause)
static getWorkspaceVersionOfRecord($workspace, $table, $uid, $fields=' *')
static createPreviewUrl($pageUid, $rootLine, $anchorSection, $additionalGetVars, $viewScript)
static helpTextIcon($table, $field, $BACK_PATH, $force=0)
static getAjaxUrl($ajaxIdentifier, array $urlParameters=array(), $backPathOverride=FALSE, $returnAbsoluteUrl=FALSE)
static editOnClick($params, $backPath='', $requestUri='')
$moduleName
Definition: mod.php:22
static getItemLabel($table, $col, $printAllWrap='')
static getRecordsByField($theTable, $theField, $theValue, $whereClause='', $groupBy='', $orderBy='', $limit='', $useDeleteClause=TRUE)
static BEgetRootLine($uid, $clause='', $workspaceOL=FALSE)
static countVersionsOfRecordsOnPage($workspace, $pageId)
static isFirstPartOfStr($str, $partStr)
static getSpriteIconForResource(\TYPO3\CMS\Core\Resource\ResourceInterface $resource, array $options=array(), array $overlays=array())
static resolveAllSheetsInDS(array $dataStructArray)
static openPageTree($pid, $clearExpansion)
static workspaceOL($table, &$row, $wsid=-99, $unsetMovePointers=FALSE)
static intExplode($delimiter, $string, $removeEmptyValues=FALSE, $limit=0)
$uid
Definition: server.php:36
static cshItem($table, $field, $BACK_PATH, $wrap='', $onlyIconMode=FALSE, $styleAttrib='')
static getUserObj($classRef, $checkPrefix='', $silent=FALSE)
static getRecordsSortedByTitle(array $fields, $table, $titleField, $where='')
static getWorkspaceWhereClause($table, $workspaceId=NULL)
static getMovePlaceholder($table, $uid, $fields=' *', $workspace=NULL)
static getFuncInput($mainParams, $elementName, $currentValue, $size=10, $script='', $addParams='')
$formprotection
Definition: mod.php:24
static getGroupNames($fields='title, uid', $where='')
static lockRecords($table='', $uid=0, $pid=0)
die
Definition: index.php:6
static getUrlToken($formName='securityToken', $tokenName='formToken')
static replaceMarkersInWhereClause($whereClause, $table, $field='', $tsConfig=array())
static storeHash($hash, $data, $ident)
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
static getFlexFormDS($conf, $row, $table, $fieldName='', $WSOL=TRUE, $newRecordPidValue=0)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
static calcAge($seconds, $labels=' min|hrs|days|yrs|min|hour|day|year')
static getProcessedValueExtra($table, $fN, $fV, $fixed_lgd_chars=0, $uid=0, $forceResult=TRUE)
static getRecordTitle($table, $row, $prep=FALSE, $forceResult=TRUE)
static getModuleUrl($moduleName, $urlParameters=array(), $backPathOverride=FALSE, $returnAbsoluteUrl=FALSE)
static getInlineLocalizationMode($table, $fieldOrConfig)
static time($value, $withSeconds=TRUE)
static wrapInHelp($table, $field, $text='', array $overloadHelpText=array())
$BACK_PATH
Definition: conf.php:3
static getDomainStartPage($domain, $path='')
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
static getRegisteredFlexForms($table='tt_content')
static getCommonSelectFields($table, $prefix='', $fields=array())
static getModuleData($MOD_MENU, $CHANGED_SETTINGS, $modName, $type='', $dontValidateList='', $setDefaultList='')
static getUrl($url, $includeHeader=0, $requestHeaders=FALSE, &$report=NULL)
static emitGetPagesTSconfigPreIncludeSignal(array $TSdataArray, $id, array $rootLine, $returnPartArray)
static inArray(array $in_array, $item)
static getUserNames($fields='username, usergroup, usergroup_cached_list, uid', $where='')
static getRecordLocalization($table, $uid, $language, $andWhereClause='')
static makeConfigForm($configArray, $defaults, $dataPrefix)
static getSpriteIcon($iconName, array $options=array(), array $overlays=array())
static setUpdateSignal($set='', $params='')
$extConf
static getTCAtypes($table, $rec, $useFieldNameAsKey=0)
static blindGroupNames($groups, $groupArray, $excludeBlindedFlag=0)
static getRecordRaw($table, $where='', $fields=' *')
static getTcaFieldConfiguration($table, $field)
static RTEsetup($RTEprop, $table, $field, $type='')
static getFuncMenu($mainParams, $elementName, $currentValue, $menuItems, $script='', $addparams='')
static unsetMenuItems($modTSconfig, $itemArray, $TSref)
static implodeArrayForUrl($name, array $theArray, $str='', $skipBlank=FALSE, $rawurlencodeParamName=FALSE)
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel=E_DEBUG)
static selectVersionsOfRecord($table, $uid, $fields=' *', $workspace=0, $includeDeletedRecords=FALSE, $row=NULL)
static getSQLselectableList($in_list, $tablename, $default_tablename)
static fixed_lgd_cs($string, $chars, $appendString='...')
static getPageForRootline($uid, $clause, $workspaceOL)
static fixVersioningPid($table, &$rr, $ignoreWorkspaceMatch=FALSE)
static getListGroupNames($fields='title, uid')
static getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit=0)
static getSpecConfParts($str, $defaultExtras)
static getRecordTitlePrep($title, $titleLength=0)
static getPidForModTSconfig($table, $uid, $pid)
static buildScriptUrl($mainParams, $addParams, $script='')
static getLiveVersionOfRecord($table, $uid, $fields=' *')
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
static exec_foreign_table_where_query($fieldValue, $field='', $TSconfig=array(), $prefix='')
static xml2array($string, $NSprefix='', $reportDocTag=FALSE)
static getFileAbsFileName($filename, $onlyRelative=TRUE, $relToTYPO3_mainDir=FALSE)
static getPagesTSconfig($id, $rootLine=NULL, $returnPartArray=FALSE)
static dateTimeAge($tstamp, $prefix=1, $date='')
static getListViewLink($urlParameters=array(), $linkTitle='', $linkText='')
static deleteClause($table, $tableAlias='')
static replaceL10nModeFields($table, array $row)
static TYPO3_copyRightNotice($showVersionNumber=TRUE)