5505bf37886d1c92aa25159a926d73e804b97b47
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Functional / Persistence / RelationTest.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Tests\Functional\Persistence;
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\Database\ConnectionPool;
18 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20 use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
21
22 class RelationTest extends \TYPO3\TestingFramework\Core\Functional\FunctionalTestCase
23 {
24 /**
25 * @var \ExtbaseTeam\BlogExample\Domain\Model\Blog
26 */
27 protected $blog;
28
29 /**
30 * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
31 */
32 protected $persistentManager;
33
34 protected $testExtensionsToLoad = ['typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example'];
35
36 protected $coreExtensionsToLoad = ['extbase', 'fluid'];
37
38 /**
39 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface The object manager
40 */
41 protected $objectManager;
42
43 /**
44 * Sets up this test suite.
45 */
46 protected function setUp()
47 {
48 parent::setUp();
49
50 $this->importDataSet(ORIGINAL_ROOT . 'components/testing_framework/Resources/Core/Functional/Fixtures/pages.xml');
51 $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/blogs.xml');
52 $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml');
53 $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/tags.xml');
54 $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/post-tag-mm.xml');
55 $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/categories.xml');
56 $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/category-mm.xml');
57
58 $this->objectManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
59 $this->persistentManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class);
60 /* @var $blogRepository \TYPO3\CMS\Extbase\Persistence\Repository */
61 $blogRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\BlogRepository::class);
62 $this->blog = $blogRepository->findByUid(1);
63 }
64
65 /**
66 * Tests adding object at the end of sorted 1:M relation (Blog:Posts)
67 *
68 * @test
69 */
70 public function attachPostToBlogAtTheEnd()
71 {
72 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_domain_model_post');
73 $queryBuilder->getRestrictions()->removeAll();
74 $countPostsOriginal = $queryBuilder
75 ->count('*')
76 ->from('tx_blogexample_domain_model_post')
77 ->where(
78 $queryBuilder->expr()->eq(
79 'blog',
80 $queryBuilder->createNamedParameter($this->blog->getUid(), \PDO::PARAM_INT)
81 )
82 )->execute()
83 ->fetchColumn(0);
84
85 $newPostTitle = 'sdufhisdhuf';
86 /** @var \ExtbaseTeam\BlogExample\Domain\Model\Post $newPost */
87 $newPost = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Model\Post::class);
88 $newPost->setBlog($this->blog);
89 $newPost->setTitle($newPostTitle);
90 $newPost->setContent('Bla Bla Bla');
91
92 $this->blog->addPost($newPost);
93 $this->updateAndPersistBlog();
94
95 $queryBuilder->resetQueryParts();
96 $countPosts = $queryBuilder
97 ->count('*')
98 ->from('tx_blogexample_domain_model_post')
99 ->where(
100 $queryBuilder->expr()->eq(
101 'blog',
102 $queryBuilder->createNamedParameter($this->blog->getUid(), \PDO::PARAM_INT)
103 )
104 )->execute()
105 ->fetchColumn(0);
106 $this->assertSame(($countPostsOriginal + 1), $countPosts);
107
108 $queryBuilder->resetQueryParts();
109 $post = $queryBuilder
110 ->select('title', 'sorting')
111 ->from('tx_blogexample_domain_model_post')
112 ->where(
113 $queryBuilder->expr()->eq(
114 'blog',
115 $queryBuilder->createNamedParameter($this->blog->getUid(), \PDO::PARAM_INT)
116 )
117 )->orderBy('sorting', 'DESC')
118 ->execute()
119 ->fetch();
120 $this->assertSame($newPostTitle, $post['title']);
121 $this->assertSame((int)($countPostsOriginal + 1), $post['sorting']);
122 }
123
124 /**
125 * Tests removing object from the end of sorted 1:M relation (Blog:Posts)
126 *
127 * @test
128 */
129 public function removeLastPostFromBlog()
130 {
131 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_domain_model_post');
132 $queryBuilder->getRestrictions()
133 ->removeAll()->add(new DeletedRestriction());
134 $countPostsOriginal = $queryBuilder
135 ->count('*')
136 ->from('tx_blogexample_domain_model_post')
137 ->execute()
138 ->fetchColumn(0);
139
140 $queryBuilder->resetQueryParts();
141 $post = $queryBuilder
142 ->select('title', 'sorting')
143 ->from('tx_blogexample_domain_model_post')
144 ->where(
145 $queryBuilder->expr()->eq(
146 'blog',
147 $queryBuilder->createNamedParameter($this->blog->getUid(), \PDO::PARAM_INT)
148 )
149 )->orderBy('sorting', 'DESC')
150 ->execute()
151 ->fetch();
152 $this->assertEquals(10, $post['sorting']);
153
154 $posts = $this->blog->getPosts();
155 $postsArray = $posts->toArray();
156 $latestPost = array_pop($postsArray);
157
158 $this->assertEquals(10, $latestPost->getUid());
159
160 $this->blog->removePost($latestPost);
161 $this->updateAndPersistBlog();
162
163 $queryBuilder->resetQueryParts();
164 $countPosts = $queryBuilder
165 ->count('*')
166 ->from('tx_blogexample_domain_model_post')
167 ->execute()
168 ->fetchColumn(0);
169 $this->assertEquals(($countPostsOriginal - 1), $countPosts);
170
171 $queryBuilder->resetQueryParts();
172 $post = $queryBuilder
173 ->select('title', 'sorting')
174 ->from('tx_blogexample_domain_model_post')
175 ->where(
176 $queryBuilder->expr()->eq(
177 'uid',
178 $queryBuilder->createNamedParameter($latestPost->getUid(), \PDO::PARAM_INT)
179 )
180 )->orderBy('sorting', 'DESC')
181 ->execute()
182 ->fetch();
183 $this->assertSame(null, $post['uid']);
184
185 $queryBuilder->resetQueryParts();
186 $post = $queryBuilder
187 ->select('title', 'sorting')
188 ->from('tx_blogexample_domain_model_post')
189 ->where(
190 $queryBuilder->expr()->eq(
191 'blog',
192 $queryBuilder->createNamedParameter($this->blog->getUid(), \PDO::PARAM_INT)
193 )
194 )->orderBy('sorting', 'DESC')
195 ->execute()
196 ->fetch();
197 $this->assertSame('Post9', $post['title']);
198 $this->assertSame(9, $post['sorting']);
199 }
200
201 /**
202 * Tests adding object in the middle of the sorted 1:M relation (Blog:Posts)
203 *
204 * @test
205 */
206 public function addPostToBlogInTheMiddle()
207 {
208 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_domain_model_post');
209 $queryBuilder->getRestrictions()
210 ->removeAll()->add(new DeletedRestriction());
211 $countPostsOriginal = $queryBuilder
212 ->count('*')
213 ->from('tx_blogexample_domain_model_post')
214 ->execute()
215 ->fetchColumn(0);
216
217 /** @var \ExtbaseTeam\BlogExample\Domain\Model\Post $newPost */
218 $newPost = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Model\Post::class);
219
220 $posts = clone $this->blog->getPosts();
221 $this->blog->getPosts()->removeAll($posts);
222 $counter = 1;
223 $newPostTitle = 'INSERTED POST at position 6';
224 foreach ($posts as $post) {
225 $this->blog->addPost($post);
226 if ($counter == 5) {
227 $newPost->setBlog($this->blog);
228 $newPost->setTitle($newPostTitle);
229 $newPost->setContent('Bla Bla Bla');
230 $this->blog->addPost($newPost);
231 }
232 $counter++;
233 }
234 $this->updateAndPersistBlog();
235
236 $queryBuilder->resetQueryParts();
237 $countPosts = $queryBuilder
238 ->count('*')
239 ->from('tx_blogexample_domain_model_post')
240 ->execute()
241 ->fetchColumn(0);
242 $this->assertSame(($countPostsOriginal + 1), $countPosts);
243
244 //last post
245 $queryBuilder->resetQueryParts();
246 $post = $queryBuilder
247 ->select('title', 'sorting')
248 ->from('tx_blogexample_domain_model_post')
249 ->where(
250 $queryBuilder->expr()->eq(
251 'blog',
252 $queryBuilder->createNamedParameter($this->blog->getUid(), \PDO::PARAM_INT)
253 )
254 )->orderBy('sorting', 'DESC')
255 ->execute()
256 ->fetch();
257 $this->assertSame('Post10', $post['title']);
258 $this->assertSame(11, $post['sorting']);
259
260 // check sorting of the post added in the middle
261 $queryBuilder->resetQueryParts();
262 $post = $queryBuilder
263 ->select('title', 'sorting')
264 ->from('tx_blogexample_domain_model_post')
265 ->where(
266 $queryBuilder->expr()->eq(
267 'uid',
268 $queryBuilder->createNamedParameter($newPost->getUid(), \PDO::PARAM_INT)
269 )
270 )->orderBy('sorting', 'DESC')
271 ->execute()
272 ->fetch();
273 $this->assertSame($newPostTitle, $post['title']);
274 $this->assertSame(6, $post['sorting']);
275 }
276
277 /**
278 * Tests removing object from the middle of sorted 1:M relation (Blog:Posts)
279 *
280 * @test
281 */
282 public function removeMiddlePostFromBlog()
283 {
284 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_domain_model_post');
285 $queryBuilder->getRestrictions()
286 ->removeAll()->add(new DeletedRestriction());
287 $countPostsOriginal = $queryBuilder
288 ->count('*')
289 ->from('tx_blogexample_domain_model_post')
290 ->execute()
291 ->fetchColumn(0);
292
293 $posts = clone $this->blog->getPosts();
294 $counter = 1;
295 foreach ($posts as $post) {
296 if ($counter == 5) {
297 $this->blog->removePost($post);
298 }
299 $counter++;
300 }
301 $this->updateAndPersistBlog();
302
303 $queryBuilder->resetQueryParts();
304 $countPosts = $queryBuilder
305 ->count('*')
306 ->from('tx_blogexample_domain_model_post')
307 ->execute()
308 ->fetchColumn(0);
309 $this->assertSame(($countPostsOriginal - 1), $countPosts);
310
311 $queryBuilder->resetQueryParts();
312 $post = $queryBuilder
313 ->select('title', 'sorting')
314 ->from('tx_blogexample_domain_model_post')
315 ->where(
316 $queryBuilder->expr()->eq(
317 'blog',
318 $queryBuilder->createNamedParameter($this->blog->getUid(), \PDO::PARAM_INT)
319 )
320 )->orderBy('sorting', 'DESC')
321 ->execute()
322 ->fetch();
323 $this->assertSame('Post10', $post['title']);
324 $this->assertSame(10, $post['sorting']);
325 }
326
327 /**
328 * Tests moving object from the end to the middle of the sorted 1:M relation (Blog:Posts)
329 *
330 * @test
331 */
332 public function movePostFromEndToTheMiddle()
333 {
334 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_domain_model_post');
335 $queryBuilder->getRestrictions()
336 ->removeAll()->add(new DeletedRestriction());
337 $countPostsOriginal = $queryBuilder
338 ->count('*')
339 ->from('tx_blogexample_domain_model_post')
340 ->execute()
341 ->fetchColumn(0);
342
343 $posts = clone $this->blog->getPosts();
344 $postsArray = $posts->toArray();
345 $latestPost = array_pop($postsArray);
346
347 $this->blog->getPosts()->removeAll($posts);
348 $counter = 0;
349 $postCount = $posts->count();
350 foreach ($posts as $post) {
351 if ($counter != ($postCount - 1)) {
352 $this->blog->addPost($post);
353 }
354 if ($counter == 4) {
355 $latestPost->setTitle('MOVED POST ' . $latestPost->getTitle());
356 $this->blog->addPost($latestPost);
357 }
358 $counter++;
359 }
360 $this->updateAndPersistBlog();
361
362 $queryBuilder->resetQueryParts();
363 $countPosts = $queryBuilder
364 ->count('*')
365 ->from('tx_blogexample_domain_model_post')
366 ->execute()
367 ->fetchColumn(0);
368 $this->assertSame($countPostsOriginal, $countPosts);
369
370 $queryBuilder->getRestrictions()->removeAll();
371 $post = $queryBuilder
372 ->select('title', 'sorting')
373 ->from('tx_blogexample_domain_model_post')
374 ->where(
375 $queryBuilder->expr()->eq(
376 'blog',
377 $queryBuilder->createNamedParameter($this->blog->getUid(), \PDO::PARAM_INT)
378 )
379 )->orderBy('sorting', 'DESC')
380 ->execute()
381 ->fetch();
382 $this->assertSame('Post9', $post['title']);
383 $this->assertSame(10, $post['sorting']);
384
385 $queryBuilder->resetQueryParts();
386 $post = $queryBuilder
387 ->select('title', 'uid')
388 ->from('tx_blogexample_domain_model_post')
389 ->where(
390 $queryBuilder->expr()->andX(
391 $queryBuilder->expr()->eq(
392 'blog',
393 $queryBuilder->createNamedParameter($this->blog->getUid(), \PDO::PARAM_INT)
394 ),
395 $queryBuilder->expr()->eq('sorting', $queryBuilder->createNamedParameter(6, \PDO::PARAM_INT))
396 )
397 )
398 ->execute()
399 ->fetch();
400 $this->assertSame('MOVED POST Post10', $post['title']);
401 $this->assertSame(10, $post['uid']);
402 }
403
404 /**
405 * Tests adding object at the end of sorted M:M relation (Post:Tag)
406 *
407 * @test
408 */
409 public function attachTagToPostAtTheEnd()
410 {
411 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_domain_model_tag');
412 $queryBuilder->getRestrictions()
413 ->removeAll();
414 $countOriginal = $queryBuilder
415 ->count('*')
416 ->from('tx_blogexample_domain_model_tag')
417 ->execute()
418 ->fetchColumn(0);
419
420 $newTagTitle = 'sdufhisdhuf';
421
422 /** @var \ExtbaseTeam\BlogExample\Domain\Model\Tag $newTag */
423 $newTag = $this->objectManager->get('ExtbaseTeam\\BlogExample\\Domain\\Model\\Tag', $newTagTitle);
424
425 /** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
426 $postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
427 $post = $postRepository->findByUid(1);
428 $post->addTag($newTag);
429
430 $postRepository->update($post);
431 $this->persistentManager->persistAll();
432
433 $queryBuilder->resetQueryParts();
434 $count = $queryBuilder
435 ->count('*')
436 ->from('tx_blogexample_domain_model_tag')
437 ->execute()
438 ->fetchColumn(0);
439 $this->assertSame(($countOriginal + 1), $count);
440
441 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_post_tag_mm');
442 $queryBuilder->getRestrictions()
443 ->removeAll();
444 $tag = $queryBuilder
445 ->select('uid_foreign')
446 ->from('tx_blogexample_post_tag_mm')
447 ->where(
448 $queryBuilder->expr()->eq(
449 'uid_local',
450 $queryBuilder->createNamedParameter($post->getUid(), \PDO::PARAM_INT)
451 )
452 )->orderBy('sorting', 'DESC')
453 ->execute()
454 ->fetch();
455 $this->assertSame($newTag->getUid(), $tag['uid_foreign']);
456 }
457
458 /**
459 * Tests removing object from the end of sorted M:M relation (Post:Tag)
460 *
461 * @test
462 */
463 public function removeLastTagFromPost()
464 {
465 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_domain_model_tag');
466 $queryBuilder->getRestrictions()
467 ->removeAll()->add(new DeletedRestriction());
468 $countOriginal = $queryBuilder
469 ->count('*')
470 ->from('tx_blogexample_domain_model_tag')
471 ->execute()
472 ->fetchColumn(0);
473
474 /** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
475 $postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
476 $post = $postRepository->findByUid(1);
477 $tags = $post->getTags();
478 $tagsArray = $tags->toArray();
479 $latestTag = array_pop($tagsArray);
480
481 $this->assertEquals(10, $latestTag->getUid());
482
483 $post->removeTag($latestTag);
484
485 $postRepository->update($post);
486 $this->persistentManager->persistAll();
487
488 $queryBuilder->resetQueryParts();
489 $countTags = $queryBuilder
490 ->count('*')
491 ->from('tx_blogexample_domain_model_tag')
492 ->execute()
493 ->fetchColumn(0);
494 $this->assertEquals($countOriginal, $countTags);
495
496 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_post_tag_mm');
497 $queryBuilder->getRestrictions()
498 ->removeAll();
499 $tag = $queryBuilder
500 ->select('uid_foreign')
501 ->from('tx_blogexample_post_tag_mm')
502 ->where(
503 $queryBuilder->expr()->eq(
504 'uid_local',
505 $queryBuilder->createNamedParameter($post->getUid(), \PDO::PARAM_INT)
506 )
507 )->orderBy('sorting', 'DESC')
508 ->execute()
509 ->fetch();
510 $this->assertSame(9, $tag['uid_foreign']);
511
512 $queryBuilder->resetQueryParts();
513 $tag = $queryBuilder
514 ->select('uid_foreign')
515 ->from('tx_blogexample_post_tag_mm')
516 ->where(
517 $queryBuilder->expr()->andX(
518 $queryBuilder->expr()->eq(
519 'uid_local',
520 $queryBuilder->createNamedParameter($post->getUid(), \PDO::PARAM_INT)
521 ),
522 $queryBuilder->expr()->eq(
523 'uid_foreign',
524 $queryBuilder->createNamedParameter($latestTag->getUid(), \PDO::PARAM_INT)
525 )
526 )
527 )->orderBy('sorting', 'DESC')
528 ->execute()
529 ->fetch();
530 $this->assertSame(null, $tag['uid_foreign']);
531 }
532
533 /**
534 * Tests adding object in the middle of sorted M:M relation (Post:Tag)
535 *
536 * @test
537 */
538 public function addTagToPostInTheMiddle()
539 {
540 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_post_tag_mm');
541 $queryBuilder->getRestrictions()
542 ->removeAll();
543 $countTagsOriginal = $queryBuilder
544 ->count('*')
545 ->from('tx_blogexample_post_tag_mm')
546 ->where(
547 $queryBuilder->expr()->eq('uid_local', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
548 )
549 ->execute()
550 ->fetchColumn(0);
551
552 /** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
553 $postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
554 $post = $postRepository->findByUid(1);
555 $tags = clone $post->getTags();
556 $post->setTags(new ObjectStorage());
557
558 /** @var \ExtbaseTeam\BlogExample\Domain\Model\Tag $newTag */
559 $newTag = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Model\Tag::class, 'INSERTED TAG at position 6 : ' . strftime(''));
560
561 $counter = 1;
562 foreach ($tags as $tag) {
563 $post->addTag($tag);
564 if ($counter == 5) {
565 $post->addTag($newTag);
566 }
567 $counter++;
568 }
569
570 $postRepository->update($post);
571 $this->persistentManager->persistAll();
572
573 $queryBuilder->resetQueryParts();
574 $countTags = $queryBuilder
575 ->count('*')
576 ->from('tx_blogexample_post_tag_mm')
577 ->where(
578 $queryBuilder->expr()->eq('uid_local', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
579 )
580 ->execute()
581 ->fetchColumn(0);
582 $this->assertSame(($countTagsOriginal + 1), $countTags);
583
584 $queryBuilder->resetQueryParts();
585 $tag = $queryBuilder
586 ->select('uid_foreign')
587 ->from('tx_blogexample_post_tag_mm')
588 ->where(
589 $queryBuilder->expr()->eq(
590 'uid_local',
591 $queryBuilder->createNamedParameter($post->getUid(), \PDO::PARAM_INT)
592 )
593 )->orderBy('sorting', 'DESC')
594 ->execute()
595 ->fetch();
596 $this->assertSame(10, $tag['uid_foreign']);
597
598 $queryBuilder->resetQueryParts();
599 $tag = $queryBuilder
600 ->select('uid_foreign')
601 ->from('tx_blogexample_post_tag_mm')
602 ->where(
603 $queryBuilder->expr()->andX(
604 $queryBuilder->expr()->eq(
605 'uid_local',
606 $queryBuilder->createNamedParameter($post->getUid(), \PDO::PARAM_INT)
607 ),
608 $queryBuilder->expr()->eq('sorting', $queryBuilder->createNamedParameter(6, \PDO::PARAM_INT))
609 )
610 )->orderBy('sorting', 'DESC')
611 ->execute()
612 ->fetch();
613 $this->assertSame($newTag->getUid(), $tag['uid_foreign']);
614 }
615
616 /**
617 * Tests removing object from the middle of the sorted M:M relation (Post:Tag)
618 *
619 * @test
620 */
621 public function removeMiddleTagFromPost()
622 {
623 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_post_tag_mm');
624 $queryBuilder->getRestrictions()
625 ->removeAll();
626 $countTags = $queryBuilder
627 ->count('*')
628 ->from('tx_blogexample_post_tag_mm')
629 ->where(
630 $queryBuilder->expr()->eq('uid_local', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
631 )
632 ->execute()
633 ->fetchColumn(0);
634 $this->assertSame(10, $countTags);
635
636 /** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
637 $postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
638 $post = $postRepository->findByUid(1);
639 $tags = clone $post->getTags();
640 $counter = 1;
641 foreach ($tags as $tag) {
642 if ($counter == 5) {
643 $post->removeTag($tag);
644 }
645 $counter++;
646 }
647
648 $postRepository->update($post);
649 $this->persistentManager->persistAll();
650
651 $queryBuilder->resetQueryParts();
652 $countTags = $queryBuilder
653 ->count('*')
654 ->from('tx_blogexample_post_tag_mm')
655 ->where(
656 $queryBuilder->expr()->eq('uid_local', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
657 )
658 ->execute()
659 ->fetchColumn(0);
660 $this->assertSame(9, $countTags);
661
662 $queryBuilder->resetQueryParts();
663 $tag = $queryBuilder
664 ->select('uid_foreign', 'sorting')
665 ->from('tx_blogexample_post_tag_mm')
666 ->where(
667 $queryBuilder->expr()->eq(
668 'uid_local',
669 $queryBuilder->createNamedParameter($post->getUid(), \PDO::PARAM_INT)
670 )
671 )->orderBy('sorting', 'DESC')
672 ->execute()
673 ->fetch();
674 $this->assertSame(10, $tag['uid_foreign']);
675 $this->assertSame(10, $tag['sorting']);
676
677 $queryBuilder->resetQueryParts();
678 $tag = $queryBuilder
679 ->select('uid_foreign')
680 ->from('tx_blogexample_post_tag_mm')
681 ->where(
682 $queryBuilder->expr()->andX(
683 $queryBuilder->expr()->eq(
684 'uid_local',
685 $queryBuilder->createNamedParameter($post->getUid(), \PDO::PARAM_INT)
686 ),
687 $queryBuilder->expr()->eq('sorting', $queryBuilder->createNamedParameter(5, \PDO::PARAM_INT))
688 )
689 )
690 ->execute()
691 ->fetch();
692 $this->assertSame(null, $tag['uid_foreign']);
693 }
694
695 /**
696 * Tests moving object from the end to the middle of sorted M:M relation (Post:Tag)
697 *
698 * @test
699 */
700 public function moveTagFromEndToTheMiddle()
701 {
702 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_post_tag_mm');
703 $queryBuilder->getRestrictions()
704 ->removeAll();
705 $countTags = $queryBuilder
706 ->count('*')
707 ->from('tx_blogexample_post_tag_mm')
708 ->where(
709 $queryBuilder->expr()->eq('uid_local', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
710 )
711 ->execute()
712 ->fetchColumn(0);
713 $this->assertSame(10, $countTags);
714
715 /** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
716 $postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
717 $post = $postRepository->findByUid(1);
718 $tags = clone $post->getTags();
719 $tagsArray = $tags->toArray();
720 $latestTag = array_pop($tagsArray);
721 $post->removeTag($latestTag);
722 $post->setTags(new ObjectStorage());
723
724 $counter = 1;
725 $tagCount = $tags->count();
726 foreach ($tags as $tag) {
727 if ($counter != $tagCount) {
728 $post->addTag($tag);
729 }
730 if ($counter == 5) {
731 $post->addTag($latestTag);
732 }
733 $counter++;
734 }
735 $post->addTag($latestTag);
736
737 $postRepository->update($post);
738 $this->persistentManager->persistAll();
739
740 $queryBuilder->resetQueryParts();
741 $countTags = $queryBuilder
742 ->count('*')
743 ->from('tx_blogexample_post_tag_mm')
744 ->where(
745 $queryBuilder->expr()->eq('uid_local', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
746 )
747 ->execute()
748 ->fetchColumn(0);
749 $this->assertSame(10, $countTags);
750
751 $queryBuilder->resetQueryParts();
752 $tag = $queryBuilder
753 ->select('uid_foreign', 'sorting')
754 ->from('tx_blogexample_post_tag_mm')
755 ->where(
756 $queryBuilder->expr()->eq(
757 'uid_local',
758 $queryBuilder->createNamedParameter($post->getUid(), \PDO::PARAM_INT)
759 )
760 )->orderBy('sorting', 'DESC')
761 ->execute()
762 ->fetch();
763 $this->assertSame(9, $tag['uid_foreign']);
764 $this->assertSame(10, $tag['sorting']);
765
766 $sorting = '6';
767 $queryBuilder->resetQueryParts();
768 $tag = $queryBuilder
769 ->select('uid_foreign')
770 ->from('tx_blogexample_post_tag_mm')
771 ->where(
772 $queryBuilder->expr()->andX(
773 $queryBuilder->expr()->eq(
774 'uid_local',
775 $queryBuilder->createNamedParameter($post->getUid(), \PDO::PARAM_INT)
776 ),
777 $queryBuilder->expr()->eq(
778 'sorting',
779 $queryBuilder->createNamedParameter($sorting, \PDO::PARAM_STR)
780 )
781 )
782 )
783 ->execute()
784 ->fetch();
785 $this->assertSame(10, $tag['uid_foreign']);
786 }
787
788 /**
789 * Test if timestamp field is updated when updating a record
790 *
791 * @test
792 */
793 public function timestampFieldIsUpdatedOnPostSave()
794 {
795 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('tx_blogexample_domain_model_post');
796 $queryBuilder->getRestrictions()
797 ->removeAll();
798 $rawPost = $queryBuilder
799 ->select('*')
800 ->from('tx_blogexample_domain_model_post')
801 ->where(
802 $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
803 )
804 ->execute()
805 ->fetch();
806
807 /** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
808 $postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
809 $post = $postRepository->findByUid(1);
810 $post->setTitle('newTitle');
811
812 $postRepository->update($post);
813 $this->persistentManager->persistAll();
814
815 $queryBuilder->resetQueryParts();
816 $rawPost2 = $queryBuilder
817 ->select('*')
818 ->from('tx_blogexample_domain_model_post')
819 ->where(
820 $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
821 )
822 ->execute()
823 ->fetch();
824 $this->assertTrue($rawPost2['tstamp'] > $rawPost['tstamp']);
825 }
826
827 /**
828 * Test query matching for mm relation without MM_match_fields defined
829 *
830 * @test
831 */
832 public function mmRelationWithoutMatchFieldIsResolved()
833 {
834 /** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
835 $postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
836 $posts = $postRepository->findByTagAndBlog('Tag2', $this->blog);
837 $this->assertSame(1, count($posts));
838 }
839
840 /**
841 * @test
842 */
843 public function mmRelationWithMatchFieldIsResolvedFromLocalSide()
844 {
845 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('sys_category_record_mm');
846 $queryBuilder->getRestrictions()
847 ->removeAll();
848 $countCategories = $queryBuilder
849 ->count('*')
850 ->from('sys_category_record_mm')
851 ->where(
852 $queryBuilder->expr()->andX(
853 $queryBuilder->expr()->eq('uid_foreign', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)),
854 $queryBuilder->expr()->eq(
855 'tablenames',
856 $queryBuilder->createNamedParameter('tx_blogexample_domain_model_post', \PDO::PARAM_STR)
857 ),
858 $queryBuilder->expr()->eq(
859 'fieldname',
860 $queryBuilder->createNamedParameter('categories', \PDO::PARAM_STR)
861 )
862 )
863 )
864 ->execute()
865 ->fetchColumn(0);
866 $this->assertSame(3, $countCategories);
867
868 /** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
869 $postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
870 $post = $postRepository->findByUid(1);
871 $this->assertSame(3, count($post->getCategories()));
872 }
873
874 /**
875 * Test query matching respects MM_match_fields
876 *
877 * @test
878 */
879 public function mmRelationWithMatchFieldIsResolvedFromForeignSide()
880 {
881 /** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
882 $postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
883 $posts = $postRepository->findByCategory(1);
884 $this->assertSame(2, count($posts));
885
886 $posts = $postRepository->findByCategory(4);
887 $this->assertSame(0, count($posts));
888 }
889
890 /**
891 * @test
892 */
893 public function mmRelationWithMatchFieldIsCreatedFromLocalSide()
894 {
895 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('sys_category_record_mm');
896 $queryBuilder->getRestrictions()
897 ->removeAll();
898 $countCategories = $queryBuilder
899 ->count('*')
900 ->from('sys_category_record_mm')
901 ->where(
902 $queryBuilder->expr()->andX(
903 $queryBuilder->expr()->eq('uid_foreign', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)),
904 $queryBuilder->expr()->eq(
905 'tablenames',
906 $queryBuilder->createNamedParameter('tx_blogexample_domain_model_post', \PDO::PARAM_STR)
907 ),
908 $queryBuilder->expr()->eq(
909 'fieldname',
910 $queryBuilder->createNamedParameter('categories', \PDO::PARAM_STR)
911 )
912 )
913 )
914 ->execute()
915 ->fetchColumn(0);
916 $this->assertSame(3, $countCategories);
917
918 /** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
919 $postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
920 $post = $postRepository->findByUid(1);
921
922 /** @var \TYPO3\CMS\Extbase\Domain\Model\Category $newCategory */
923 $newCategory = $this->objectManager->get(\TYPO3\CMS\Extbase\Domain\Model\Category::class);
924 $newCategory->setTitle('New Category');
925
926 $post->addCategory($newCategory);
927
928 $postRepository->update($post);
929 $this->persistentManager->persistAll();
930
931 $queryBuilder->resetQueryParts();
932 $countCategories = $queryBuilder
933 ->count('*')
934 ->from('sys_category_record_mm')
935 ->where(
936 $queryBuilder->expr()->andX(
937 $queryBuilder->expr()->eq('uid_foreign', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)),
938 $queryBuilder->expr()->eq(
939 'tablenames',
940 $queryBuilder->createNamedParameter('tx_blogexample_domain_model_post', \PDO::PARAM_STR)
941 ),
942 $queryBuilder->expr()->eq(
943 'fieldname',
944 $queryBuilder->createNamedParameter('categories', \PDO::PARAM_STR)
945 )
946 )
947 )
948 ->execute()
949 ->fetchColumn(0);
950 $this->assertSame(4, $countCategories);
951 }
952
953 /**
954 * Test if adjusting existing mm relations do not relations with other objects
955 *
956 * @test
957 */
958 public function adjustingMmRelationWithTablesnameAndFieldnameFieldDoNotTouchOtherRelations()
959 {
960 /** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
961 $postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
962 /** @var \ExtbaseTeam\BlogExample\Domain\Model\Post $post */
963 $post = $postRepository->findByUid(1);
964 // Move category down
965 foreach ($post->getCategories() as $category) {
966 $post->removeCategory($category);
967 $post->addCategory($category);
968 break;
969 }
970 $postRepository->update($post);
971 $this->persistentManager->persistAll();
972
973 // re-fetch Post and Blog
974 $queryBuilder = (new ConnectionPool())->getQueryBuilderForTable('sys_category_record_mm');
975 $queryBuilder->getRestrictions()
976 ->removeAll();
977 $newBlogCategoryCount = $queryBuilder
978 ->count('*')
979 ->from('sys_category_record_mm')
980 ->where(
981 $queryBuilder->expr()->andX(
982 $queryBuilder->expr()->eq(
983 'uid_foreign',
984 $queryBuilder->createNamedParameter($this->blog->getUid(), \PDO::PARAM_INT)
985 ),
986 $queryBuilder->expr()->eq(
987 'tablenames',
988 $queryBuilder->createNamedParameter('tx_blogexample_domain_model_post', \PDO::PARAM_STR)
989 ),
990 $queryBuilder->expr()->eq(
991 'fieldname',
992 $queryBuilder->createNamedParameter('categories', \PDO::PARAM_STR)
993 )
994 )
995 )
996 ->execute()
997 ->fetchColumn(0);
998
999 $this->assertSame($this->blog->getCategories()->count(), $newBlogCategoryCount);
1000 }
1001
1002 /**
1003 * Helper method for persisting blog
1004 */
1005 protected function updateAndPersistBlog()
1006 {
1007 /** @var \ExtbaseTeam\BlogExample\Domain\Repository\BlogRepository $blogRepository */
1008 $blogRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\BlogRepository::class);
1009 $blogRepository->update($this->blog);
1010 $this->persistentManager->persistAll();
1011 }
1012 }