[BUGFIX] Use MM_oppositeUsage for category relations
[Packages/TYPO3.CMS.git] / typo3 / sysext / workspaces / Tests / Functional / DataHandling / ManyToMany / AbstractActionTestCase.php
1 <?php
2 namespace TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\ManyToMany;
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 require_once __DIR__ . '/../../../../../core/Tests/Functional/DataHandling/AbstractDataHandlerActionTestCase.php';
28
29 /**
30 * Functional test for the DataHandler
31 */
32 abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\AbstractDataHandlerActionTestCase {
33
34 const VALUE_PageId = 89;
35 const VALUE_PageIdTarget = 90;
36 const VALUE_ContentIdFirst = 297;
37 const VALUE_ContentIdLast = 298;
38 const VALUE_LanguageId = 1;
39 const VALUE_CategoryIdFirst = 28;
40 const VALUE_CategoryIdSecond = 29;
41 const VALUE_WorkspaceId = 1;
42
43 const TABLE_Content = 'tt_content';
44 const TABLE_Category = 'sys_category';
45 const TABLE_ContentCategory_ManyToMany = 'sys_category_record_mm';
46
47 /**
48 * @var string
49 */
50 protected $dataSetDirectory = 'typo3/sysext/workspaces/Tests/Functional/DataHandling/ManyToMany/DataSet/';
51
52 /**
53 * @var array
54 */
55 protected $coreExtensionsToLoad = array(
56 'version',
57 'workspaces',
58 );
59
60 public function setUp() {
61 parent::setUp();
62 $this->importScenarioDataSet('LiveDefaultPages');
63 $this->importScenarioDataSet('LiveDefaultElements');
64
65 $this->setUpFrontendRootPage(1, array('typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.ts'));
66 }
67
68 /**
69 * MM Relations
70 */
71
72 /**
73 * @test
74 */
75 public function addCategoryRelation() {
76 $this->actionService->modifyReferences(
77 self::TABLE_Content, self::VALUE_ContentIdFirst, 'categories', array(self::VALUE_CategoryIdFirst, self::VALUE_CategoryIdSecond, 31)
78 );
79 $this->assertAssertionDataSet('addCategoryRelation');
80
81 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
82 $this->assertResponseContentStructureHasRecords(
83 $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
84 self::TABLE_Category, 'title', array('Category A', 'Category B', 'Category A.A')
85 );
86 }
87
88 /**
89 * @test
90 */
91 public function deleteCategoryRelation() {
92 $this->actionService->modifyReferences(
93 self::TABLE_Content, self::VALUE_ContentIdFirst, 'categories', array(self::VALUE_CategoryIdFirst)
94 );
95 $this->assertAssertionDataSet('deleteCategoryRelation');
96
97 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
98 $this->assertResponseContentStructureHasRecords(
99 $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
100 self::TABLE_Category, 'title', array('Category A')
101 );
102 $this->assertResponseContentStructureDoesNotHaveRecords(
103 $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
104 self::TABLE_Category, 'title', array('Category B', 'Category C', 'Category A.A')
105 );
106 }
107
108 /**
109 * @test
110 */
111 public function changeCategoryRelationSorting() {
112 $this->actionService->modifyReferences(
113 self::TABLE_Content, self::VALUE_ContentIdFirst, 'categories', array(self::VALUE_CategoryIdSecond, self::VALUE_CategoryIdFirst)
114 );
115 $this->assertAssertionDataSet('changeCategoryRelationSorting');
116
117 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
118 $this->assertResponseContentStructureHasRecords(
119 $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
120 self::TABLE_Category, 'title', array('Category A', 'Category B')
121 );
122 }
123
124 /**
125 * @test
126 */
127 public function createContentRecordAndAddCategoryRelation() {
128 $newTableIds = $this->actionService->createNewRecord(
129 self::TABLE_Content, self::VALUE_PageId, array('header' => 'Testing #1', 'categories' => self::VALUE_CategoryIdSecond)
130 );
131 $this->assertAssertionDataSet('createContentRecordAndAddCategoryRelation');
132
133 $newContentId = $newTableIds[self::TABLE_Content][0];
134 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
135 $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
136 $this->assertResponseContentStructureHasRecords(
137 $responseContent, self::TABLE_Content . ':' . $newContentId, 'categories',
138 self::TABLE_Category, 'title', 'Category B'
139 );
140 }
141
142 /**
143 * @test
144 */
145 public function createCategoryRecordAndAddCategoryRelation() {
146 $this->actionService->createNewRecord(
147 self::TABLE_Category, 0, array('title' => 'Testing #1', 'items' => 'tt_content_' . self::VALUE_ContentIdFirst)
148 );
149 $this->assertAssertionDataSet('createCategoryRecordAndAddCategoryRelation');
150
151 // @todo Does not work due to the core bug of not setting the reference field in the MM record
152 /*
153 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
154 $this->assertResponseContentHasRecords($responseContent, self::TABLE_Category, 'title', 'Testing #1');
155 $this->assertResponseContentStructureHasRecords(
156 $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
157 self::TABLE_Category, 'title', 'Testing #1'
158 );
159 */
160 }
161
162 /**
163 * @test
164 */
165 public function createContentRecordAndCreateCategoryRelation() {
166 $newTableIds = $this->actionService->createNewRecords(
167 self::VALUE_PageId,
168 array(
169 self::TABLE_Category => array('title' => 'Testing #1'),
170 self::TABLE_Content => array('header' => 'Testing #1', 'categories' => '__previousUid'),
171 )
172 );
173 $this->assertAssertionDataSet('createContentRecordAndCreateCategoryRelation');
174
175 $newContentId = $newTableIds[self::TABLE_Content][0];
176 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
177 $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
178
179 // @todo New category is not resolved in new content element due to core bug
180 // The frontend query ignores pid=-1 and thus the specific workspace record in sys_category:33
181 /*
182 $this->assertResponseContentStructureHasRecords(
183 $responseContent, self::TABLE_Content . ':' . $newContentId, 'categories',
184 self::TABLE_Category, 'title', 'Testing #1'
185 );
186 */
187 }
188
189 /**
190 * @test
191 */
192 public function createCategoryRecordAndCreateCategoryRelation() {
193 $this->markTestSkipped('The new content record cannot be referenced in the new category record');
194 $this->actionService->createNewRecords(
195 self::VALUE_PageId,
196 array(
197 self::TABLE_Content => array('header' => 'Testing #1',),
198 self::TABLE_Category => array('title' => 'Testing #1', 'items' => 'tt_content___previousUid'),
199 )
200 );
201 $this->assertAssertionDataSet('createCategoryRecordAndCreateCategoryRelation');
202 }
203
204 /**
205 * @test
206 */
207 public function modifyCategoryRecordOfCategoryRelation() {
208 $this->actionService->modifyRecord(self::TABLE_Category, self::VALUE_CategoryIdFirst, array('title' => 'Testing #1'));
209 $this->assertAssertionDataSet('modifyCategoryRecordOfCategoryRelation');
210
211 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
212 $this->assertResponseContentStructureHasRecords(
213 $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
214 self::TABLE_Category, 'title', array('Testing #1', 'Category B')
215 );
216 }
217
218 /**
219 * @test
220 */
221 public function modifyContentRecordOfCategoryRelation() {
222 $this->actionService->modifyRecord(self::TABLE_Content, self::VALUE_ContentIdFirst, array('header' => 'Testing #1'));
223 $this->assertAssertionDataSet('modifyContentRecordOfCategoryRelation');
224
225 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
226 $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
227 }
228
229 /**
230 * @test
231 */
232 public function modifyBothRecordsOfCategoryRelation() {
233 $this->markTestSkipped('Using specific UIDs on both sides is not implemented yet');
234 $this->actionService->modifyRecord(self::TABLE_Category, self::VALUE_CategoryIdFirst, array('title' => 'Testing #1'));
235 $this->actionService->modifyRecord(self::TABLE_Content, self::VALUE_ContentIdFirst, array('header' => 'Testing #1'));
236 $this->assertAssertionDataSet('modifyBothRecordsOfCategoryRelation');
237
238 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
239 $this->assertResponseContentStructureHasRecords(
240 $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
241 self::TABLE_Category, 'title', array('Testing #1', 'Category B')
242 );
243 $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
244 }
245
246 /**
247 * @test
248 */
249 public function deleteContentRecordOfCategoryRelation() {
250 $this->actionService->deleteRecord(self::TABLE_Content, self::VALUE_ContentIdLast);
251 $this->assertAssertionDataSet('deleteContentRecordOfCategoryRelation');
252
253 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
254 $this->assertResponseContentDoesNotHaveRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
255 }
256
257 /**
258 * @test
259 */
260 public function deleteCategoryRecordOfCategoryRelation() {
261 $this->actionService->deleteRecord(self::TABLE_Category, self::VALUE_CategoryIdFirst);
262 $this->assertAssertionDataSet('deleteCategoryRecordOfCategoryRelation');
263
264 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
265 $this->assertResponseContentStructureDoesNotHaveRecords(
266 $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
267 self::TABLE_Category, 'title', array('Category A')
268 );
269 }
270
271 /**
272 * @test
273 */
274 public function copyContentRecordOfCategoryRelation() {
275 $newTableIds = $this->actionService->copyRecord(self::TABLE_Content, self::VALUE_ContentIdLast, self::VALUE_PageId);
276 $this->assertAssertionDataSet('copyContentRecordOfCategoryRelation');
277
278 $newContentId = $newTableIds[self::TABLE_Content][self::VALUE_ContentIdLast];
279 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
280 $this->assertResponseContentStructureHasRecords(
281 $responseContent, self::TABLE_Content . ':' . $newContentId, 'categories',
282 self::TABLE_Category, 'title', array('Category B', 'Category C')
283 );
284 }
285
286 /**
287 * @test
288 */
289 public function copyCategoryRecordOfCategoryRelation() {
290 $this->actionService->copyRecord(self::TABLE_Category, self::VALUE_CategoryIdFirst, 0);
291 $this->assertAssertionDataSet('copyCategoryRecordOfCategoryRelation');
292
293 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
294 $this->assertResponseContentStructureHasRecords(
295 $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
296 self::TABLE_Category, 'title', 'Category A'
297 // @todo Actually it should be twice "Category A" since the category got copied
298 // The frontend query ignores pid=-1 and thus the specific workspace record in sys_category:33
299 // SELECT sys_category.* FROM sys_category JOIN sys_category_record_mm ON sys_category_record_mm.uid_local = sys_category.uid WHERE sys_category.uid IN (33,28,29)
300 // AND sys_category_record_mm.uid_foreign=297 AND (sys_category.sys_language_uid IN (0,-1))
301 // AND sys_category.deleted=0 AND (sys_category.t3ver_wsid=0 OR sys_category.t3ver_wsid=1) AND sys_category.pid<>-1
302 // ORDER BY sys_category_record_mm.sorting_foreign
303 // self::TABLE_Category, 'title', array('Category A', 'Category A')
304 );
305 }
306
307 /**
308 * @test
309 */
310 public function localizeContentRecordOfCategoryRelation() {
311 $this->actionService->localizeRecord(self::TABLE_Content, self::VALUE_ContentIdLast, self::VALUE_LanguageId);
312 $this->assertAssertionDataSet('localizeContentRecordOfCategoryRelation');
313
314 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
315 $this->assertResponseContentStructureHasRecords(
316 $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, 'categories',
317 self::TABLE_Category, 'title', array('Category B', 'Category C')
318 );
319 }
320
321 /**
322 * @test
323 */
324 public function localizeCategoryRecordOfCategoryRelation() {
325 $this->actionService->localizeRecord(self::TABLE_Category, self::VALUE_CategoryIdFirst, self::VALUE_LanguageId);
326 $this->assertAssertionDataSet('localizeCategoryRecordOfCategoryRelation');
327
328 $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
329 $this->assertResponseContentStructureHasRecords(
330 $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
331 // @todo Category localization cannot be rendered - http://forge.typo3.org/issues/56059
332 // self::TABLE_Category, 'title', array('[Translate to Dansk:] Category A', 'Category B')
333 self::TABLE_Category, 'title', array('Category A', 'Category B')
334 );
335 }
336
337 /**
338 * @test
339 */
340 public function moveContentRecordOfCategoryRelationToDifferentPage() {
341 $this->actionService->moveRecord(self::TABLE_Content, self::VALUE_ContentIdLast, self::VALUE_PageIdTarget);
342 $this->assertAssertionDataSet('moveContentRecordOfCategoryRelationToDifferentPage');
343
344 $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
345 $this->assertResponseContentStructureHasRecords(
346 $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, 'categories',
347 self::TABLE_Category, 'title', array('Category B', 'Category C')
348 );
349 }
350
351 }