SoftDeleteableEntityTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. <?php
  2. namespace Gedmo\SoftDeleteable;
  3. use Tool\BaseTestCaseORM;
  4. use Doctrine\Common\EventManager;
  5. use Doctrine\Common\Util\Debug,
  6. SoftDeleteable\Fixture\Entity\Article,
  7. SoftDeleteable\Fixture\Entity\Comment,
  8. SoftDeleteable\Fixture\Entity\User,
  9. SoftDeleteable\Fixture\Entity\Page,
  10. SoftDeleteable\Fixture\Entity\MegaPage,
  11. SoftDeleteable\Fixture\Entity\Module,
  12. SoftDeleteable\Fixture\Entity\OtherArticle,
  13. SoftDeleteable\Fixture\Entity\OtherComment,
  14. Gedmo\SoftDeleteable\SoftDeleteableListener;
  15. /**
  16. * These are tests for SoftDeleteable behavior
  17. *
  18. * @author Gustavo Falco <comfortablynumb84@gmail.com>
  19. * @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
  20. * @author Patrik Votoček <patrik@votocek.cz>
  21. * @package Gedmo.SoftDeleteable
  22. * @link http://www.gediminasm.org
  23. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  24. */
  25. class SoftDeleteableEntityTest extends BaseTestCaseORM
  26. {
  27. const ARTICLE_CLASS = 'SoftDeleteable\Fixture\Entity\Article';
  28. const COMMENT_CLASS = 'SoftDeleteable\Fixture\Entity\Comment';
  29. const PAGE_CLASS = 'SoftDeleteable\Fixture\Entity\Page';
  30. const MEGA_PAGE_CLASS = 'SoftDeleteable\Fixture\Entity\MegaPage';
  31. const MODULE_CLASS = 'SoftDeleteable\Fixture\Entity\Module';
  32. const OTHER_ARTICLE_CLASS = 'SoftDeleteable\Fixture\Entity\OtherArticle';
  33. const OTHER_COMMENT_CLASS = 'SoftDeleteable\Fixture\Entity\OtherComment';
  34. const USER_CLASS = 'SoftDeleteable\Fixture\Entity\User';
  35. const SOFT_DELETEABLE_FILTER_NAME = 'soft-deleteable';
  36. private $softDeleteableListener;
  37. protected function setUp()
  38. {
  39. parent::setUp();
  40. $evm = new EventManager();
  41. $this->softDeleteableListener = new SoftDeleteableListener();
  42. $evm->addEventSubscriber($this->softDeleteableListener);
  43. $config = $this->getMockAnnotatedConfig();
  44. $config->addFilter(self::SOFT_DELETEABLE_FILTER_NAME, 'Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter');
  45. $this->em = $this->getMockSqliteEntityManager($evm, $config);
  46. $this->em->getFilters()->enable(self::SOFT_DELETEABLE_FILTER_NAME);
  47. }
  48. /**
  49. * @test
  50. */
  51. public function shouldSoftlyDeleteIfColumnNameDifferFromPropertyName()
  52. {
  53. $repo = $this->em->getRepository(self::USER_CLASS);
  54. $newUser = new User();
  55. $username = 'test_user';
  56. $newUser->setUsername($username);
  57. $this->em->persist($newUser);
  58. $this->em->flush();
  59. $user = $repo->findOneBy(array('username' => $username));
  60. $this->assertNull($user->getDeletedAt());
  61. $this->em->remove($user);
  62. $this->em->flush();
  63. $user = $repo->findOneBy(array('username' => $username));
  64. $this->assertNull($user);
  65. }
  66. public function testSoftDeleteable()
  67. {
  68. $repo = $this->em->getRepository(self::ARTICLE_CLASS);
  69. $commentRepo = $this->em->getRepository(self::COMMENT_CLASS);
  70. $comment = new Comment();
  71. $commentField = 'comment';
  72. $commentValue = 'Comment 1';
  73. $comment->setComment($commentValue);
  74. $art0 = new Article();
  75. $field = 'title';
  76. $value = 'Title 1';
  77. $art0->setTitle($value);
  78. $art0->addComment($comment);
  79. $this->em->persist($art0);
  80. $this->em->flush();
  81. $art = $repo->findOneBy(array($field => $value));
  82. $this->assertNull($art->getDeletedAt());
  83. $this->assertNull($comment->getDeletedAt());
  84. $this->em->remove($art);
  85. $this->em->flush();
  86. $art = $repo->findOneBy(array($field => $value));
  87. $this->assertNull($art);
  88. $comment = $commentRepo->findOneBy(array($commentField => $commentValue));
  89. $this->assertNull($comment);
  90. // Now we deactivate the filter so we test if the entity appears in the result
  91. $this->em->getFilters()->disable(self::SOFT_DELETEABLE_FILTER_NAME);
  92. $this->em->clear();
  93. $art = $repo->findOneBy(array($field => $value));
  94. $this->assertTrue(is_object($art));
  95. $this->assertTrue(is_object($art->getDeletedAt()));
  96. $this->assertTrue($art->getDeletedAt() instanceof \DateTime);
  97. $comment = $commentRepo->findOneBy(array($commentField => $commentValue));
  98. $this->assertTrue(is_object($comment));
  99. $this->assertTrue(is_object($comment->getDeletedAt()));
  100. $this->assertTrue($comment->getDeletedAt() instanceof \DateTime);
  101. $this->em->createQuery('UPDATE '.self::ARTICLE_CLASS.' a SET a.deletedAt = NULL')->execute();
  102. $this->em->refresh($art);
  103. $this->em->refresh($comment);
  104. // Now we try with a DQL Delete query
  105. $this->em->getFilters()->enable(self::SOFT_DELETEABLE_FILTER_NAME);
  106. $dql = sprintf('DELETE FROM %s a WHERE a.%s = :%s',
  107. self::ARTICLE_CLASS, $field, $field);
  108. $query = $this->em->createQuery($dql);
  109. $query->setParameter($field, $value);
  110. $query->setHint(
  111. \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
  112. 'Gedmo\SoftDeleteable\Query\TreeWalker\SoftDeleteableWalker'
  113. );
  114. $query->execute();
  115. $art = $repo->findOneBy(array($field => $value));
  116. $this->assertNull($art);
  117. // Now we deactivate the filter so we test if the entity appears in the result
  118. $this->em->getFilters()->disable(self::SOFT_DELETEABLE_FILTER_NAME);
  119. $this->em->clear();
  120. $art = $repo->findOneBy(array($field => $value));
  121. $this->assertTrue(is_object($art));
  122. $this->assertTrue(is_object($art->getDeletedAt()));
  123. $this->assertTrue($art->getDeletedAt() instanceof \DateTime);
  124. // Inheritance tree DELETE DQL
  125. $this->em->getFilters()->enable(self::SOFT_DELETEABLE_FILTER_NAME);
  126. $megaPageRepo = $this->em->getRepository(self::MEGA_PAGE_CLASS);
  127. $module = new Module();
  128. $module->setTitle('Module 1');
  129. $page = new MegaPage();
  130. $page->setTitle('Page 1');
  131. $page->addModule($module);
  132. $module->setPage($page);
  133. $this->em->persist($page);
  134. $this->em->persist($module);
  135. $this->em->flush();
  136. $dql = sprintf('DELETE FROM %s p',
  137. self::PAGE_CLASS);
  138. $query = $this->em->createQuery($dql);
  139. $query->setHint(
  140. \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
  141. 'Gedmo\SoftDeleteable\Query\TreeWalker\SoftDeleteableWalker'
  142. );
  143. $query->execute();
  144. $p = $megaPageRepo->findOneBy(array('title' => 'Page 1'));
  145. $this->assertNull($p);
  146. // Now we deactivate the filter so we test if the entity appears in the result
  147. $this->em->getFilters()->disable(self::SOFT_DELETEABLE_FILTER_NAME);
  148. $this->em->clear();
  149. $p = $megaPageRepo->findOneBy(array('title' => 'Page 1'));
  150. $this->assertTrue(is_object($p));
  151. $this->assertTrue(is_object($p->getDeletedAt()));
  152. $this->assertTrue($p->getDeletedAt() instanceof \DateTime);
  153. // Test of #301
  154. $this->em->getFilters()->enable(self::SOFT_DELETEABLE_FILTER_NAME);
  155. $otherArticleRepo = $this->em->getRepository(self::OTHER_ARTICLE_CLASS);
  156. $otherCommentRepo = $this->em->getRepository(self::OTHER_COMMENT_CLASS);
  157. $otherArt = new OtherArticle();
  158. $otherComment = new OtherComment();
  159. $otherArt->setTitle('Page 1');
  160. $otherComment->setComment('Comment');
  161. $otherArt->addComment($otherComment);
  162. $otherComment->setArticle($otherArt);
  163. $this->em->persist($otherArt);
  164. $this->em->persist($otherComment);
  165. $this->em->flush();
  166. $this->em->refresh($otherArt);
  167. $this->em->refresh($otherComment);
  168. $artId = $otherArt->getId();
  169. $commentId = $otherComment->getId();
  170. $this->em->remove($otherArt);
  171. $this->em->flush();
  172. $foundArt = $otherArticleRepo->findOneBy(array('id' => $artId));
  173. $foundComment = $otherCommentRepo->findOneBy(array('id' => $commentId));
  174. $this->assertNull($foundArt);
  175. $this->assertTrue(is_object($foundComment));
  176. $this->assertInstanceOf(self::OTHER_COMMENT_CLASS, $foundComment);
  177. $this->em->getFilters()->disable(self::SOFT_DELETEABLE_FILTER_NAME);
  178. $foundArt = $otherArticleRepo->findOneById($artId);
  179. $foundComment = $otherCommentRepo->findOneById($commentId);
  180. $this->assertTrue(is_object($foundArt));
  181. $this->assertTrue(is_object($foundArt->getDeletedAt()));
  182. $this->assertTrue($foundArt->getDeletedAt() instanceof \DateTime);
  183. $this->assertTrue(is_object($foundComment));
  184. $this->assertInstanceOf(self::OTHER_COMMENT_CLASS, $foundComment);
  185. }
  186. public function testSoftDeleteableFilter()
  187. {
  188. $filter = $this->em->getFilters()->enable(self::SOFT_DELETEABLE_FILTER_NAME);
  189. $filter->disableForEntity(self::USER_CLASS);
  190. $repo = $this->em->getRepository(self::USER_CLASS);
  191. $newUser = new User();
  192. $username = 'test_user';
  193. $newUser->setUsername($username);
  194. $this->em->persist($newUser);
  195. $this->em->flush();
  196. $user = $repo->findOneBy(array('username' => $username));
  197. $this->assertNull($user->getDeletedAt());
  198. $this->em->remove($user);
  199. $this->em->flush();
  200. $user = $repo->findOneBy(array('username' => $username));
  201. $this->assertNotNull($user->getDeletedAt());
  202. $filter->enableForEntity(self::USER_CLASS);
  203. $user = $repo->findOneBy(array('username' => $username));
  204. $this->assertNull($user);
  205. }
  206. public function testPostSoftDeleteEventIsDispatched()
  207. {
  208. $subscriber = $this->getMock(
  209. "Doctrine\Common\EventSubscriber",
  210. array(
  211. "getSubscribedEvents",
  212. "preSoftDelete",
  213. "postSoftDelete"
  214. )
  215. );
  216. $subscriber->expects($this->once())
  217. ->method("getSubscribedEvents")
  218. ->will($this->returnValue(array(SoftDeleteableListener::PRE_SOFT_DELETE, SoftDeleteableListener::POST_SOFT_DELETE)));
  219. $subscriber->expects($this->exactly(2))
  220. ->method("preSoftDelete")
  221. ->with($this->anything());
  222. $subscriber->expects($this->exactly(2))
  223. ->method("postSoftDelete")
  224. ->with($this->anything());
  225. $this->em->getEventManager()->addEventSubscriber($subscriber);
  226. $repo = $this->em->getRepository(self::ARTICLE_CLASS);
  227. $commentRepo = $this->em->getRepository(self::COMMENT_CLASS);
  228. $comment = new Comment();
  229. $commentField = 'comment';
  230. $commentValue = 'Comment 1';
  231. $comment->setComment($commentValue);
  232. $art0 = new Article();
  233. $field = 'title';
  234. $value = 'Title 1';
  235. $art0->setTitle($value);
  236. $art0->addComment($comment);
  237. $this->em->persist($art0);
  238. $this->em->flush();
  239. $art = $repo->findOneBy(array($field => $value));
  240. $this->assertNull($art->getDeletedAt());
  241. $this->assertNull($comment->getDeletedAt());
  242. $this->em->remove($art);
  243. $this->em->flush();
  244. }
  245. protected function getUsedEntityFixtures()
  246. {
  247. return array(
  248. self::ARTICLE_CLASS,
  249. self::PAGE_CLASS,
  250. self::MEGA_PAGE_CLASS,
  251. self::MODULE_CLASS,
  252. self::COMMENT_CLASS,
  253. self::USER_CLASS,
  254. self::OTHER_ARTICLE_CLASS,
  255. self::OTHER_COMMENT_CLASS
  256. );
  257. }
  258. }