‪TYPO3CMS  ‪main
DatabaseRecordTypeValue.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
19 use TYPO3\CMS\Backend\Utility\BackendUtility;
21 
26 {
37  public function ‪addData(array $result)
38  {
39  if (!isset($result['processedTca']['types'])
40  || !is_array($result['processedTca']['types'])
41  || empty($result['processedTca']['types'])
42  ) {
43  throw new \UnexpectedValueException(
44  'At least one "types" array must be defined for table ' . $result['tableName'] . ', preferred "0"',
45  1438185331
46  );
47  }
48 
49  // Guard clause to suppress any calculation if record type value has been set from outside already
50  if ($result['recordTypeValue'] !== '') {
51  return $result;
52  }
53 
54  $recordTypeValue = '0';
55  if (!empty($result['processedTca']['ctrl']['type'])) {
56  $tcaTypeField = $result['processedTca']['ctrl']['type'];
57 
58  if (!str_contains($tcaTypeField, ':')) {
59  // $tcaTypeField is the name of a field in database row
60  if (!array_key_exists($tcaTypeField, $result['databaseRow'])) {
61  throw new \UnexpectedValueException(
62  'TCA table ' . $result['tableName'] . ' ctrl[\'type\'] is set to ' . $tcaTypeField . ', but'
63  . ' this field does not exist in the database of this table',
64  1438183881
65  );
66  }
67  $recordTypeValue = $result['databaseRow'][$tcaTypeField];
68  } else {
69  // If type is configured as localField:foreignField, fetch the type value from
70  // a foreign table. localField then point to a group or select field in the own table,
71  // this points to a record in a foreign table and the value of foreignField is then
72  // used as type field. This was introduced for some FAL scenarios.
73  [$pointerField, $foreignTableTypeField] = explode(':', $tcaTypeField);
74 
75  $relationType = (string)($result['processedTca']['columns'][$pointerField]['config']['type'] ?? '');
76  if (!in_array($relationType, ['select', 'category', 'group'], true)) {
77  throw new \UnexpectedValueException(
78  'TCA foreign field pointer fields are only allowed to be used with group, select or category field types.'
79  . ' Handling field ' . $pointerField . ' with type configured as ' . $tcaTypeField,
80  1325862241
81  );
82  }
83 
84  $foreignUid = $result['databaseRow'][$pointerField];
85  // Resolve the foreign record only if there is a uid, otherwise fall back 0
86  if (!empty($foreignUid)) {
87  // Determine table name to fetch record from
88  if ($relationType === 'select' || $relationType === 'category') {
89  $foreignTable = $result['processedTca']['columns'][$pointerField]['config']['foreign_table'] ?? '';
90  } else {
91  $allowedTables = explode(',', $result['processedTca']['columns'][$pointerField]['config']['allowed']);
92  // Always take the first configured table.
93  $foreignTable = $allowedTables[0];
94  }
95  if (empty($foreignTable)) {
96  throw new \UnexpectedValueException(
97  'No target table defined for type config field ' . $pointerField . ' of table ' . $result['tableName'],
98  1438253614
99  );
100  }
101  if (!‪MathUtility::canBeInterpretedAsInteger($foreignUid) && is_array($foreignUid[0])) {
102  // A group relation - has been resolved to array by TcaGroup data provider already
103  $foreignUid = $foreignUid[0]['uid'];
104  }
105  // Fetch field of this foreign row from db
107  $foreignRow = $this->‪getDatabaseRow($foreignTable, (int)$foreignUid, $foreignTableTypeField);
108  if (!empty($foreignRow[$foreignTableTypeField])) {
109  // @todo: It might be necessary to fetch the value from default language record as well here,
110  // @todo: this was buggy in the "old" implementation and never worked. It was therefor left out here for now.
111  // @todo: To implement that, see if the foreign row is a localized overlay, fetch default and merge exclude
112  $recordTypeValue = $foreignRow[$foreignTableTypeField];
113  }
114  }
115  }
116  }
117  }
118 
119  // Throw another exception if determined value and '0' and '1' do not exist
120  if (empty($result['processedTca']['types'][$recordTypeValue])
121  && empty($result['processedTca']['types']['0'])
122  && empty($result['processedTca']['types']['1'])
123  ) {
124  throw new \UnexpectedValueException(
125  'Type value ' . $recordTypeValue . ' from database record not defined in TCA of table '
126  . $result['tableName'] . ' and neither 0 nor 1 are defined as fallback.',
127  1438185437
128  );
129  }
130 
131  // Check the determined value actually exists as types key, otherwise fall back to 0 or 1, 1 for "historical reasons"
132  if (empty($result['processedTca']['types'][$recordTypeValue])) {
133  $recordTypeValue = !empty($result['processedTca']['types']['0']) ? '0' : '1';
134  }
135 
136  $result['recordTypeValue'] = (string)$recordTypeValue;
137  return $result;
138  }
139 
143  protected function ‪getDatabaseRow(string $tableName, int ‪$uid, string $fieldName): array
144  {
145  $row = BackendUtility::getRecord($tableName, ‪$uid, $fieldName);
146 
147  return $row ?: [];
148  }
149 }
‪TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRecordTypeValue
Definition: DatabaseRecordTypeValue.php:26
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger(mixed $var)
Definition: MathUtility.php:69
‪TYPO3\CMS\Backend\Form\FormDataProvider
Definition: AbstractDatabaseRecordProvider.php:16
‪TYPO3\CMS\Backend\Form\FormDataProviderInterface
Definition: FormDataProviderInterface.php:23
‪TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRecordTypeValue\addData
‪array addData(array $result)
Definition: DatabaseRecordTypeValue.php:37
‪TYPO3\CMS\Webhooks\Message\$uid
‪identifier readonly int $uid
Definition: PageModificationMessage.php:35
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRecordTypeValue\getDatabaseRow
‪getDatabaseRow(string $tableName, int $uid, string $fieldName)
Definition: DatabaseRecordTypeValue.php:143