‪TYPO3CMS  9.5
AddController.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
31 
38 {
40 
46  protected ‪$deprecatedPublicProperties = [
47  'content' => 'Using $content of class AddController from the outside is discouraged, as this variable is only used for internal storage.',
48  'processDataFlag' => 'Using $processDataFlag of class AddController from the outside is discouraged, as this variable is only used for internal storage.',
49  'pid' => 'Using $pid of class AddController from the outside is discouraged, as this variable is only used for internal storage.',
50  'table' => 'Using $table of class AddController from the outside is discouraged, as this variable is only used for internal storage.',
51  'id' => 'Using $id of class AddController from the outside is discouraged, as this variable is only used for internal storage.',
52  'P' => 'Using $P of class AddController from the outside is discouraged, as this variable is only used for internal storage.',
53  'returnEditConf' => 'Using $returnEditConf of class AddController from the outside is discouraged, as this variable is only used for internal storage.',
54  ];
61  protected ‪$content;
62 
68  protected ‪$processDataFlag = 0;
69 
75  protected ‪$pid;
76 
82  protected ‪$table;
83 
89  protected ‪$id;
90 
96  protected ‪$P;
97 
103  protected ‪$returnEditConf;
104 
108  public function ‪__construct()
109  {
110  $this->‪getLanguageService()->‪includeLLFile('EXT:core/Resources/Private/Language/locallang_wizards.xlf');
111  // @deprecated since TYPO3 v9, will be moved out of __construct() in TYPO3 v10.0
112  $this->‪init(‪$GLOBALS['TYPO3_REQUEST']);
113  }
114 
122  public function ‪mainAction(ServerRequestInterface $request): ResponseInterface
123  {
124  return $this->‪processRequest($request);
125  }
126 
133  public function ‪main()
134  {
135  trigger_error('AddController->main() will be replaced by protected method processRequest() in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
136 
137  $response = $this->‪processRequest(‪$GLOBALS['TYPO3_REQUEST']);
138  ‪HttpUtility::redirect($response->getHeaders()['location'][0]);
139  }
140 
145  protected function ‪init(ServerRequestInterface $request): void
146  {
147  $parsedBody = $request->getParsedBody();
148  $queryParams = $request->getQueryParams();
149  // Init GPvars:
150  $this->P = $parsedBody['P'] ?? $queryParams['P'] ?? [];
151  $this->returnEditConf = $parsedBody['returnEditConf'] ?? $queryParams['returnEditConf'] ?? null;
152  // Get this record
153  $record = ‪BackendUtility::getRecord($this->P['table'], $this->P['uid']);
154  // Set table:
155  $this->table = $this->P['params']['table'];
156  // Get TSconfig for it.
158  $this->P['table'],
159  is_array($record) ? $record : ['pid' => $this->P['pid']]
160  );
161  // Set [params][pid]
162  if (strpos($this->P['params']['pid'], '###') === 0 && substr($this->P['params']['pid'], -3) === '###') {
163  $keyword = substr($this->P['params']['pid'], 3, -3);
164  if (strpos($keyword, 'PAGE_TSCONFIG_') === 0) {
165  $this->pid = (int)$TSconfig[$this->P['field']][$keyword];
166  } else {
167  $this->pid = (int)$TSconfig['_' . $keyword];
168  }
169  } else {
170  $this->pid = (int)$this->P['params']['pid'];
171  }
172  // Return if new record as parent (not possibly/allowed)
173  if ($this->pid === '') {
174  // HTTP Redirect is performed by processRequest()
175  return;
176  }
177  // Else proceed:
178  // If a new id has returned from a newly created record...
179  if ($this->returnEditConf) {
180  $editConfiguration = json_decode($this->returnEditConf, true);
181  if (is_array($editConfiguration[$this->table]) && ‪MathUtility::canBeInterpretedAsInteger($this->P['uid'])) {
182  // Getting id and cmd from returning editConf array.
183  reset($editConfiguration[$this->table]);
184  $this->id = (int)key($editConfiguration[$this->table]);
185  $cmd = current($editConfiguration[$this->table]);
186  // ... and if everything seems OK we will register some classes for inclusion and instruct the object
187  // to perform processing later.
188  if ($this->P['params']['setValue']
189  && $cmd === 'edit'
190  && $this->id
191  && $this->P['table']
192  && $this->P['field'] && $this->P['uid']
193  ) {
194  $liveRecord = ‪BackendUtility::getLiveVersionOfRecord($this->table, $this->id, 'uid');
195  if ($liveRecord) {
196  $this->id = $liveRecord['uid'];
197  }
198  $this->processDataFlag = 1;
199  }
200  }
201  }
202  }
203 
211  protected function ‪processRequest(ServerRequestInterface $request): ResponseInterface
212  {
213  // Return if new record as parent (not possibly/allowed)
214  if ($this->pid === '') {
215  return new ‪RedirectResponse(GeneralUtility::sanitizeLocalUrl($this->P['returnUrl']));
216  }
217 
218  if ($this->returnEditConf) {
219  if ($this->processDataFlag) {
220  // Because OnTheFly can't handle MM relations with intermediate tables we use TcaDatabaseRecord here
221  // Otherwise already stored relations are overwritten with the new entry
223  $formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class);
225  $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
226  $input = [
227  'tableName' => $this->P['table'],
228  'vanillaUid' => (int)$this->P['uid'],
229  'command' => 'edit',
230  ];
231  $result = $formDataCompiler->compile($input);
232  $currentParentRow = $result['databaseRow'];
233 
234  // If that record was found (should absolutely be...), then init DataHandler and set, prepend or append
235  // the record
236  if (is_array($currentParentRow)) {
238  $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
239  $data = [];
240  $recordId = $this->table . '_' . ‪$this->id;
241  // Setting the new field data:
242  // If the field is a flexForm field, work with the XML structure instead:
243  if ($this->P['flexFormPath']) {
244  // Current value of flexForm path:
245  $currentFlexFormData = $currentParentRow[$this->P['field']];
247  $flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
248  $currentFlexFormValueByPath = $flexFormTools->getArrayValueByPath(
249  $this->P['flexFormPath'],
250  $currentFlexFormData
251  );
252 
253  // Compile currentFlexFormData to functional string
254  $currentFlexFormValues = [];
255  foreach ($currentFlexFormValueByPath as $value) {
256  if (is_array($value)) {
257  // group fields are always resolved to array
258  $currentFlexFormValues[] = $value['table'] . '_' . $value['uid'];
259  } else {
260  // but select fields may be uids only
261  $currentFlexFormValues[] = $value;
262  }
263  }
264  $currentFlexFormValue = implode(',', $currentFlexFormValues);
265 
266  $insertValue = '';
267  switch ((string)$this->P['params']['setValue']) {
268  case 'set':
269  $insertValue = $recordId;
270  break;
271  case 'append':
272  $insertValue = $currentFlexFormValue . ',' . $recordId;
273  break;
274  case 'prepend':
275  $insertValue = $recordId . ',' . $currentFlexFormValue;
276  break;
277  }
278  $insertValue = implode(',', GeneralUtility::trimExplode(',', $insertValue, true));
279  $data[$this->P['table']][$this->P['uid']][$this->P['field']] = [];
280  $flexFormTools->setArrayValueByPath(
281  $this->P['flexFormPath'],
282  $data[$this->P['table']][$this->P['uid']][$this->P['field']],
283  $insertValue
284  );
285  } else {
286  $currentValue = $currentParentRow[$this->P['field']];
287 
288  // Normalize CSV values
289  if (!is_array($currentValue)) {
290  $currentValue = GeneralUtility::trimExplode(',', $currentValue, true);
291  }
292 
293  // Normalize all items to "<table>_<uid>" format
294  $currentValue = array_map(function ($item) {
295  // Handle per-item table for "group" elements
296  if (is_array($item)) {
297  $item = $item['table'] . '_' . $item['uid'];
298  } else {
299  $item = $this->table . '_' . $item;
300  }
301 
302  return $item;
303  }, $currentValue);
304 
305  switch ((string)$this->P['params']['setValue']) {
306  case 'set':
307  $currentValue = [$recordId];
308  break;
309  case 'append':
310  $currentValue[] = $recordId;
311  break;
312  case 'prepend':
313  array_unshift($currentValue, $recordId);
314  break;
315  }
316 
317  $data[$this->P['table']][$this->P['uid']][$this->P['field']] = implode(',', $currentValue);
318  }
319  // Submit the data:
320  $dataHandler->start($data, []);
321  $dataHandler->process_datamap();
322  }
323  }
324  // Return to the parent FormEngine record editing session:
325  return new RedirectResponse(GeneralUtility::sanitizeLocalUrl($this->P['returnUrl']));
326  }
327 
328  // Redirecting to FormEngine with instructions to create a new record
329  // AND when closing to return back with information about that records ID etc.
331  $normalizedParams = $request->getAttribute('normalizedParams');
333  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
334  $redirectUrl = (string)$uriBuilder->buildUriFromRoute('record_edit', [
335  'returnEditConf' => 1,
336  'edit[' . $this->P['params']['table'] . '][' . $this->pid . ']' => 'new',
337  'returnUrl' => $normalizedParams->getRequestUri(),
338  ]);
339 
340  return new RedirectResponse($redirectUrl);
341  }
342 }
‪TYPO3\CMS\Core\DataHandling\DataHandler
Definition: DataHandler.php:81
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$deprecatedPublicProperties
‪array $deprecatedPublicProperties
Definition: AddController.php:44
‪TYPO3\CMS\Backend\Controller\Wizard\AddController
Definition: AddController.php:38
‪TYPO3\CMS\Core\Localization\LanguageService\includeLLFile
‪mixed includeLLFile($fileRef, $setGlobal=true, $mergeLocalOntoDefault=false)
Definition: LanguageService.php:260
‪TYPO3\CMS\Backend\Controller\Wizard\AbstractWizardController\getLanguageService
‪LanguageService getLanguageService()
Definition: AbstractWizardController.php:77
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$table
‪string $table
Definition: AddController.php:76
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$pid
‪int $pid
Definition: AddController.php:70
‪TYPO3\CMS\Backend\Controller\Wizard\AbstractWizardController
Definition: AbstractWizardController.php:28
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$processDataFlag
‪int $processDataFlag
Definition: AddController.php:64
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$content
‪string $content
Definition: AddController.php:58
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$id
‪int $id
Definition: AddController.php:82
‪TYPO3\CMS\Backend\Controller\Wizard
Definition: AbstractWizardController.php:2
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\processRequest
‪ResponseInterface processRequest(ServerRequestInterface $request)
Definition: AddController.php:202
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\main
‪main()
Definition: AddController.php:124
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:35
‪TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools
Definition: FlexFormTools.php:36
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLiveVersionOfRecord
‪static array null getLiveVersionOfRecord($table, $uid, $fields=' *')
Definition: BackendUtility.php:4213
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$P
‪array $P
Definition: AddController.php:88
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$returnEditConf
‪string $returnEditConf
Definition: AddController.php:94
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\__construct
‪__construct()
Definition: AddController.php:99
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\init
‪init(ServerRequestInterface $request)
Definition: AddController.php:136
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:130
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:27
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\mainAction
‪ResponseInterface mainAction(ServerRequestInterface $request)
Definition: AddController.php:113
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:21
‪TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait
Definition: PublicPropertyDeprecationTrait.php:66
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTCEFORM_TSconfig
‪static array getTCEFORM_TSconfig($table, $row)
Definition: BackendUtility.php:3482
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Backend\Form\FormDataCompiler
Definition: FormDataCompiler.php:24
‪TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord
Definition: TcaDatabaseRecord.php:24
‪TYPO3\CMS\Core\Utility\HttpUtility\redirect
‪static redirect($url, $httpStatus=self::HTTP_STATUS_303)
Definition: HttpUtility.php:103