TYPO3  7.6
GroupElement.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Backend\Form\Element;
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 
26 
31 {
38  public function render()
39  {
40  $table = $this->data['tableName'];
41  $fieldName = $this->data['fieldName'];
42  $row = $this->data['databaseRow'];
43  $parameterArray = $this->data['parameterArray'];
44  $config = $parameterArray['fieldConf']['config'];
45  $show_thumbs = $config['show_thumbs'];
46  $resultArray = $this->initializeResultArray();
47 
48  $size = isset($config['size']) ? (int)$config['size'] : $this->minimumInputWidth;
49  $maxitems = MathUtility::forceIntegerInRange($config['maxitems'], 0);
50  if (!$maxitems) {
51  $maxitems = 100000;
52  }
53  $minitems = MathUtility::forceIntegerInRange($config['minitems'], 0);
54  $thumbnails = array();
55  $allowed = GeneralUtility::trimExplode(',', $config['allowed'], true);
56  $disallowed = GeneralUtility::trimExplode(',', $config['disallowed'], true);
57  $disabled = $config['readOnly'];
58  $info = array();
59  $parameterArray['itemFormElID_file'] = $parameterArray['itemFormElID'] . '_files';
60 
61  // whether the list and delete controls should be disabled
62  $noList = isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'list');
63  $noDelete = isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'delete');
64 
65  // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist.
66  $specConf = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
67 
68  // Register properties in required elements / validation
69  $attributes['data-formengine-validation-rules'] = htmlspecialchars(
71  array(
72  'minitems' => $minitems,
73  'maxitems' => $maxitems
74  )
75  )
76  );
77 
78  // If maxitems==1 then automatically replace the current item (in list and file selector)
79  if ($maxitems === 1) {
80  $resultArray['additionalJavaScriptPost'][] =
81  'TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . '] = {
82  itemFormElID_file: ' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElID_file']) . '
83  }';
84  $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'setFormValueManipulate(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName'])
85  . ', \'Remove\'); ' . $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'];
86  } elseif ($noList) {
87  // If the list controls have been removed and the maximum number is reached, remove the first entry to avoid "write once" field
88  $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'setFormValueManipulate(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName'])
89  . ', \'RemoveFirstIfFull\', ' . GeneralUtility::quoteJSvalue($maxitems) . '); ' . $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'];
90  }
91 
92  $html = '<input type="hidden" class="t3js-group-hidden-field" data-formengine-input-name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="' . ($config['multiple'] ? 1 : 0) . '"' . $disabled . ' />';
93 
94  // Define parameters for all types below
95  $commonParameters = array(
96  'size' => $size,
97  'dontShowMoveIcons' => isset($config['hideMoveIcons']) || $maxitems <= 1,
98  'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0),
99  'maxitems' => $maxitems,
100  'style' => isset($config['selectedListStyle'])
101  ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"'
102  : '',
103  'readOnly' => $disabled,
104  'noBrowser' => $noList || isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'browser'),
105  'noList' => $noList,
106  );
107 
108  // Acting according to either "file" or "db" type:
109  switch ((string)$config['internal_type']) {
110  case 'file_reference':
111  $config['uploadfolder'] = '';
112  // Fall through
113  case 'file':
114  // Creating string showing allowed types:
115  if (empty($allowed)) {
116  $allowed = array('*');
117  }
118  // Making the array of file items:
119  $itemArray = GeneralUtility::trimExplode(',', $parameterArray['itemFormElValue'], true);
120  $fileFactory = ResourceFactory::getInstance();
121  // Correct the filename for the FAL items
122  foreach ($itemArray as &$fileItem) {
123  list($fileUid, $fileLabel) = explode('|', $fileItem);
125  $fileObject = $fileFactory->getFileObject($fileUid);
126  $fileLabel = $fileObject->getName();
127  }
128  $fileItem = $fileUid . '|' . $fileLabel;
129  }
130  // Showing thumbnails:
131  if ($show_thumbs) {
132  foreach ($itemArray as $imgRead) {
133  $imgP = explode('|', $imgRead);
134  $imgPath = rawurldecode($imgP[0]);
135  // FAL icon production
137  $fileObject = $fileFactory->getFileObject($imgP[0]);
138  if ($fileObject->isMissing()) {
139  $thumbnails[] = array(
140  'message' => \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject)->render()
141  );
142  } elseif (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileObject->getExtension())) {
143  $thumbnails[] = array(
144  'name' => htmlspecialchars($fileObject->getName()),
145  'image' => $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array())->getPublicUrl(true)
146  );
147  } else {
148  $name = htmlspecialchars($fileObject->getName());
149  // Icon
150  $thumbnails[] = array(
151  'name' => $name,
152  'image' => '<span title="' . $name . '">' . $this->iconFactory->getIconForResource($fileObject, Icon::SIZE_SMALL) . '</span>'
153  );
154  }
155  } else {
156  $rowCopy = array();
157  $rowCopy[$fieldName] = $imgPath;
158  try {
159  $thumbnails[] = array(
160  'name' => $imgPath,
161  'image' => BackendUtility::thumbCode(
162  $rowCopy,
163  $table,
164  $fieldName,
165  '',
166  '',
167  $config['uploadfolder'],
168  0,
169  ' align="middle"'
170  )
171  );
172  } catch (\Exception $exception) {
174  $message = $exception->getMessage();
175  $flashMessage = GeneralUtility::makeInstance(
176  FlashMessage::class,
177  htmlspecialchars($message), '', FlashMessage::ERROR, true
178  );
180  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
181  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
182  $defaultFlashMessageQueue->enqueue($flashMessage);
183  $logMessage = $message . ' (' . $table . ':' . $row['uid'] . ')';
184  GeneralUtility::sysLog($logMessage, 'core', GeneralUtility::SYSLOG_SEVERITY_WARNING);
185  }
186  }
187  }
188  }
189  // Creating the element:
190  $params = array_merge($commonParameters, array(
191  'allowed' => $allowed,
192  'disallowed' => $disallowed,
193  'thumbnails' => $thumbnails,
194  'noDelete' => $noDelete
195  ));
196  $html .= $this->dbFileIcons(
197  $parameterArray['itemFormElName'],
198  'file',
199  implode(',', $allowed),
200  $itemArray,
201  '',
202  $params,
203  $parameterArray['onFocus'],
204  '',
205  '',
206  '',
207  $config);
208  if (!$disabled && !(isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'upload'))) {
209  // Adding the upload field:
210  $isDirectFileUploadEnabled = (bool)$this->getBackendUserAuthentication()->uc['edit_docModuleUpload'];
211  if ($isDirectFileUploadEnabled && $config['uploadfolder']) {
212  // Insert the multiple attribute to enable HTML5 multiple file upload
213  $multipleAttribute = '';
214  $multipleFilenameSuffix = '';
215  if (isset($config['maxitems']) && $config['maxitems'] > 1) {
216  $multipleAttribute = ' multiple="multiple"';
217  $multipleFilenameSuffix = '[]';
218  }
219  $html .= '
220  <div id="' . $parameterArray['itemFormElID_file'] . '">
221  <input type="file"' . $multipleAttribute . '
222  name="data_files' . $this->data['elementBaseName'] . $multipleFilenameSuffix . '"
223  size="35" onchange="' . implode('', $parameterArray['fieldChangeFunc']) . '"
224  />
225  </div>';
226  }
227  }
228  break;
229  case 'folder':
230  // If the element is of the internal type "folder":
231  // Array of folder items:
232  $itemArray = GeneralUtility::trimExplode(',', $parameterArray['itemFormElValue'], true);
233  // Creating the element:
234  $params = $commonParameters;
235  $html .= $this->dbFileIcons(
236  $parameterArray['itemFormElName'],
237  'folder',
238  '',
239  $itemArray,
240  '',
241  $params,
242  $parameterArray['onFocus']
243  );
244  break;
245  case 'db':
246  // If the element is of the internal type "db":
247  // Creating string showing allowed types:
248  $onlySingleTableAllowed = false;
249  $languageService = $this->getLanguageService();
250 
251  $allowedTables = array();
252  if ($allowed[0] === '*') {
253  $allowedTables = array(
254  'name' => htmlspecialchars($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.allTables'))
255  );
256  } elseif ($allowed) {
257  $onlySingleTableAllowed = count($allowed) === 1;
258  foreach ($allowed as $allowedTable) {
259  $allowedTables[] = array(
260  // @todo: access to globals!
261  'name' => htmlspecialchars($languageService->sL($GLOBALS['TCA'][$allowedTable]['ctrl']['title'])),
262  'icon' => $this->iconFactory->getIconForRecord($allowedTable, array(), Icon::SIZE_SMALL)->render(),
263  'onClick' => 'setFormValueOpenBrowser(\'db\', ' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName'] . '|||' . $allowedTable) . '); return false;'
264  );
265  }
266  }
267  $perms_clause = $this->getBackendUserAuthentication()->getPagePermsClause(1);
268  $itemArray = array();
269 
270  // Thumbnails:
271  // @todo: this is data processing - must be extracted
272  $temp_itemArray = GeneralUtility::trimExplode(',', $parameterArray['itemFormElValue'], true);
273  foreach ($temp_itemArray as $dbRead) {
274  $recordParts = explode('|', $dbRead);
275  list($this_table, $this_uid) = BackendUtility::splitTable_Uid($recordParts[0]);
276  // For the case that no table was found and only a single table is defined to be allowed, use that one:
277  if (!$this_table && $onlySingleTableAllowed) {
278  $this_table = $allowed;
279  }
280  $itemArray[] = array('table' => $this_table, 'id' => $this_uid);
281  if (!$disabled && $show_thumbs) {
282  $rr = BackendUtility::getRecordWSOL($this_table, $this_uid);
283  $thumbnails[] = array(
284  'name' => BackendUtility::getRecordTitle($this_table, $rr, true),
285  'image' => $this->iconFactory->getIconForRecord($this_table, $rr, Icon::SIZE_SMALL)->render(),
286  'path' => BackendUtility::getRecordPath($rr['pid'], $perms_clause, 15),
287  'uid' => $rr['uid'],
288  'table' => $this_table
289  );
290  }
291  }
292  // Creating the element:
293  $params = array_merge($commonParameters, array(
294  'info' => $info,
295  'allowedTables' => $allowedTables,
296  'thumbnails' => $thumbnails,
297  ));
298  $html .= $this->dbFileIcons(
299  $parameterArray['itemFormElName'],
300  'db',
301  implode(',', $allowed),
302  $itemArray,
303  '',
304  $params,
305  $parameterArray['onFocus'],
306  $table,
307  $fieldName,
308  $row['uid'],
309  $config
310  );
311  break;
312  }
313  // Wizards:
314  if (!$disabled) {
315  $html = $this->renderWizards(
316  array($html),
317  $config['wizards'],
318  $table,
319  $row,
320  $fieldName,
321  $parameterArray,
322  $parameterArray['itemFormElName'],
323  $specConf
324  );
325  }
326  $resultArray['html'] = $html;
327  return $resultArray;
328  }
329 
333  protected function getBackendUserAuthentication()
334  {
335  return $GLOBALS['BE_USER'];
336  }
337 }