[BUGFIX] Invalid relations of MM records in workspaces
[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 * Copyright notice
6 *
7 * (c) 2014 Oliver Hader <oliver.hader@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 use TYPO3\CMS\Core\DataHandling\DataHandler;
28
29 /**
30 * DataHandler Actions
31 */
32 class ActionService {
33
34 /**
35 * @var DataHandler
36 */
37 protected $dataHandler;
38
39 /**
40 * @return DataHandler
41 */
42 public function getDataHander() {
43 return $this->dataHandler;
44 }
45
46 /**
47 * @param string $tableName
48 * @param integer $pageId
49 * @param array $recordData
50 * @return array
51 */
52 public function createNewRecord($tableName, $pageId, array $recordData) {
53 return $this->createNewRecords($pageId, array($tableName => $recordData));
54 }
55
56 /**
57 * @param integer $pageId
58 * @param array $tableRecordData
59 * @return array
60 */
61 public function createNewRecords($pageId, array $tableRecordData) {
62 $dataMap = array();
63 $newTableIds = array();
64 $currentUid = NULL;
65 $previousTableName = NULL;
66 $previousUid = NULL;
67 foreach ($tableRecordData as $tableName => $recordData) {
68 $recordData = $this->resolvePreviousUid($recordData, $currentUid);
69 if (!isset($recordData['pid'])) {
70 $recordData['pid'] = $pageId;
71 }
72 $currentUid = uniqid('NEW');
73 $newTableIds[$tableName][] = $currentUid;
74 $dataMap[$tableName][$currentUid] = $recordData;
75 if ($previousTableName !== NULL && $previousUid !== NULL) {
76 $dataMap[$previousTableName][$previousUid] = $this->resolveNextUid(
77 $dataMap[$previousTableName][$previousUid],
78 $currentUid
79 );
80 }
81 $previousTableName = $tableName;
82 $previousUid = $currentUid;
83 }
84 $this->createDataHandler();
85 $this->dataHandler->start($dataMap, array());
86 $this->dataHandler->process_datamap();
87
88 foreach ($newTableIds as $tableName => &$ids) {
89 foreach ($ids as &$id) {
90 if (!empty($this->dataHandler->substNEWwithIDs[$id])) {
91 $id = $this->dataHandler->substNEWwithIDs[$id];
92 }
93 }
94 }
95
96 return $newTableIds;
97 }
98
99 /**
100 * @param string $tableName
101 * @param integer $uid
102 * @param array $recordData
103 * @param NULL|array $deleteTableRecordIds
104 */
105 public function modifyRecord($tableName, $uid, array $recordData, array $deleteTableRecordIds = NULL) {
106 $dataMap = array(
107 $tableName => array(
108 $uid => $recordData,
109 ),
110 );
111 $commandMap = array();
112 if (!empty($deleteTableRecordIds)) {
113 foreach ($deleteTableRecordIds as $tableName => $recordIds) {
114 foreach ($recordIds as $recordId) {
115 $commandMap[$tableName][$recordId]['delete'] = TRUE;
116 }
117 }
118 }
119 $this->createDataHandler();
120 $this->dataHandler->start($dataMap, $commandMap);
121 $this->dataHandler->process_datamap();
122 if (!empty($commandMap)) {
123 $this->dataHandler->process_cmdmap();
124 }
125 }
126
127 /**
128 * @param integer $pageId
129 * @param array $tableRecordData
130 */
131 public function modifyRecords($pageId, array $tableRecordData) {
132 $dataMap = array();
133 $currentUid = NULL;
134 $previousTableName = NULL;
135 $previousUid = NULL;
136 foreach ($tableRecordData as $tableName => $recordData) {
137 if (empty($recordData['uid'])) {
138 continue;
139 }
140 $recordData = $this->resolvePreviousUid($recordData, $currentUid);
141 $currentUid = $recordData['uid'];
142 if ($recordData['uid'] === '__NEW') {
143 $recordData['pid'] = $pageId;
144 $currentUid = uniqid('NEW');
145 }
146 unset($recordData['uid']);
147 $dataMap[$tableName][$currentUid] = $recordData;
148 if ($previousTableName !== NULL && $previousUid !== NULL) {
149 $dataMap[$previousTableName][$previousUid] = $this->resolveNextUid(
150 $dataMap[$previousTableName][$previousUid],
151 $currentUid
152 );
153 }
154 $previousTableName = $tableName;
155 $previousUid = $currentUid;
156 }
157 $this->createDataHandler();
158 $this->dataHandler->start($dataMap, array());
159 $this->dataHandler->process_datamap();
160 }
161
162 /**
163 * @param string $tableName
164 * @param integer $uid
165 * @return array
166 */
167 public function deleteRecord($tableName, $uid) {
168 return $this->deleteRecords(
169 array(
170 $tableName => array($uid),
171 )
172 );
173 }
174
175 /**
176 * @param array $tableRecordIds
177 * @return array
178 */
179 public function deleteRecords(array $tableRecordIds) {
180 $commandMap = array();
181 foreach ($tableRecordIds as $tableName => $ids) {
182 foreach ($ids as $uid) {
183 $commandMap[$tableName][$uid] = array(
184 'delete' => TRUE,
185 );
186 }
187 }
188 $this->createDataHandler();
189 $this->dataHandler->start(array(), $commandMap);
190 $this->dataHandler->process_cmdmap();
191 // Deleting workspace records is actually a copy(!)
192 return $this->dataHandler->copyMappingArray;
193 }
194
195 /**
196 * @param string $tableName
197 * @param integer $uid
198 */
199 public function clearWorkspaceRecord($tableName, $uid) {
200 $this->clearWorkspaceRecords(
201 array(
202 $tableName => array($uid),
203 )
204 );
205 }
206
207 /**
208 * @param array $tableRecordIds
209 */
210 public function clearWorkspaceRecords(array $tableRecordIds) {
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 integer $uid
229 * @param integer $pageId
230 * @return array
231 */
232 public function copyRecord($tableName, $uid, $pageId) {
233 $commandMap = array(
234 $tableName => array(
235 $uid => array(
236 'copy' => $pageId,
237 ),
238 ),
239 );
240 $this->createDataHandler();
241 $this->dataHandler->start(array(), $commandMap);
242 $this->dataHandler->process_cmdmap();
243 return $this->dataHandler->copyMappingArray;
244 }
245
246 /**
247 * @param string $tableName
248 * @param integer $uid
249 * @param integer $pageId
250 */
251 public function moveRecord($tableName, $uid, $pageId) {
252 $commandMap = array(
253 $tableName => array(
254 $uid => array(
255 'move' => $pageId,
256 ),
257 ),
258 );
259 $this->createDataHandler();
260 $this->dataHandler->start(array(), $commandMap);
261 $this->dataHandler->process_cmdmap();
262 }
263
264 /**
265 * @param string $tableName
266 * @param integer $uid
267 * @param integer $languageId
268 * @return array
269 */
270 public function localizeRecord($tableName, $uid, $languageId) {
271 $commandMap = array(
272 $tableName => array(
273 $uid => array(
274 'localize' => $languageId,
275 ),
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 integer $uid
287 * @param string $fieldName
288 * @param array $referenceIds
289 */
290 public function modifyReferences($tableName, $uid, $fieldName, array $referenceIds) {
291 $dataMap = array(
292 $tableName => array(
293 $uid => array(
294 $fieldName => implode(',', $referenceIds),
295 ),
296 )
297 );
298 $this->createDataHandler();
299 $this->dataHandler->start($dataMap, array());
300 $this->dataHandler->process_datamap();
301 }
302
303 /**
304 * @param string $tableName
305 * @param int $liveUid
306 * @param bool $throwException
307 */
308 public function publishRecord($tableName, $liveUid, $throwException = TRUE) {
309 $this->publishRecords(array($tableName => array($liveUid)), $throwException);
310 }
311
312 /**
313 * @param array $tableLiveUids
314 * @param bool $throwException
315 * @throws \TYPO3\CMS\Core\Tests\Exception
316 */
317 public function publishRecords(array $tableLiveUids, $throwException = TRUE) {
318 $commandMap = array();
319 foreach ($tableLiveUids as $tableName => $liveUids) {
320 foreach ($liveUids as $liveUid) {
321 $versionedUid = $this->getVersionedId($tableName, $liveUid);
322 if (empty($versionedUid)) {
323 if ($throwException) {
324 throw new \TYPO3\CMS\Core\Tests\Exception('Versioned UID could not be determined');
325 } else {
326 continue;
327 }
328 }
329
330 $commandMap[$tableName][$liveUid] = array(
331 'version' => array(
332 'action' => 'swap',
333 'swapWith' => $versionedUid,
334 'notificationAlternativeRecipients' => array(),
335 ),
336 );
337 }
338 }
339 $this->createDataHandler();
340 $this->dataHandler->start(array(), $commandMap);
341 $this->dataHandler->process_cmdmap();
342 }
343
344 /**
345 * @param int $workspaceId
346 */
347 public function publishWorkspace($workspaceId) {
348 $commandMap = $this->getWorkspaceService()->getCmdArrayForPublishWS($workspaceId, FALSE);
349 $this->createDataHandler();
350 $this->dataHandler->start(array(), $commandMap);
351 $this->dataHandler->process_cmdmap();
352 }
353
354 /**
355 * @param int $workspaceId
356 */
357 public function swapWorkspace($workspaceId) {
358 $commandMap = $this->getWorkspaceService()->getCmdArrayForPublishWS($workspaceId, TRUE);
359 $this->createDataHandler();
360 $this->dataHandler->start(array(), $commandMap);
361 $this->dataHandler->process_cmdmap();
362 }
363
364 /**
365 * @param array $recordData
366 * @param NULL|string|int $previousUid
367 * @return array
368 */
369 protected function resolvePreviousUid(array $recordData, $previousUid) {
370 if ($previousUid === NULL) {
371 return $recordData;
372 }
373 foreach ($recordData as $fieldName => $fieldValue) {
374 if (strpos($fieldValue, '__previousUid') === FALSE) {
375 continue;
376 }
377 $recordData[$fieldName] = str_replace('__previousUid', $previousUid, $fieldValue);
378 }
379 return $recordData;
380 }
381
382 /**
383 * @param array $recordData
384 * @param NULL|string|int $nextUid
385 * @return array
386 */
387 protected function resolveNextUid(array $recordData, $nextUid) {
388 if ($nextUid === NULL) {
389 return $recordData;
390 }
391 foreach ($recordData as $fieldName => $fieldValue) {
392 if (strpos($fieldValue, '__nextUid') === FALSE) {
393 continue;
394 }
395 $recordData[$fieldName] = str_replace('__nextUid', $nextUid, $fieldValue);
396 }
397 return $recordData;
398 }
399
400 /**
401 * @param string $tableName
402 * @param int $liveUid
403 * @param bool $useDeleteClause
404 * @return NULL|int
405 */
406 protected function getVersionedId($tableName, $liveUid, $useDeleteClause = FALSE) {
407 $versionedId = NULL;
408 $liveUid = (int)$liveUid;
409 $workspaceId = (int)$this->getBackendUser()->workspace;
410 $row = $this->getDatabaseConnection()->exec_SELECTgetSingleRow(
411 'uid',
412 $tableName,
413 'pid=-1 AND t3ver_oid=' . $liveUid . ' AND t3ver_wsid=' . $workspaceId .
414 ($useDeleteClause ? \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause($tableName) : '')
415 );
416 if (!empty($row['uid'])) {
417 $versionedId = (int)$row['uid'];
418 }
419 return $versionedId;
420 }
421
422 /**
423 * @return \TYPO3\CMS\Core\DataHandling\DataHandler
424 */
425 protected function createDataHandler() {
426 $dataHandler = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
427 'TYPO3\\CMS\\Core\\DataHandling\\DataHandler'
428 );
429 $this->dataHandler = $dataHandler;
430 return $dataHandler;
431 }
432
433 /**
434 * @return \TYPO3\CMS\Workspaces\Service\WorkspaceService
435 */
436 protected function getWorkspaceService() {
437 return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
438 'TYPO3\\CMS\\Workspaces\\Service\\WorkspaceService'
439 );
440 }
441
442 /**
443 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
444 */
445 protected function getBackendUser() {
446 return $GLOBALS['BE_USER'];
447 }
448
449 /**
450 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
451 */
452 protected function getDatabaseConnection() {
453 return $GLOBALS['TYPO3_DB'];
454 }
455
456 }