‪TYPO3CMS  9.5
TcaInputPlaceholders.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
17 use Doctrine\DBAL\Connection;
24 
31 {
40  public function ‪addData(array $result)
41  {
42  foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
43  // Placeholders are only valid for input and text type fields
44  if (
45  ($fieldConfig['config']['type'] !== 'input' && $fieldConfig['config']['type'] !== 'text')
46  || !isset($fieldConfig['config']['placeholder'])
47  ) {
48  continue;
49  }
50 
51  // Resolve __row|field type placeholders
52  if (strpos($fieldConfig['config']['placeholder'], '__row|') === 0) {
53  // split field names into array and remove the __row indicator
54  $fieldNameArray = array_slice(
55  GeneralUtility::trimExplode('|', $fieldConfig['config']['placeholder'], true),
56  1
57  );
58  $result['processedTca']['columns'][$fieldName]['config']['placeholder'] = $this->‪getPlaceholderValue($fieldNameArray, $result);
59  }
60 
61  // Resolve placeholders from language files
62  if (strpos($fieldConfig['config']['placeholder'], 'LLL:') === 0) {
63  $result['processedTca']['columns'][$fieldName]['config']['placeholder'] = $this->‪getLanguageService()->‪sL($fieldConfig['config']['placeholder']);
64  }
65 
66  // Remove empty placeholders
67  if (empty($result['processedTca']['columns'][$fieldName]['config']['placeholder'])) {
68  unset($result['processedTca']['columns'][$fieldName]['config']['placeholder']);
69  }
70  }
71 
72  return $result;
73  }
74 
85  protected function ‪getPlaceholderValue($fieldNameArray, $result, $recursionLevel = 0)
86  {
87  if ($recursionLevel > 99) {
88  // This should not happen, treat as misconfiguration
89  return '';
90  }
91 
92  $fieldName = array_shift($fieldNameArray);
93 
94  // Skip if a defined field was actually not present in the database row
95  // Using array_key_exists here, since NULL values are valid as well.
96  if (!array_key_exists($fieldName, $result['databaseRow'])) {
97  return '';
98  }
99 
100  $value = $result['databaseRow'][$fieldName];
101 
102  if (!isset($result['processedTca']['columns'][$fieldName]['config'])
103  || !is_array($result['processedTca']['columns'][$fieldName]['config'])
104  ) {
105  return (string)$value;
106  }
107 
108  $fieldConfig = $result['processedTca']['columns'][$fieldName]['config'];
109 
110  switch ($fieldConfig['type']) {
111  case 'select':
112  // The FormDataProviders already resolved the select items to an array of uids,
113  // filter out empty values that occur when no related record has been selected.
114  $possibleUids = array_filter($value);
115  $foreignTableName = $fieldConfig['foreign_table'];
116  break;
117  case 'group':
118  $possibleUids = $this->‪getRelatedGroupFieldUids($fieldConfig, $value);
119  $foreignTableName = $this->‪getAllowedTableForGroupField($fieldConfig);
120  break;
121  case 'inline':
122  $possibleUids = array_filter(GeneralUtility::trimExplode(',', $value, true));
123  $foreignTableName = $fieldConfig['foreign_table'];
124  break;
125  default:
126  $possibleUids = [];
127  $foreignTableName = '';
128  }
129 
130  if (!empty($possibleUids) && !empty($fieldNameArray)) {
131  if (count($possibleUids) > 1
132  && !empty(‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['languageField'])
133  && isset($result['currentSysLanguage'])
134  ) {
135  $possibleUids = $this->‪getPossibleUidsByCurrentSysLanguage($possibleUids, $foreignTableName, $result['currentSysLanguage']);
136  }
137  $relatedFormData = $this->‪getRelatedFormData($foreignTableName, $possibleUids[0], $fieldNameArray[0]);
138  if (!empty(‪$GLOBALS['TCA'][$result['tableName']]['ctrl']['languageField'])
139  && isset($result['databaseRow'][‪$GLOBALS['TCA'][$result['tableName']]['ctrl']['languageField']])
140  ) {
141  $relatedFormData['currentSysLanguage'] = $result['databaseRow'][‪$GLOBALS['TCA'][$result['tableName']]['ctrl']['languageField']][0];
142  }
143  $value = $this->‪getPlaceholderValue($fieldNameArray, $relatedFormData, $recursionLevel + 1);
144  }
145 
146  if ($recursionLevel === 0 && is_array($value)) {
147  $value = implode(', ', $value);
148  }
149  return (string)$value;
150  }
151 
160  protected function ‪getRelatedFormData($tableName, $uid, $columnToProcess)
161  {
162  $fakeDataInput = [
163  'command' => 'edit',
164  'vanillaUid' => (int)$uid,
165  'tableName' => $tableName,
166  'inlineCompileExistingChildren' => false,
167  'columnsToProcess' => [$columnToProcess],
168  ];
170  $formDataGroup = GeneralUtility::makeInstance(TcaInputPlaceholderRecord::class);
172  $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
173  $compilerResult = $formDataCompiler->compile($fakeDataInput);
174  return $compilerResult;
175  }
176 
187  protected function ‪getRelatedGroupFieldUids(array $fieldConfig, $value)
188  {
189  $relatedUids = [];
190  $allowedTable = $this->‪getAllowedTableForGroupField($fieldConfig);
191 
192  // Skip if it's not a database relation with a resolvable foreign table
193  if (($fieldConfig['internal_type'] !== 'db') || ($allowedTable === false)) {
194  return $relatedUids;
195  }
196 
197  // Related group values have been prepared by TcaGroup data provider, an array is expected here
198  foreach ($value as $singleValue) {
199  $relatedUids[] = $singleValue['uid'];
200  }
201 
202  return $relatedUids;
203  }
204 
213  protected function ‪getAllowedTableForGroupField(array $fieldConfig)
214  {
215  $allowedTable = false;
216 
217  $allowedTables = GeneralUtility::trimExplode(',', $fieldConfig['allowed'], true);
218  if (count($allowedTables) === 1) {
219  $allowedTable = $allowedTables[0];
220  }
221 
222  return $allowedTable;
223  }
224 
237  protected function ‪getPossibleUidsByCurrentSysLanguage(array $possibleUids, $foreignTableName, $currentLanguage)
238  {
239  $languageField = ‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['languageField'];
240  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($foreignTableName);
241  $possibleRecords = $queryBuilder->select('uid', $languageField)
242  ->from($foreignTableName)
243  ->where(
244  $queryBuilder->expr()->in(
245  'uid',
246  $queryBuilder->createNamedParameter($possibleUids, Connection::PARAM_INT_ARRAY)
247  ),
248  $queryBuilder->expr()->in(
249  $languageField,
250  $queryBuilder->createNamedParameter([$currentLanguage, 0], Connection::PARAM_INT_ARRAY)
251  )
252  )
253  ->groupBy($languageField, 'uid')
254  ->execute()
255  ->fetchAll();
256 
257  if (!empty($possibleRecords)) {
258  // Either only one record or first record matches language
259  if (count($possibleRecords) === 1
260  || (int)$possibleRecords[0][$languageField] === (int)$currentLanguage
261  ) {
262  return [$possibleRecords[0]['uid']];
263  }
264 
265  // Language of second record matches language
266  return [$possibleRecords[1]['uid']];
267  }
268 
269  return $possibleUids;
270  }
271 
275  protected function ‪getLanguageService()
276  {
277  return ‪$GLOBALS['LANG'];
278  }
279 }
‪TYPO3\CMS\Backend\Form\FormDataGroup\TcaInputPlaceholderRecord
Definition: TcaInputPlaceholderRecord.php:24
‪TYPO3\CMS\Backend\Form\FormDataProvider\TcaInputPlaceholders\getAllowedTableForGroupField
‪bool string getAllowedTableForGroupField(array $fieldConfig)
Definition: TcaInputPlaceholders.php:213
‪TYPO3\CMS\Backend\Form\FormDataProvider\TcaInputPlaceholders
Definition: TcaInputPlaceholders.php:31
‪TYPO3\CMS\Backend\Form\FormDataProvider\TcaInputPlaceholders\getLanguageService
‪LanguageService getLanguageService()
Definition: TcaInputPlaceholders.php:275
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪string sL($input)
Definition: LanguageService.php:158
‪TYPO3\CMS\Backend\Form\FormDataProvider\TcaInputPlaceholders\getRelatedFormData
‪array getRelatedFormData($tableName, $uid, $columnToProcess)
Definition: TcaInputPlaceholders.php:160
‪TYPO3\CMS\Backend\Form\FormDataProvider\TcaInputPlaceholders\addData
‪array addData(array $result)
Definition: TcaInputPlaceholders.php:40
‪TYPO3\CMS\Backend\Form\FormDataProvider\TcaInputPlaceholders\getPlaceholderValue
‪string getPlaceholderValue($fieldNameArray, $result, $recursionLevel=0)
Definition: TcaInputPlaceholders.php:85
‪TYPO3\CMS\Backend\Form\FormDataProvider\TcaInputPlaceholders\getRelatedGroupFieldUids
‪array getRelatedGroupFieldUids(array $fieldConfig, $value)
Definition: TcaInputPlaceholders.php:187
‪TYPO3\CMS\Backend\Form\FormDataProvider
Definition: AbstractDatabaseRecordProvider.php:2
‪TYPO3\CMS\Backend\Form\FormDataProviderInterface
Definition: FormDataProviderInterface.php:22
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Form\FormDataProvider\TcaInputPlaceholders\getPossibleUidsByCurrentSysLanguage
‪array getPossibleUidsByCurrentSysLanguage(array $possibleUids, $foreignTableName, $currentLanguage)
Definition: TcaInputPlaceholders.php:237
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:29
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Backend\Form\FormDataCompiler
Definition: FormDataCompiler.php:24