‪TYPO3CMS  ‪main
AddController.php
Go to the documentation of this file.
1 <?php
2 
3 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 
19 
20 use Psr\Http\Message\ResponseInterface;
21 use Psr\Http\Message\ServerRequestInterface;
26 use TYPO3\CMS\Backend\Utility\BackendUtility;
32 
39 #[AsController]
41 {
45  protected int ‪$processDataFlag = 0;
46 
50  protected int ‪$pid = 0;
51 
55  protected string ‪$table = '';
56 
60  protected int ‪$id = 0;
61 
65  protected array ‪$P = [];
66 
70  protected string ‪$returnEditConf = '';
71 
72  public function ‪__construct(
73  private readonly ‪FormDataCompiler $formDataCompiler,
74  ) {}
75 
80  public function ‪mainAction(ServerRequestInterface $request): ResponseInterface
81  {
82  $this->‪init($request);
83 
84  if ($this->returnEditConf) {
85  if ($this->processDataFlag) {
86  // Because OnTheFly can't handle MM relations with intermediate tables we use TcaDatabaseRecord here
87  // Otherwise already stored relations are overwritten with the new entry
88  $input = [
89  'request' => $request,
90  'tableName' => $this->P['table'],
91  'vanillaUid' => (int)$this->P['uid'],
92  'command' => 'edit',
93  ];
94  $result = $this->formDataCompiler->compile($input, GeneralUtility::makeInstance(TcaDatabaseRecord::class));
95  $currentParentRow = $result['databaseRow'];
96 
97  // If that record was found (should absolutely be...), then init DataHandler and set, prepend or append
98  // the record
99  if (is_array($currentParentRow)) {
100  $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
101  $data = [];
102  $recordId = $this->table . '_' . ‪$this->id;
103  // Setting the new field data:
104  // If the field is a flexForm field, work with the XML structure instead:
105  if ($this->P['flexFormPath']) {
106  // Current value of flexForm path:
107  $currentFlexFormData = $currentParentRow[$this->P['field']];
108  $currentFlexFormValueByPath = ‪ArrayUtility::getValueByPath($currentFlexFormData, $this->P['flexFormPath']);
109 
110  // Compile currentFlexFormData to functional string
111  $currentFlexFormValues = [];
112  foreach ($currentFlexFormValueByPath as $value) {
113  if (is_array($value)) {
114  // group fields are always resolved to array
115  $currentFlexFormValues[] = $value['table'] . '_' . $value['uid'];
116  } else {
117  // but select fields may be uids only
118  $currentFlexFormValues[] = $value;
119  }
120  }
121  $currentFlexFormValue = implode(',', $currentFlexFormValues);
122 
123  $insertValue = '';
124  switch ((string)$this->P['params']['setValue']) {
125  case 'set':
126  $insertValue = $recordId;
127  break;
128  case 'append':
129  $insertValue = $currentFlexFormValue . ',' . $recordId;
130  break;
131  case 'prepend':
132  $insertValue = $recordId . ',' . $currentFlexFormValue;
133  break;
134  }
135  $insertValue = implode(',', ‪GeneralUtility::trimExplode(',', $insertValue, true));
136  $data[$this->P['table']][$this->P['uid']][$this->P['field']] = ‪ArrayUtility::setValueByPath([], $this->P['flexFormPath'], $insertValue);
137  } else {
138  $currentValue = $currentParentRow[$this->P['field']];
139 
140  // Normalize CSV values
141  if (!is_array($currentValue)) {
142  $currentValue = ‪GeneralUtility::trimExplode(',', $currentValue, true);
143  }
144 
145  // Normalize all items to "<table>_<uid>" format
146  $currentValue = array_map(function (array|int|string $item): string {
147  // Handle per-item table for "group" elements
148  if (is_array($item)) {
149  $item = $item['table'] . '_' . $item['uid'];
150  } else {
151  $item = $this->table . '_' . $item;
152  }
153 
154  return $item;
155  }, $currentValue);
156 
157  switch ((string)$this->P['params']['setValue']) {
158  case 'set':
159  $currentValue = [$recordId];
160  break;
161  case 'append':
162  $currentValue[] = $recordId;
163  break;
164  case 'prepend':
165  array_unshift($currentValue, $recordId);
166  break;
167  }
168 
169  $data[$this->P['table']][$this->P['uid']][$this->P['field']] = implode(',', $currentValue);
170  }
171  // Submit the data:
172  $dataHandler->start($data, []);
173  $dataHandler->process_datamap();
174  }
175  }
176  // Return to the parent FormEngine record editing session:
177  return new ‪RedirectResponse(GeneralUtility::sanitizeLocalUrl($this->P['returnUrl']));
178  }
179 
180  // Redirecting to FormEngine with instructions to create a new record
181  // AND when closing to return back with information about that records ID etc.
182  $normalizedParams = $request->getAttribute('normalizedParams');
183  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
184  $redirectUrl = (string)$uriBuilder->buildUriFromRoute('record_edit', [
185  'returnEditConf' => 1,
186  'edit[' . $this->P['params']['table'] . '][' . $this->pid . ']' => 'new',
187  'returnUrl' => $normalizedParams->getRequestUri(),
188  ]);
189 
190  return new ‪RedirectResponse($redirectUrl);
191  }
192 
196  protected function ‪init(ServerRequestInterface $request): void
197  {
198  $parsedBody = $request->getParsedBody();
199  $queryParams = $request->getQueryParams();
200  // Init GPvars:
201  $this->P = $parsedBody['P'] ?? $queryParams['P'] ?? [];
202  $this->returnEditConf = $parsedBody['returnEditConf'] ?? $queryParams['returnEditConf'] ?? '';
203  // Get this record
204  ‪$record = BackendUtility::getRecord($this->P['table'], $this->P['uid']);
205  // Set table:
206  $this->table = $this->P['params']['table'];
207  // Get TSconfig for it.
208  $TSconfig = BackendUtility::getTCEFORM_TSconfig(
209  $this->P['table'],
210  is_array(‪$record) ? ‪$record : ['pid' => (int)$this->P['params']['pid']]
211  );
212  // Set [params][pid]
213  if (str_starts_with($this->P['params']['pid'], '###') && str_ends_with($this->P['params']['pid'], '###')) {
214  $keyword = substr($this->P['params']['pid'], 3, -3);
215  $this->pid = str_starts_with($keyword, 'PAGE_TSCONFIG_')
216  ? (int)$TSconfig[$this->P['field']][$keyword]
217  : (int)$TSconfig['_' . $keyword];
218  } else {
219  $this->pid = (int)$this->P['params']['pid'];
220  }
221 
222  // If a new id has returned from a newly created record...
223  if ($this->returnEditConf) {
224  $editConfiguration = json_decode($this->returnEditConf, true);
225  if (is_array($editConfiguration[$this->table]) && ‪MathUtility::canBeInterpretedAsInteger($this->P['uid'])) {
226  // Getting id and cmd from returning editConf array.
227  reset($editConfiguration[$this->table]);
228  $this->id = (int)key($editConfiguration[$this->table]);
229  $cmd = current($editConfiguration[$this->table]);
230  // ... and if everything seems OK we will register some classes for inclusion and instruct the object
231  // to perform processing later.
232  if ($this->P['params']['setValue']
233  && $cmd === 'edit'
234  && $this->id
235  && $this->P['table']
236  && $this->P['field'] && $this->P['uid']
237  ) {
238  $liveRecord = BackendUtility::getLiveVersionOfRecord($this->table, $this->id, 'uid');
239  if ($liveRecord) {
240  $this->id = $liveRecord['uid'];
241  }
242  $this->processDataFlag = 1;
243  }
244  }
245  }
246  }
247 }
‪TYPO3\CMS\Core\DataHandling\DataHandler
Definition: DataHandler.php:94
‪TYPO3\CMS\Backend\Controller\Wizard\AddController
Definition: AddController.php:41
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$table
‪string $table
Definition: AddController.php:55
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$pid
‪int $pid
Definition: AddController.php:50
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$processDataFlag
‪int $processDataFlag
Definition: AddController.php:45
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$id
‪int $id
Definition: AddController.php:60
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static getValueByPath(array $array, array|string $path, string $delimiter='/')
Definition: ArrayUtility.php:176
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger(mixed $var)
Definition: MathUtility.php:69
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\mainAction
‪mainAction(ServerRequestInterface $request)
Definition: AddController.php:80
‪TYPO3\CMS\Backend\Controller\Wizard
Definition: AddController.php:18
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\__construct
‪__construct(private readonly FormDataCompiler $formDataCompiler,)
Definition: AddController.php:72
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:44
‪TYPO3\CMS\Webhooks\Message\$record
‪identifier readonly int readonly array $record
Definition: PageModificationMessage.php:36
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$P
‪array $P
Definition: AddController.php:65
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\$returnEditConf
‪string $returnEditConf
Definition: AddController.php:70
‪TYPO3\CMS\Backend\Controller\Wizard\AddController\init
‪init(ServerRequestInterface $request)
Definition: AddController.php:196
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:30
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:26
‪TYPO3\CMS\Core\Utility\ArrayUtility\setValueByPath
‪static array setValueByPath(array $array, string|array|\ArrayAccess $path, mixed $value, string $delimiter='/')
Definition: ArrayUtility.php:261
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Backend\Attribute\AsController
Definition: AsController.php:25
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Backend\Form\FormDataCompiler
Definition: FormDataCompiler.php:26
‪TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord
Definition: TcaDatabaseRecord.php:25
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode(string $delim, string $string, bool $removeEmptyValues=false, int $limit=0)
Definition: GeneralUtility.php:822