08345289459efa6ba1419ef9955a80306d603f49
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Functional / DataHandling / Framework / ActionService.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Functional\DataHandling\Framework;
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
17 use TYPO3\CMS\Core\DataHandling\DataHandler;
18 use TYPO3\CMS\Core\Utility\StringUtility;
19
20 /**
21 * DataHandler Actions
22 */
23 class ActionService
24 {
25 /**
26 * @var DataHandler
27 */
28 protected $dataHandler;
29
30 /**
31 * @return DataHandler
32 */
33 public function getDataHandler()
34 {
35 return $this->dataHandler;
36 }
37
38 /**
39 * @param string $tableName
40 * @param int $pageId
41 * @param array $recordData
42 * @return array
43 */
44 public function createNewRecord($tableName, $pageId, array $recordData)
45 {
46 return $this->createNewRecords($pageId, array($tableName => $recordData));
47 }
48
49 /**
50 * @param int $pageId
51 * @param array $tableRecordData
52 * @return array
53 */
54 public function createNewRecords($pageId, array $tableRecordData)
55 {
56 $dataMap = array();
57 $newTableIds = array();
58 $currentUid = null;
59 $previousTableName = null;
60 $previousUid = null;
61 foreach ($tableRecordData as $tableName => $recordData) {
62 $recordData = $this->resolvePreviousUid($recordData, $currentUid);
63 if (!isset($recordData['pid'])) {
64 $recordData['pid'] = $pageId;
65 }
66 $currentUid = StringUtility::getUniqueId('NEW');
67 $newTableIds[$tableName][] = $currentUid;
68 $dataMap[$tableName][$currentUid] = $recordData;
69 if ($previousTableName !== null && $previousUid !== null) {
70 $dataMap[$previousTableName][$previousUid] = $this->resolveNextUid(
71 $dataMap[$previousTableName][$previousUid],
72 $currentUid
73 );
74 }
75 $previousTableName = $tableName;
76 $previousUid = $currentUid;
77 }
78 $this->createDataHandler();
79 $this->dataHandler->start($dataMap, array());
80 $this->dataHandler->process_datamap();
81
82 foreach ($newTableIds as $tableName => &$ids) {
83 foreach ($ids as &$id) {
84 if (!empty($this->dataHandler->substNEWwithIDs[$id])) {
85 $id = $this->dataHandler->substNEWwithIDs[$id];
86 }
87 }
88 }
89
90 return $newTableIds;
91 }
92
93 /**
94 * @param string $tableName
95 * @param int $uid
96 * @param array $recordData
97 * @param NULL|array $deleteTableRecordIds
98 */
99 public function modifyRecord($tableName, $uid, array $recordData, array $deleteTableRecordIds = null)
100 {
101 $dataMap = array(
102 $tableName => array(
103 $uid => $recordData,
104 ),
105 );
106 $commandMap = array();
107 if (!empty($deleteTableRecordIds)) {
108 foreach ($deleteTableRecordIds as $tableName => $recordIds) {
109 foreach ($recordIds as $recordId) {
110 $commandMap[$tableName][$recordId]['delete'] = true;
111 }
112 }
113 }
114 $this->createDataHandler();
115 $this->dataHandler->start($dataMap, $commandMap);
116 $this->dataHandler->process_datamap();
117 if (!empty($commandMap)) {
118 $this->dataHandler->process_cmdmap();
119 }
120 }
121
122 /**
123 * @param int $pageId
124 * @param array $tableRecordData
125 */
126 public function modifyRecords($pageId, array $tableRecordData)
127 {
128 $dataMap = array();
129 $currentUid = null;
130 $previousTableName = null;
131 $previousUid = null;
132 foreach ($tableRecordData as $tableName => $recordData) {
133 if (empty($recordData['uid'])) {
134 continue;
135 }
136 $recordData = $this->resolvePreviousUid($recordData, $currentUid);
137 $currentUid = $recordData['uid'];
138 if ($recordData['uid'] === '__NEW') {
139 $recordData['pid'] = $pageId;
140 $currentUid = StringUtility::getUniqueId('NEW');
141 }
142 unset($recordData['uid']);
143 $dataMap[$tableName][$currentUid] = $recordData;
144 if ($previousTableName !== null && $previousUid !== null) {
145 $dataMap[$previousTableName][$previousUid] = $this->resolveNextUid(
146 $dataMap[$previousTableName][$previousUid],
147 $currentUid
148 );
149 }
150 $previousTableName = $tableName;
151 $previousUid = $currentUid;
152 }
153 $this->createDataHandler();
154 $this->dataHandler->start($dataMap, array());
155 $this->dataHandler->process_datamap();
156 }
157
158 /**
159 * @param string $tableName
160 * @param int $uid
161 * @return array
162 */
163 public function deleteRecord($tableName, $uid)
164 {
165 return $this->deleteRecords(
166 array(
167 $tableName => array($uid),
168 )
169 );
170 }
171
172 /**
173 * @param array $tableRecordIds
174 * @return array
175 */
176 public function deleteRecords(array $tableRecordIds)
177 {
178 $commandMap = array();
179 foreach ($tableRecordIds as $tableName => $ids) {
180 foreach ($ids as $uid) {
181 $commandMap[$tableName][$uid] = array(
182 'delete' => true,
183 );
184 }
185 }
186 $this->createDataHandler();
187 $this->dataHandler->start(array(), $commandMap);
188 $this->dataHandler->process_cmdmap();
189 // Deleting workspace records is actually a copy(!)
190 return $this->dataHandler->copyMappingArray;
191 }
192
193 /**
194 * @param string $tableName
195 * @param int $uid
196 */
197 public function clearWorkspaceRecord($tableName, $uid)
198 {
199 $this->clearWorkspaceRecords(
200 array(
201 $tableName => array($uid),
202 )
203 );
204 }
205
206 /**
207 * @param array $tableRecordIds
208 */
209 public function clearWorkspaceRecords(array $tableRecordIds)
210 {
211 $commandMap = array();
212 foreach ($tableRecordIds as $tableName => $ids) {
213 foreach ($ids as $uid) {
214 $commandMap[$tableName][$uid] = array(
215 'version' => array(
216 'action' => 'clearWSID',
217 )
218 );
219 }
220 }
221 $this->createDataHandler();
222 $this->dataHandler->start(array(), $commandMap);
223 $this->dataHandler->process_cmdmap();
224 }
225
226 /**
227 * @param string $tableName
228 * @param int $uid
229 * @param int $pageId
230 * @param NULL|array $recordData
231 * @return array
232 */
233 public function copyRecord($tableName, $uid, $pageId, array $recordData = null)
234 {
235 $commandMap = array(
236 $tableName => array(
237 $uid => array(
238 'copy' => $pageId,
239 ),
240 ),
241 );
242 if ($recordData !== null) {
243 $commandMap[$tableName][$uid]['copy'] = array(
244 'action' => 'paste',
245 'target' => $pageId,
246 'update' => $recordData,
247 );
248 }
249 $this->createDataHandler();
250 $this->dataHandler->start(array(), $commandMap);
251 $this->dataHandler->process_cmdmap();
252 return $this->dataHandler->copyMappingArray;
253 }
254
255 /**
256 * @param string $tableName
257 * @param int $uid
258 * @param int $pageId
259 * @param NULL|array $recordData
260 * @return array
261 */
262 public function moveRecord($tableName, $uid, $pageId, array $recordData = null)
263 {
264 $commandMap = array(
265 $tableName => array(
266 $uid => array(
267 'move' => $pageId,
268 ),
269 ),
270 );
271 if ($recordData !== null) {
272 $commandMap[$tableName][$uid]['move'] = array(
273 'action' => 'paste',
274 'target' => $pageId,
275 'update' => $recordData,
276 );
277 }
278 $this->createDataHandler();
279 $this->dataHandler->start(array(), $commandMap);
280 $this->dataHandler->process_cmdmap();
281 return $this->dataHandler->copyMappingArray;
282 }
283
284 /**
285 * @param string $tableName
286 * @param int $uid
287 * @param int $languageId
288 * @return array
289 */
290 public function localizeRecord($tableName, $uid, $languageId)
291 {
292 $commandMap = array(
293 $tableName => array(
294 $uid => array(
295 'localize' => $languageId,
296 ),
297 ),
298 );
299 $this->createDataHandler();
300 $this->dataHandler->start(array(), $commandMap);
301 $this->dataHandler->process_cmdmap();
302 return $this->dataHandler->copyMappingArray;
303 }
304
305 /**
306 * @param string $tableName
307 * @param int $uid
308 * @param string $fieldName
309 * @param array $referenceIds
310 */
311 public function modifyReferences($tableName, $uid, $fieldName, array $referenceIds)
312 {
313 $dataMap = array(
314 $tableName => array(
315 $uid => array(
316 $fieldName => implode(',', $referenceIds),
317 ),
318 )
319 );
320 $this->createDataHandler();
321 $this->dataHandler->start($dataMap, array());
322 $this->dataHandler->process_datamap();
323 }
324
325 /**
326 * @param string $tableName
327 * @param int $liveUid
328 * @param bool $throwException
329 */
330 public function publishRecord($tableName, $liveUid, $throwException = true)
331 {
332 $this->publishRecords(array($tableName => array($liveUid)), $throwException);
333 }
334
335 /**
336 * @param array $tableLiveUids
337 * @param bool $throwException
338 * @throws \TYPO3\CMS\Core\Tests\Exception
339 */
340 public function publishRecords(array $tableLiveUids, $throwException = true)
341 {
342 $commandMap = array();
343 foreach ($tableLiveUids as $tableName => $liveUids) {
344 foreach ($liveUids as $liveUid) {
345 $versionedUid = $this->getVersionedId($tableName, $liveUid);
346 if (empty($versionedUid)) {
347 if ($throwException) {
348 throw new \TYPO3\CMS\Core\Tests\Exception('Versioned UID could not be determined');
349 } else {
350 continue;
351 }
352 }
353
354 $commandMap[$tableName][$liveUid] = array(
355 'version' => array(
356 'action' => 'swap',
357 'swapWith' => $versionedUid,
358 'notificationAlternativeRecipients' => array(),
359 ),
360 );
361 }
362 }
363 $this->createDataHandler();
364 $this->dataHandler->start(array(), $commandMap);
365 $this->dataHandler->process_cmdmap();
366 }
367
368 /**
369 * @param int $workspaceId
370 */
371 public function publishWorkspace($workspaceId)
372 {
373 $commandMap = $this->getWorkspaceService()->getCmdArrayForPublishWS($workspaceId, false);
374 $this->createDataHandler();
375 $this->dataHandler->start(array(), $commandMap);
376 $this->dataHandler->process_cmdmap();
377 }
378
379 /**
380 * @param int $workspaceId
381 */
382 public function swapWorkspace($workspaceId)
383 {
384 $commandMap = $this->getWorkspaceService()->getCmdArrayForPublishWS($workspaceId, true);
385 $this->createDataHandler();
386 $this->dataHandler->start(array(), $commandMap);
387 $this->dataHandler->process_cmdmap();
388 }
389
390 /**
391 * @param array $recordData
392 * @param NULL|string|int $previousUid
393 * @return array
394 */
395 protected function resolvePreviousUid(array $recordData, $previousUid)
396 {
397 if ($previousUid === null) {
398 return $recordData;
399 }
400 foreach ($recordData as $fieldName => $fieldValue) {
401 if (strpos($fieldValue, '__previousUid') === false) {
402 continue;
403 }
404 $recordData[$fieldName] = str_replace('__previousUid', $previousUid, $fieldValue);
405 }
406 return $recordData;
407 }
408
409 /**
410 * @param array $recordData
411 * @param NULL|string|int $nextUid
412 * @return array
413 */
414 protected function resolveNextUid(array $recordData, $nextUid)
415 {
416 if ($nextUid === null) {
417 return $recordData;
418 }
419 foreach ($recordData as $fieldName => $fieldValue) {
420 if (strpos($fieldValue, '__nextUid') === false) {
421 continue;
422 }
423 $recordData[$fieldName] = str_replace('__nextUid', $nextUid, $fieldValue);
424 }
425 return $recordData;
426 }
427
428 /**
429 * @param string $tableName
430 * @param int $liveUid
431 * @param bool $useDeleteClause
432 * @return NULL|int
433 */
434 protected function getVersionedId($tableName, $liveUid, $useDeleteClause = false)
435 {
436 $versionedId = null;
437 $liveUid = (int)$liveUid;
438 $workspaceId = (int)$this->getBackendUser()->workspace;
439 $row = $this->getDatabaseConnection()->exec_SELECTgetSingleRow(
440 'uid',
441 $tableName,
442 'pid=-1 AND t3ver_oid=' . $liveUid . ' AND t3ver_wsid=' . $workspaceId .
443 ($useDeleteClause ? \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause($tableName) : '')
444 );
445 if (!empty($row['uid'])) {
446 $versionedId = (int)$row['uid'];
447 }
448 return $versionedId;
449 }
450
451 /**
452 * @return DataHandler
453 */
454 protected function createDataHandler()
455 {
456 $this->dataHandler = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(DataHandler::class);
457 $backendUser = $this->getBackendUser();
458 if (isset($backendUser->uc['copyLevels'])) {
459 $this->dataHandler->copyTree = $backendUser->uc['copyLevels'];
460 }
461 return $this->dataHandler;
462 }
463
464 /**
465 * @return \TYPO3\CMS\Workspaces\Service\WorkspaceService
466 */
467 protected function getWorkspaceService()
468 {
469 return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
470 \TYPO3\CMS\Workspaces\Service\WorkspaceService::class
471 );
472 }
473
474 /**
475 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
476 */
477 protected function getBackendUser()
478 {
479 return $GLOBALS['BE_USER'];
480 }
481
482 /**
483 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
484 */
485 protected function getDatabaseConnection()
486 {
487 return $GLOBALS['TYPO3_DB'];
488 }
489 }