TYPO3  7.6
TcaRecordTitle.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Backend\Form\FormDataProvider;
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 
22 
30 {
37  public function addData(array $result)
38  {
39  if (!isset($result['processedTca']['ctrl']['label'])) {
40  throw new \UnexpectedValueException(
41  'TCA of table ' . $result['tableName'] . ' misses required [\'ctrl\'][\'label\'] definition.',
42  1443706103
43  );
44  }
45 
46  if ($result['isInlineChild'] && isset($result['processedTca']['ctrl']['formattedLabel_userFunc'])) {
47  // inline child with formatted user func is first
48  $parameters = [
49  'table' => $result['tableName'],
50  'row' => $result['databaseRow'],
51  'title' => '',
52  'isOnSymmetricSide' => $result['isOnSymmetricSide'],
53  'options' => isset($result['processedTca']['ctrl']['formattedLabel_userFunc_options'])
54  ? $result['processedTca']['ctrl']['formattedLabel_userFunc_options']
55  : [],
56  'parent' => [
57  'uid' => $result['databaseRow']['uid'],
58  'config' => $result['inlineParentConfig']
59  ]
60  ];
61  // callUserFunction requires a third parameter, but we don't want to give $this as reference!
62  $null = null;
63  GeneralUtility::callUserFunction($result['processedTca']['ctrl']['formattedLabel_userFunc'], $parameters, $null);
64  $result['recordTitle'] = $parameters['title'];
65  } elseif (isset($result['processedTca']['ctrl']['label_userFunc'])) {
66  // userFunc takes precedence over everything else
67  $parameters = [
68  'table' => $result['tableName'],
69  'row' => $result['databaseRow'],
70  'title' => '',
71  'options' => isset($result['processedTca']['ctrl']['label_userFunc_options'])
72  ? $result['processedTca']['ctrl']['label_userFunc_options']
73  : [],
74  ];
75  $null = null;
76  GeneralUtility::callUserFunction($result['processedTca']['ctrl']['label_userFunc'], $parameters, $null);
77  $result['recordTitle'] = $parameters['title'];
78  } elseif ($result['isInlineChild'] && isset($result['inlineParentConfig']['foreign_label'])
79  || $result['isInlineChild'] && isset($result['inlineParentConfig']['symmetric_label'])
80  ) {
81  // inline child with foreign label or symmetric inline child with symmetric_label
82  $fieldName = $result['isOnSymmetricSide']
83  ? $result['inlineParentConfig']['symmetric_label']
84  : $result['inlineParentConfig']['foreign_label'];
85  // @todo: this is a mixup here. problem is the prep method cuts the string, but also hsc's the thing.
86  // @todo: this is uncool for the userfuncs, so it is applied only here. however, the OuterWrapContainer
87  // @todo: also prep()'s the title created by the else patch below ... find a better separation and clean this up!
88  $result['recordTitle'] = BackendUtility::getRecordTitlePrep($this->getRecordTitleForField($fieldName, $result));
89  } else {
90  // standard record
91  $result = $this->getRecordTitleByLabelProperties($result);
92  }
93 
94  return $result;
95  }
96 
103  protected function getRecordTitleByLabelProperties(array $result)
104  {
105  $titles = [];
106  $titleByLabel = $this->getRecordTitleForField($result['processedTca']['ctrl']['label'], $result);
107  if (!empty($titleByLabel)) {
108  $titles[] = $titleByLabel;
109  }
110 
111  $labelAltForce = isset($result['processedTca']['ctrl']['label_alt_force'])
112  ? (bool)$result['processedTca']['ctrl']['label_alt_force']
113  : false;
114  if (!empty($result['processedTca']['ctrl']['label_alt']) && ($labelAltForce || empty($titleByLabel))) {
115  // Dive into label_alt evaluation if label_alt_force is set or if label did not came up with a title yet
116  $labelAltFields = GeneralUtility::trimExplode(',', $result['processedTca']['ctrl']['label_alt'], true);
117  foreach ($labelAltFields as $fieldName) {
118  $titleByLabelAlt = $this->getRecordTitleForField($fieldName, $result);
119  if (!empty($titleByLabelAlt)) {
120  $titles[] = $titleByLabelAlt;
121  }
122  if (!$labelAltForce && !empty($titleByLabelAlt)) {
123  // label_alt_force creates a comma separated list of multiple fields.
124  // If not set, one found field with content is enough
125  break;
126  }
127  }
128  }
129 
130  $result['recordTitle'] = implode(', ', $titles);
131  return $result;
132  }
133 
141  protected function getRecordTitleForField($fieldName, $result)
142  {
143  if ($fieldName === 'uid') {
144  // uid return field content directly since it usually has not TCA definition
145  return $result['databaseRow']['uid'];
146  }
147 
148  if (!isset($result['processedTca']['columns'][$fieldName]['config']['type'])
149  || !is_string($result['processedTca']['columns'][$fieldName]['config']['type'])
150  ) {
151  return '';
152  }
153 
154  $recordTitle = '';
155  $rawValue = null;
156  if (array_key_exists($fieldName, $result['databaseRow'])) {
157  $rawValue = $result['databaseRow'][$fieldName];
158  }
159  $fieldConfig = $result['processedTca']['columns'][$fieldName]['config'];
160  switch ($fieldConfig['type']) {
161  case 'radio':
162  $recordTitle = $this->getRecordTitleForRadioType($rawValue, $fieldConfig);
163  break;
164  case 'inline':
165  // intentional fall-through
166  case 'select':
167  $recordTitle = $this->getRecordTitleForSelectType($rawValue, $fieldConfig);
168  break;
169  case 'group':
170  $recordTitle = $this->getRecordTitleForGroupType($rawValue, $fieldConfig);
171  break;
172  case 'check':
173  $recordTitle = $this->getRecordTitleForCheckboxType($rawValue, $fieldConfig);
174  break;
175  case 'input':
176  $recordTitle = $this->getRecordTitleForInputType($rawValue, $fieldConfig);
177  break;
178  case 'text':
179  $recordTitle = $this->getRecordTitleForTextType($rawValue);
180  case 'flex':
181  // @todo: Check if and how a label could be generated from flex field data
182  default:
183 
184  }
185 
186  return $recordTitle;
187  }
188 
196  protected function getRecordTitleForRadioType($value, $fieldConfig)
197  {
198  if (!isset($fieldConfig['items']) || !is_array($fieldConfig['items'])) {
199  return '';
200  }
201  foreach ($fieldConfig['items'] as $item) {
202  list($itemLabel, $itemValue) = $item;
203  if ((string)$value === (string)$itemValue) {
204  return $itemLabel;
205  }
206  }
207  return '';
208  }
209 
217  protected function getRecordTitleForSelectType($value, $fieldConfig)
218  {
219  if (!is_array($value)) {
220  return '';
221  }
222  $labelParts = [];
223  foreach ($value as $itemValue) {
224  $itemKey = array_search($itemValue, array_column($fieldConfig['items'], 1));
225  if ($itemKey !== false) {
226  $labelParts[] = $fieldConfig['items'][$itemKey][0];
227  }
228  }
229  $title = implode(', ', $labelParts);
230  if (empty($title) && !empty($value)) {
231  $title = implode(', ', $value);
232  }
233  return $title;
234  }
235 
243  protected function getRecordTitleForGroupType($value, $fieldConfig)
244  {
245  if ($fieldConfig['internal_type'] !== 'db') {
246  return implode(', ', GeneralUtility::trimExplode(',', $value, true));
247  }
248  $labelParts = array_map(
249  function ($rawLabelItem) {
250  return array_pop(GeneralUtility::trimExplode('|', $rawLabelItem, true, 2));
251  },
252  GeneralUtility::trimExplode(',', $value, true)
253  );
254  if (!empty($labelParts)) {
255  sort($labelParts);
256  return implode(', ', $labelParts);
257  }
258  return '';
259  }
260 
268  protected function getRecordTitleForCheckboxType($value, $fieldConfig)
269  {
270  $languageService = $this->getLanguageService();
271  if (empty($fieldConfig['items']) || !is_array($fieldConfig['items'])) {
272  $title = (bool)$value
273  ? $languageService->sL('LLL:EXT:lang/locallang_common.xlf:yes')
274  : $languageService->sL('LLL:EXT:lang/locallang_common.xlf:no');
275  } else {
276  $labelParts = [];
277  foreach ($fieldConfig['items'] as $key => $val) {
278  if ($value & pow(2, $key)) {
279  $labelParts[] = $val[0];
280  }
281  }
282  $title = implode(', ', $labelParts);
283  }
284  return $title;
285  }
286 
294  protected function getRecordTitleForInputType($value, $fieldConfig)
295  {
296  if (!isset($value)) {
297  return '';
298  }
299  $title = $value;
300  if (GeneralUtility::inList($fieldConfig['eval'], 'date')) {
301  if (isset($fieldConfig['dbType']) && $fieldConfig['dbType'] === 'date') {
302  $value = $value === '0000-00-00' ? 0 : (int)strtotime($value);
303  } else {
304  $value = (int)$value;
305  }
306  if (!empty($value)) {
307  $ageSuffix = '';
308  // Generate age suffix as long as not explicitly suppressed
309  if (!isset($fieldConfig['disableAgeDisplay']) || (bool)$fieldConfig['disableAgeDisplay'] === false) {
310  $ageDelta = $GLOBALS['EXEC_TIME'] - $value;
311  $calculatedAge = BackendUtility::calcAge(
312  abs($ageDelta),
313  $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysYears')
314  );
315  $ageSuffix = ' (' . ($ageDelta > 0 ? '-' : '') . $calculatedAge . ')';
316  }
317  $title = BackendUtility::date($value) . $ageSuffix;
318  }
319  } elseif (GeneralUtility::inList($fieldConfig['eval'], 'time')) {
320  if (!empty($value)) {
321  $title = BackendUtility::time((int)$value, false);
322  }
323  } elseif (GeneralUtility::inList($fieldConfig['eval'], 'timesec')) {
324  if (!empty($value)) {
325  $title = BackendUtility::time((int)$value);
326  }
327  } elseif (GeneralUtility::inList($fieldConfig['eval'], 'datetime')) {
328  // Handle native date/time field
329  if (isset($fieldConfig['dbType']) && $fieldConfig['dbType'] === 'datetime') {
330  $value = $value === '0000-00-00 00:00:00' ? 0 : (int)strtotime($value);
331  } else {
332  $value = (int)$value;
333  }
334  if (!empty($value)) {
335  $title = BackendUtility::datetime($value);
336  }
337  }
338  return $title;
339  }
340 
347  protected function getRecordTitleForTextType($value)
348  {
349  return trim(strip_tags($value));
350  }
351 
355  protected function getDatabaseConnection()
356  {
357  return $GLOBALS['TYPO3_DB'];
358  }
359 
363  protected function getLanguageService()
364  {
365  return $GLOBALS['LANG'];
366  }
367 }