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