diff --git a/Module.php b/Module.php index 5b8e5a6..027c6a4 100755 --- a/Module.php +++ b/Module.php @@ -132,8 +132,10 @@ public function getServiceConfig() return new Service\CategoryService($categoryMapper); }, 'ZfrForum\Service\PostService' => function($serviceManager) { - $postMapper = $serviceManager->get('ZfrForum\Mapper\PostMapperInterface'); - return new Service\PostService($postMapper); + $postMapper = $serviceManager->get('ZfrForum\Mapper\PostMapperInterface'); + $reportMapper = $serviceManager->get('ZfrForum\Mapper\ReportMapperInterface'); + $authentication = $serviceManager->get('Zend\Authentication\AuthenticationService'); + return new Service\PostService($postMapper, $reportMapper, $authentication); }, 'ZfrForum\Service\RankService' => function($serviceManager) { $rankMapper = $serviceManager->get('ZfrForum\Mapper\RankMapperInterface'); @@ -144,8 +146,9 @@ public function getServiceConfig() return new Service\SettingsService($settingsMapper); }, 'ZfrForum\Service\ThreadService' => function($serviceManager) { - $threadMapper = $serviceManager->get('ZfrForum\Mapper\ThreadMapperInterface'); - return new Service\ThreadService($threadMapper); + $threadMapper = $serviceManager->get('ZfrForum\Mapper\ThreadMapperInterface'); + $authentication = $serviceManager->get('Zend\Authentication\AuthenticationService'); + return new Service\ThreadService($threadMapper, $authentication); }, 'ZfrForum\Service\UserBanService' => function($serviceManager) { $userBanMapper = $serviceManager->get('ZfrForum\Mapper\UserBanMapperInterface'); diff --git a/config/module.config.php b/config/module.config.php index 03e8645..f3c749a 100755 --- a/config/module.config.php +++ b/config/module.config.php @@ -6,6 +6,15 @@ */ 'router' => include 'module.config.routes.php', + /** + * Override ZfcUser options + */ + 'zfcuser' => array( + // We don't want the original User entity to be generated as we have our own extended class + // for ZfrForum + 'enable_default_entities' => false + ), + /** * Doctrine configuration */ diff --git a/src/ZfrForum/Entity/Category.php b/src/ZfrForum/Entity/Category.php index 13d8611..3352647 100644 --- a/src/ZfrForum/Entity/Category.php +++ b/src/ZfrForum/Entity/Category.php @@ -54,7 +54,7 @@ class Category * * @ORM\Column(type="string", length=128) */ - protected $name; + protected $name = ''; /** * @var string @@ -68,7 +68,7 @@ class Category * * @ORM\Column(type="smallint") */ - protected $depth = 1; + protected $depth = 0; /** * @var int @@ -96,20 +96,17 @@ public function getId() } /** - * Set the parent category (null if none) + * Set the parent category * * @param Category $parent * @return Category */ - public function setParent(Category $parent = null) + public function setParent(Category $parent) { $this->parent = $parent; - - if ($parent !== null) { - $this->setDepth($parent->getDepth() + 1) - ->setLeftBound($parent->getRightBound()) - ->setRightBound($parent->getRightBound() + 1); - } + $this->setDepth($parent->getDepth() + 1) + ->setLeftBound($parent->getRightBound()) + ->setRightBound($parent->getRightBound() + 1); return $this; } @@ -131,7 +128,7 @@ public function getParent() */ public function hasParent() { - return !($this->parent === null); + return ($this->depth > 1); } /** diff --git a/src/ZfrForum/Entity/Post.php b/src/ZfrForum/Entity/Post.php index 032e62f..6edea9c 100644 --- a/src/ZfrForum/Entity/Post.php +++ b/src/ZfrForum/Entity/Post.php @@ -76,7 +76,7 @@ class Post /** * @var DateTime * - * @ORM\Column(type="datetime") + * @ORM\Column(type="datetime", nullable=true) */ protected $lastModifiedAt; diff --git a/src/ZfrForum/Entity/Report.php b/src/ZfrForum/Entity/Report.php index a5f8f31..453e1ba 100644 --- a/src/ZfrForum/Entity/Report.php +++ b/src/ZfrForum/Entity/Report.php @@ -23,7 +23,7 @@ use ZfrForum\Entity\UserInterface; /** - * @ORM\Entity(readOnly=true) + * @ORM\Entity(repositoryClass="ZfrForum\Repository\ReportRepository", readOnly=true) * @ORM\Table(name="Reports", uniqueConstraints={ * @ORM\UniqueConstraint(name="UNIQ_C38372B2B6BD307F", columns={"post_id", "reportedBy_id"}) * }) @@ -148,11 +148,13 @@ public function getReportedAt() /** * Set the description of the report * - * @param string $description + * @param string $description + * @return Report */ public function setDescription($description) { $this->description = (string) $description; + return $this; } /** diff --git a/src/ZfrForum/Entity/Thread.php b/src/ZfrForum/Entity/Thread.php index 2bc10b4..6f0d5bc 100644 --- a/src/ZfrForum/Entity/Thread.php +++ b/src/ZfrForum/Entity/Thread.php @@ -71,7 +71,7 @@ class Thread /** * @var Collection * - * @ORM\OneToMany(targetEntity="ZfrForum\Entity\Post", mappedBy="thread", fetch="EXTRA_LAZY") + * @ORM\OneToMany(targetEntity="ZfrForum\Entity\Post", mappedBy="thread", cascade={"persist"}, fetch="EXTRA_LAZY") * @ORM\OrderBy({"sentAt"="ASC"}) */ protected $posts; @@ -85,9 +85,12 @@ class Thread /** * @var Collection + * TODO: remettre UserInterface * - * @ORM\ManyToMany(targetEntity="ZfrForum\Entity\UserInterface", fetch="EXTRA_LAZY") - * @ORM\JoinTable(name="ThreadsFollowers") + * @ORM\ManyToMany(targetEntity="ZfrForum\Entity\User", fetch="EXTRA_LAZY") + * @ORM\JoinTable(name="ThreadsFollowers", + * inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")} + * ) */ protected $followers; diff --git a/src/ZfrForum/Entity/User.php b/src/ZfrForum/Entity/User.php index 4382b30..1327bcb 100644 --- a/src/ZfrForum/Entity/User.php +++ b/src/ZfrForum/Entity/User.php @@ -23,7 +23,8 @@ use ZfcUser\Entity\User as BaseUser; /** - * @ORM\MappedSuperclass + * @ORM\Entity + * @ORM\Table(name="Users") */ class User extends BaseUser implements UserInterface { @@ -32,7 +33,7 @@ class User extends BaseUser implements UserInterface * * @ORM\Column(type="string", length=39) */ - protected $ip; + protected $ip = ''; /** * @var DateTime diff --git a/src/ZfrForum/Mapper/CategoryMapperInterface.php b/src/ZfrForum/Mapper/CategoryMapperInterface.php index 0b0c663..a1456c2 100644 --- a/src/ZfrForum/Mapper/CategoryMapperInterface.php +++ b/src/ZfrForum/Mapper/CategoryMapperInterface.php @@ -29,6 +29,12 @@ interface CategoryMapperInterface extends ObjectRepository */ public function create(Category $category); + /** + * @param Category $category + * @return Category + */ + public function update(Category $category); + /** * @param Category $category * @return void @@ -36,8 +42,7 @@ public function create(Category $category); public function remove(Category $category); /** - * @param Category $category * @return Category */ - public function update(Category $category); + public function findRoot(); } diff --git a/src/ZfrForum/Mapper/PostMapperInterface.php b/src/ZfrForum/Mapper/PostMapperInterface.php index 1598049..e8c2a20 100644 --- a/src/ZfrForum/Mapper/PostMapperInterface.php +++ b/src/ZfrForum/Mapper/PostMapperInterface.php @@ -20,7 +20,6 @@ use Doctrine\Common\Persistence\ObjectRepository; use ZfrForum\Entity\Post; -use ZfrForum\Entity\Report; interface PostMapperInterface extends ObjectRepository { @@ -29,10 +28,4 @@ interface PostMapperInterface extends ObjectRepository * @return Post */ public function update(Post $post); - - /** - * @param Report $report - * @return void - */ - public function addReport(Report $report); } diff --git a/src/ZfrForum/Mapper/RankMapperInterface.php b/src/ZfrForum/Mapper/RankMapperInterface.php index 9cfb6ea..8599d1d 100644 --- a/src/ZfrForum/Mapper/RankMapperInterface.php +++ b/src/ZfrForum/Mapper/RankMapperInterface.php @@ -33,11 +33,11 @@ public function create(Rank $rank); * @param Rank $rank * @return void */ - public function remove(Rank $rank); + public function update(Rank $rank); /** * @param Rank $rank * @return void */ - public function update(Rank $rank); + public function remove(Rank $rank); } diff --git a/src/ZfrForum/Mapper/ReportMapperInterface.php b/src/ZfrForum/Mapper/ReportMapperInterface.php new file mode 100644 index 0000000..6fbb2a3 --- /dev/null +++ b/src/ZfrForum/Mapper/ReportMapperInterface.php @@ -0,0 +1,39 @@ +getEntityManager(); + // Does not have a parent ? Add the super root + if (!$category->hasParent()) { + $category->setParent($this->findRoot()); + } - if ($category->hasParent()) { - $queryBuilder = $em->createQueryBuilder(); + $em = $this->getEntityManager(); + $queryBuilder = $em->createQueryBuilder(); - // First update right bounds - $queryBuilder->update('ZfrForum\Entity\Category', 'c') - ->set('c.rightBound', 'c.rightBound + 2') - ->where('c.rightBound >= :rightBound') - ->setParameter('rightBound', $category->getParent()->getRightBound()) - ->getQuery()->execute(); + // First update right bounds + $queryBuilder->update('ZfrForum\Entity\Category', 'c') + ->set('c.rightBound', 'c.rightBound + 2') + ->where('c.rightBound >= :rightBound') + ->setParameter('rightBound', $category->getParent()->getRightBound()) + ->getQuery()->execute(); - // Then left bounds - $queryBuilder->resetDQLParts(array('set', 'where')) - ->set('c.leftBound', 'c.leftBound + 2') - ->where('c.leftBound >= :rightBound') - ->getQuery()->execute(); - } + // Then left bounds + $queryBuilder->resetDQLParts(array('set', 'where')) + ->set('c.leftBound', 'c.leftBound + 2') + ->where('c.leftBound >= :rightBound') + ->getQuery()->execute(); // Finally, add the category $em->persist($category); @@ -63,6 +65,15 @@ public function create(Category $category) return $em->merge($category); } + /** + * @param Category $category + * @return Category + */ + public function update(Category $category) + { + // TODO: Implement update() method. + } + /** * Note : to efficiently remove a category, we perform an UPDATE at SQL level. To work correctly with * Doctrine 2, we need to clear the entity manager at the end of the operation. As a consequence, you need @@ -101,11 +112,20 @@ public function remove(Category $category) } /** - * @param Category $category + * This function returns a special category node + * * @return Category */ - public function update(Category $category) + public function findRoot() { - // TODO: Implement update() method. + $root = $this->findOneBy(array('parent' => null)); + + if ($root === null) { + $root = new Category(); + $this->_em->persist($root); + $this->_em->flush(); + } + + return $root; } } diff --git a/src/ZfrForum/Repository/PostRepository.php b/src/ZfrForum/Repository/PostRepository.php index 9c803ab..4a7a4d1 100644 --- a/src/ZfrForum/Repository/PostRepository.php +++ b/src/ZfrForum/Repository/PostRepository.php @@ -20,12 +20,13 @@ use Doctrine\ORM\EntityRepository; use ZfrForum\Entity\Post; -use ZfrForum\Entity\Report; use ZfrForum\Mapper\PostMapperInterface; class PostRepository extends EntityRepository implements PostMapperInterface { /** + * Update the post + * * @param Post $post * @return mixed */ @@ -34,15 +35,4 @@ public function update(Post $post) $this->getEntityManager()->flush($post); return $post; } - - /** - * @param Report $report - * @return void - */ - public function addReport(Report $report) - { - $em = $this->getEntityManager(); - $em->persist($report); - $em->flush(); - } } diff --git a/src/ZfrForum/Repository/RankRepository.php b/src/ZfrForum/Repository/RankRepository.php index 7601bf3..88b37e8 100644 --- a/src/ZfrForum/Repository/RankRepository.php +++ b/src/ZfrForum/Repository/RankRepository.php @@ -37,17 +37,17 @@ public function create(Rank $rank) * @param Rank $rank * @return mixed */ - public function remove(Rank $rank) + public function update(Rank $rank) { - // TODO: Implement remove() method. + // TODO: Implement update() method. } /** * @param Rank $rank * @return mixed */ - public function update(Rank $rank) + public function remove(Rank $rank) { - // TODO: Implement update() method. + // TODO: Implement remove() method. } } diff --git a/src/ZfrForum/Repository/ReportRepository.php b/src/ZfrForum/Repository/ReportRepository.php new file mode 100644 index 0000000..0df1c8f --- /dev/null +++ b/src/ZfrForum/Repository/ReportRepository.php @@ -0,0 +1,62 @@ +getEntityManager(); + $em->persist($report); + $em->flush(); + + return $report; + } + + /** + * Find all the reports for a given post, and return as a paginator + * + * @param Post $post + * @return Paginator + */ + public function findByPost(Post $post) + { + $queryBuilder = $this->createQueryBuilder('r'); + $queryBuilder->where('r.post = :post') + ->setParameter('post', $post); + + $paginatorAdapter = new PaginatorAdapter(new DoctrinePaginator($queryBuilder, false)); + + return new Paginator($paginatorAdapter); + } +} diff --git a/src/ZfrForum/Repository/ThreadRepository.php b/src/ZfrForum/Repository/ThreadRepository.php index 94175fe..3641f46 100644 --- a/src/ZfrForum/Repository/ThreadRepository.php +++ b/src/ZfrForum/Repository/ThreadRepository.php @@ -19,6 +19,8 @@ namespace ZfrForum\Repository; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator; +use DoctrineORMModule\Paginator\Adapter\DoctrinePaginator as PaginatorAdapter; use Zend\Paginator\Paginator; use ZfrForum\Entity\Category; use ZfrForum\Entity\Thread; @@ -49,10 +51,28 @@ public function update(Thread $thread) /** * @param Category $category + * @param bool $strict If set to true, do not consider threads in children categories of the one given * @return Paginator */ - public function findByCategory(Category $category = null) + public function findByCategory(Category $category = null, $strict = false) { - // TODO: Implement findByCategory() method. + $queryBuilder = $this->createQueryBuilder('t'); + + if ($category !== null) { + if ($strict) { + $queryBuilder->where('t.category = :category') + ->setParameter('category', $category); + } else { + $queryBuilder->join('t.category', 'c') + ->where('c.leftBound >= :leftBound') + ->andWhere('c.rightBound <= :rightBound') + ->setParameter('leftBound', $category->getLeftBound()) + ->setParameter('rightBound', $category->getRightBound()); + } + } + + $paginatorAdapter = new PaginatorAdapter(new DoctrinePaginator($queryBuilder, false)); + + return new Paginator($paginatorAdapter); } } diff --git a/src/ZfrForum/Service/PostService.php b/src/ZfrForum/Service/PostService.php index ab0e8c9..97fbcc5 100644 --- a/src/ZfrForum/Service/PostService.php +++ b/src/ZfrForum/Service/PostService.php @@ -20,9 +20,12 @@ use DateTime; use Zend\Authentication\AuthenticationService; +use Zend\Paginator\Paginator; use ZfrForum\Entity\Post; use ZfrForum\Entity\Report; +use ZfrForum\Entity\UserInterface; use ZfrForum\Mapper\PostMapperInterface; +use ZfrForum\Mapper\ReportMapperInterface; class PostService { @@ -31,6 +34,11 @@ class PostService */ protected $postMapper; + /*** + * @var ReportMapperInterface + */ + protected $reportMapper; + /** * @var AuthenticationService */ @@ -39,11 +47,17 @@ class PostService /** * @param PostMapperInterface $postMapper + * @param ReportMapperInterface $reportMapper * @param AuthenticationService $authenticationService */ - public function __construct(PostMapperInterface $postMapper, AuthenticationService $authenticationService) + public function __construct( + PostMapperInterface $postMapper, + ReportMapperInterface $reportMapper, + AuthenticationService $authenticationService + ) { $this->postMapper = $postMapper; + $this->reportMapper = $reportMapper; $this->authenticationService = $authenticationService; } @@ -61,13 +75,53 @@ public function report(Post $post, $description) throw new Exception\LogicException('A user has to be logged to report a post'); } - $report = new Report(); - $report->setPost($post) - ->setReportedBy($this->authenticationService->getIdentity()) - ->setReportedAt(new DateTime('now')) - ->setDescription($description); + $user = $this->authenticationService->getIdentity(); + + // TODO: make this an option like allow_multiple_reports + if (!$this->isReportedByUser($post, $user)) { + $report = new Report(); + $report->setPost($post) + ->setReportedBy($user) + ->setReportedAt(new DateTime('now')) + ->setDescription($description); + + $this->reportMapper->create($report); + } + } + + /** + * Return true if the given post is already reported by the user + * + * @param Post $post + * @param UserInterface $user + * @return boolean + */ + public function isReportedByUser(Post $post, UserInterface $user) + { + $report = $this->reportMapper->findOneBy(array('post' => $post, 'reportedBy' => $user)); + return $report !== null; + } + + /** + * Get all the reports for a given post + * + * @param Post $post + * @throws Exception\UnexpectedValueException + * @return Paginator + */ + public function getReports(Post $post) + { + $reports = $this->reportMapper->findByPost($post); + + if (!$reports instanceof Paginator) { + throw new Exception\UnexpectedValueException(sprintf( + '%s method expects a Zend\Paginator\Paginator instance, %s received', + __FUNCTION__, + get_class($reports) + )); + } - $this->postMapper->addReport($report); + return $reports; } /** diff --git a/src/ZfrForum/Service/ThreadService.php b/src/ZfrForum/Service/ThreadService.php index 0bb55e4..7c68d87 100644 --- a/src/ZfrForum/Service/ThreadService.php +++ b/src/ZfrForum/Service/ThreadService.php @@ -105,7 +105,8 @@ public function getLatestThreadsByCategory(Category $category = null) if (!$latestThreads instanceof Paginator) { throw new Exception\UnexpectedValueException(sprintf( - 'This service expects a Zend\Paginator\Paginator instance, %s received', + '%s method expects a Zend\Paginator\Paginator instance, %s received', + __FUNCTION__, get_class($latestThreads) )); } diff --git a/tests/ZfrForumTest/Fixture/CategoryFixture.php b/tests/ZfrForumTest/Fixture/CategoryFixture.php new file mode 100644 index 0000000..5089695 --- /dev/null +++ b/tests/ZfrForumTest/Fixture/CategoryFixture.php @@ -0,0 +1,57 @@ +getRepository('ZfrForum\Entity\Category'); + + for ($i = 0; $i < self::INSTANCES_COUNT; $i += 1) { + $category = new Category(); + $category->setName("Category $i"); + + $category = $repository->create($category); + $this->setReference("category-$i", $category); + + // Add a child category + $child = new Category(); + $child->setName("Category $i / 1"); + $child->setParent($category); + + $child = $repository->create($child); + $this->setReference("category-$i-1", $child); + } + + $manager->flush(); + } +} diff --git a/tests/ZfrForumTest/Fixture/ThreadFixture.php b/tests/ZfrForumTest/Fixture/ThreadFixture.php new file mode 100644 index 0000000..3b10cfc --- /dev/null +++ b/tests/ZfrForumTest/Fixture/ThreadFixture.php @@ -0,0 +1,77 @@ +getReference("user-$i"); + $category = $this->getReference("category-$i"); + + $thread = new Thread(); + $thread->setTitle('Foo thread') + ->setCategory($category) + ->setCreatedBy($user) + ->setCreatedAt(new DateTime('now')); + + $post = new Post(); + $post->setContent('France ftw') + ->setAuthor($user) + ->setSentAt(new DateTime('now')); + + $thread->addPost($post); + + $manager->persist($thread); + $this->setReference("thread-$i", $thread); + } + + $manager->flush(); + } +} diff --git a/tests/ZfrForumTest/Fixture/UserFixture.php b/tests/ZfrForumTest/Fixture/UserFixture.php new file mode 100644 index 0000000..75f9202 --- /dev/null +++ b/tests/ZfrForumTest/Fixture/UserFixture.php @@ -0,0 +1,59 @@ +setLastActivityDate(new DateTime('now')) + ->setEmail("user-$i@gmail.com") + ->setDisplayName($this->userDisplayNames[$i]) + ->setPassword('azerty'); + + $manager->persist($user); + $this->addReference("user-$i", $user); + } + + $manager->flush(); + } +} diff --git a/tests/ZfrForumTest/Repository/CategoryRepositoryTest.php b/tests/ZfrForumTest/Repository/CategoryRepositoryTest.php index b12aa0d..7e82879 100644 --- a/tests/ZfrForumTest/Repository/CategoryRepositoryTest.php +++ b/tests/ZfrForumTest/Repository/CategoryRepositoryTest.php @@ -47,6 +47,10 @@ public function tearDown() */ protected function createCategory($name, Category $parent = null) { + if ($parent === null) { + $parent = $this->categoryMapper->findRoot(); + } + $category = new Category(); $category->setName($name) ->setParent($parent); @@ -60,8 +64,8 @@ public function testCanPersistRootCategory() $this->categoryMapper->create($category); $this->assertInternalType('integer', $category->getId()); - $this->assertEquals(1, $category->getLeftBound()); - $this->assertEquals(2, $category->getRightBound()); + $this->assertEquals(2, $category->getLeftBound()); + $this->assertEquals(3, $category->getRightBound()); $this->assertTrue($category->isLeaf()); $this->assertEquals(0, $category->getChildrenCount()); } @@ -72,100 +76,100 @@ public function testCanPersistMultipleRootCategories() $firstRoot = $this->categoryMapper->create($firstRoot); $this->assertInternalType('integer', $firstRoot->getId()); - $this->assertEquals(1, $firstRoot->getLeftBound()); - $this->assertEquals(2, $firstRoot->getRightBound()); + $this->assertEquals(2, $firstRoot->getLeftBound()); + $this->assertEquals(3, $firstRoot->getRightBound()); $secondRoot = $this->createCategory('Bar'); $secondRoot = $this->categoryMapper->create($secondRoot); $this->assertInternalType('integer', $secondRoot->getId()); - $this->assertEquals(1, $secondRoot->getLeftBound()); - $this->assertEquals(2, $secondRoot->getRightBound()); + $this->assertEquals(4, $secondRoot->getLeftBound()); + $this->assertEquals(5, $secondRoot->getRightBound()); } public function testCanAddNewCategory() { - // Root category (left bound = 1, right bound = 2) + // Root category (left bound = 2, right bound = 3) $category = $this->createCategory('Foo'); $category = $this->categoryMapper->create($category); - // Node category whose parent is previous category (left bound = 2, right bound = 3) + // Node category whose parent is previous category (left bound = 3, right bound = 4) $childCategory = $this->createCategory("Foo's child", $category); $childCategory = $this->categoryMapper->create($childCategory); $this->assertInternalType('integer', $childCategory->getId()); - $this->assertEquals(2, $childCategory->getLeftBound()); - $this->assertEquals(3, $childCategory->getRightBound()); + $this->assertEquals(3, $childCategory->getLeftBound()); + $this->assertEquals(4, $childCategory->getRightBound()); $this->assertTrue($childCategory->isLeaf()); - // Root category should now have left bound = 1, right bound = 4 - $category = $this->categoryMapper->find(1); + // Root category should now have left bound = 2, right bound = 5 + $category = $this->categoryMapper->find($category->getId()); $this->assertInternalType('integer', $category->getId()); - $this->assertEquals(1, $category->getLeftBound()); - $this->assertEquals(4, $category->getRightBound()); + $this->assertEquals(2, $category->getLeftBound()); + $this->assertEquals(5, $category->getRightBound()); $this->assertFalse($category->isLeaf()); $this->assertEquals(1, $category->getChildrenCount()); } public function testCanAddMultipleCategories() { - // Root category (left bound = 1, right bound = 2) + // Root category (left bound = 2, right bound = 3) $category = $this->createCategory('Foo'); $category = $this->categoryMapper->create($category); - // Node category whose parent is previous category (left bound = 2, right bound = 3) + // Node category whose parent is previous category (left bound = 3, right bound = 4) $firstChild = $this->createCategory("Foo's First Child", $category); $this->categoryMapper->create($firstChild); - $category = $this->categoryMapper->find(1); + $category = $this->categoryMapper->find($category->getId()); - // Node category whose parent is previous category (left bound = 4, right bound = 5) + // Node category whose parent is previous category (left bound = 5, right bound = 6) $secondChild = $this->createCategory("Foo's Second Child", $category); $this->categoryMapper->create($secondChild); // Root category should now have left bound = 1, right bound = 6 - $category = $this->categoryMapper->find(1); + $category = $this->categoryMapper->find($category->getId()); $this->assertInternalType('integer', $category->getId()); - $this->assertEquals(1, $category->getLeftBound()); - $this->assertEquals(6, $category->getRightBound()); + $this->assertEquals(2, $category->getLeftBound()); + $this->assertEquals(7, $category->getRightBound()); $this->assertFalse($category->isLeaf()); $this->assertEquals(2, $category->getChildrenCount()); } public function testCanRemoveCategory() { - // Root category (left bound = 1, right bound = 2) + // Root category (left bound = 2, right bound = 3) $category = $this->createCategory('Foo'); $category = $this->categoryMapper->create($category); - // Node category whose parent is previous category (left bound = 2, right bound = 3) + // Node category whose parent is previous category (left bound = 3, right bound = 4) $childCategory = $this->createCategory("Foo's child", $category); $childCategory = $this->categoryMapper->create($childCategory); $this->categoryMapper->remove($childCategory); - // Root category now have again left bound = 1, right bound = 2 + // Root category now have again left bound = 2, right bound = 3 $category = $this->categoryMapper->find($category->getId()); - $this->assertEquals(1, $category->getLeftBound()); - $this->assertEquals(2, $category->getRightBound()); + $this->assertEquals(2, $category->getLeftBound()); + $this->assertEquals(3, $category->getRightBound()); $this->assertTrue($category->isLeaf()); $this->assertEquals(0, $category->getChildrenCount()); } public function testCanRemoveChildCategoryWhenParentNodeHaveMultipleCategories() { - // Root category (left bound = 1, right bound = 2) + // Root category (left bound = 2, right bound = 3) $category = $this->createCategory('Foo'); $category = $this->categoryMapper->create($category); - // Node category whose parent is previous category (left bound = 2, right bound = 3) + // Node category whose parent is previous category (left bound = 3, right bound = 4) $firstChild = $this->createCategory("Foo's First Child", $category); $firstChild = $this->categoryMapper->create($firstChild); $category = $this->categoryMapper->find($category->getId()); - // Node category whose parent is previous category (left bound = 4, right bound = 5) + // Node category whose parent is previous category (left bound = 5, right bound = 6) $secondChild = $this->createCategory("Foo's Second Child", $category); $secondChild = $this->categoryMapper->create($secondChild); @@ -173,14 +177,14 @@ public function testCanRemoveChildCategoryWhenParentNodeHaveMultipleCategories() $this->categoryMapper->remove($firstChild); $secondChild = $this->categoryMapper->find($secondChild->getId()); - $this->assertEquals(2, $secondChild->getLeftBound()); - $this->assertEquals(3, $secondChild->getRightBound()); + $this->assertEquals(3, $secondChild->getLeftBound()); + $this->assertEquals(4, $secondChild->getRightBound()); $this->assertTrue($secondChild->isLeaf()); $this->assertEquals(0, $secondChild->getChildrenCount()); $category = $this->categoryMapper->find($category->getId()); - $this->assertEquals(1, $category->getLeftBound()); - $this->assertEquals(4, $category->getRightBound()); + $this->assertEquals(2, $category->getLeftBound()); + $this->assertEquals(5, $category->getRightBound()); $this->assertFalse($category->isLeaf()); $this->assertEquals(1, $category->getChildrenCount()); } diff --git a/tests/ZfrForumTest/Repository/PostRepositoryTest.php b/tests/ZfrForumTest/Repository/PostRepositoryTest.php new file mode 100644 index 0000000..0953214 --- /dev/null +++ b/tests/ZfrForumTest/Repository/PostRepositoryTest.php @@ -0,0 +1,107 @@ +createDb(); + $this->postMapper = self::getServiceManager()->get('ZfrForum\Mapper\PostMapperInterface'); + $this->reportMapper = self::getServiceManager()->get('ZfrForum\Mapper\ReportMapperInterface'); + + // Init the fixture + $loader = new FixtureLoader(); + $loader->addFixture(new Fixture\CategoryFixture()); + $loader->addFixture(new Fixture\UserFixture()); + $loader->addFixture(new Fixture\ThreadFixture()); + $purger = new ORMPurger(); + $em = $this->getEntityManager(); + $this->executor = new ORMExecutor($em, $purger); + $this->executor->execute($loader->getFixtures()); + } + + public function tearDown() + { + $this->dropDb(); + } + + public function testCanReportAPost() + { + $repository = $this->executor->getReferenceRepository(); + $post = $repository->getReference('thread-0')->getLastPost(); + $reportedBy = $repository->getReference('user-1'); + + $report = new Report(); + $report->setPost($post) + ->setDescription('This post is spam !') + ->setReportedBy($reportedBy) + ->setReportedAt(new DateTime('now')); + + $this->reportMapper->create($report); + + $this->assertInternalType('integer', $report->getId()); + + $reports = $this->reportMapper->findByPost($post); + + $this->assertInstanceOf('Zend\Paginator\Paginator', $reports); + $this->assertEquals(1, $reports->getTotalItemCount()); + + + // Let's add another report + $report = new Report(); + $report->setPost($post) + ->setDescription('This post is REALLY a spam !') + ->setReportedBy($repository->getReference('user-2')) + ->setReportedAt(new DateTime('now')); + + $this->reportMapper->create($report); + + $reports = $this->reportMapper->findByPost($post); + + $this->assertInstanceOf('Zend\Paginator\Paginator', $reports); + $this->assertEquals(2, $reports->getTotalItemCount()); + } +} diff --git a/tests/ZfrForumTest/Repository/ThreadRepositoryTest.php b/tests/ZfrForumTest/Repository/ThreadRepositoryTest.php new file mode 100644 index 0000000..54b0585 --- /dev/null +++ b/tests/ZfrForumTest/Repository/ThreadRepositoryTest.php @@ -0,0 +1,120 @@ +createDb(); + $this->threadMapper = self::getServiceManager()->get('ZfrForum\Mapper\ThreadMapperInterface'); + + // Init the fixture + $loader = new FixtureLoader(); + $loader->addFixture(new Fixture\CategoryFixture()); + $loader->addFixture(new Fixture\UserFixture()); + $loader->addFixture(new Fixture\ThreadFixture()); + $purger = new ORMPurger(); + $em = $this->getEntityManager(); + $this->executor = new ORMExecutor($em, $purger); + $this->executor->execute($loader->getFixtures()); + } + + public function tearDown() + { + $this->dropDb(); + } + + public function testCanGetThreadsByCategoryAsPaginator() + { + $category = $this->executor->getReferenceRepository()->getReference('category-0'); + $threads = $this->threadMapper->findByCategory($category); + + $this->assertInstanceOf('Zend\Paginator\Paginator', $threads); + $this->assertEquals(1, $threads->getTotalItemCount()); + + $thread = $threads->getItem(1); + $this->assertInstanceOf('ZfrForum\Entity\Thread', $thread); + $this->assertEquals($category->getName(), $thread->getCategory()->getName()); + } + + /** + * Finding threads by category is either : + * - not strict (default): given a category, find all the threads in the category BUT also all the threads of + * the children categories + * - strict: only find threads in the given categories. + */ + public function testGetThreadsByCategoryUsingStrictSearch() + { + $subCategory = $this->executor->getReferenceRepository()->getReference('category-0-1'); + + // Let's add a thread in this sub-category + $user = $this->executor->getReferenceRepository()->getReference('user-0'); + $thread = new Thread(); + $thread->setTitle('Foo thread') + ->setCreatedBy($user) + ->setCategory($subCategory) + ->setCreatedAt(new DateTime('now')); + + $post = new Post(); + $post->setContent('France ftw') + ->setAuthor($user) + ->setSentAt(new DateTime('now')); + + $thread->addPost($post); + + $this->threadMapper->create($thread); + + + // The parent category should now have 2 threads + $category = $this->executor->getReferenceRepository()->getReference('category-0'); + $this->getEntityManager()->refresh($category); + + $threads = $this->threadMapper->findByCategory($category); + + $this->assertInstanceOf('Zend\Paginator\Paginator', $threads); + $this->assertEquals(2, $threads->getTotalItemCount()); + + // When using strict, only the one in the parent should appear + $threads = $this->threadMapper->findByCategory($category, true); + + $this->assertInstanceOf('Zend\Paginator\Paginator', $threads); + $this->assertEquals(1, $threads->getTotalItemCount()); + } +} diff --git a/tests/ZfrForumTest/ServiceManagerTestCase.php b/tests/ZfrForumTest/ServiceManagerTestCase.php index 9b6203d..56ebea1 100755 --- a/tests/ZfrForumTest/ServiceManagerTestCase.php +++ b/tests/ZfrForumTest/ServiceManagerTestCase.php @@ -104,5 +104,13 @@ public static function getServiceManager() { return self::$serviceManager; } + + /** + * @return \Doctrine\ORM\EntityManager + */ + public function getEntityManager() + { + return self::$serviceManager->get('Doctrine\ORM\EntityManager'); + } }