PageRenderTime 43ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/doctrine/orm/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php

https://bitbucket.org/iiic/iszp
PHP | 344 lines | 215 code | 62 blank | 67 comment | 5 complexity | 801107583a9565d4fbdae959918488fa MD5 | raw file
  1. <?php
  2. namespace Doctrine\Tests\ORM;
  3. use Doctrine\ORM\UnitOfWork;
  4. use Doctrine\Tests\Mocks\ConnectionMock;
  5. use Doctrine\Tests\Mocks\EntityManagerMock;
  6. use Doctrine\Tests\Mocks\UnitOfWorkMock;
  7. use Doctrine\Tests\Mocks\EntityPersisterMock;
  8. use Doctrine\Tests\Mocks\IdentityIdGeneratorMock;
  9. use Doctrine\Tests\Models\Forum\ForumUser;
  10. use Doctrine\Tests\Models\Forum\ForumAvatar;
  11. require_once __DIR__ . '/../TestInit.php';
  12. /**
  13. * UnitOfWork tests.
  14. */
  15. class UnitOfWorkTest extends \Doctrine\Tests\OrmTestCase
  16. {
  17. // SUT
  18. private $_unitOfWork;
  19. // Provides a sequence mock to the UnitOfWork
  20. private $_connectionMock;
  21. // The EntityManager mock that provides the mock persisters
  22. private $_emMock;
  23. protected function setUp() {
  24. parent::setUp();
  25. $this->_connectionMock = new ConnectionMock(array(), new \Doctrine\Tests\Mocks\DriverMock());
  26. $this->_emMock = EntityManagerMock::create($this->_connectionMock);
  27. // SUT
  28. $this->_unitOfWork = new UnitOfWorkMock($this->_emMock);
  29. $this->_emMock->setUnitOfWork($this->_unitOfWork);
  30. }
  31. protected function tearDown() {
  32. }
  33. public function testRegisterRemovedOnNewEntityIsIgnored()
  34. {
  35. $user = new ForumUser();
  36. $user->username = 'romanb';
  37. $this->assertFalse($this->_unitOfWork->isScheduledForDelete($user));
  38. $this->_unitOfWork->scheduleForDelete($user);
  39. $this->assertFalse($this->_unitOfWork->isScheduledForDelete($user));
  40. }
  41. /* Operational tests */
  42. public function testSavingSingleEntityWithIdentityColumnForcesInsert()
  43. {
  44. // Setup fake persister and id generator for identity generation
  45. $userPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumUser"));
  46. $this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumUser', $userPersister);
  47. //$idGeneratorMock = new IdentityIdGeneratorMock($this->_emMock);
  48. //$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumUser', $idGeneratorMock);
  49. $userPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY);
  50. // Test
  51. $user = new ForumUser();
  52. $user->username = 'romanb';
  53. $this->_unitOfWork->persist($user);
  54. // Check
  55. $this->assertEquals(0, count($userPersister->getInserts()));
  56. $this->assertEquals(0, count($userPersister->getUpdates()));
  57. $this->assertEquals(0, count($userPersister->getDeletes()));
  58. $this->assertFalse($this->_unitOfWork->isInIdentityMap($user));
  59. // should no longer be scheduled for insert
  60. $this->assertTrue($this->_unitOfWork->isScheduledForInsert($user));
  61. // Now lets check whether a subsequent commit() does anything
  62. $userPersister->reset();
  63. // Test
  64. $this->_unitOfWork->commit();
  65. // Check.
  66. $this->assertEquals(1, count($userPersister->getInserts()));
  67. $this->assertEquals(0, count($userPersister->getUpdates()));
  68. $this->assertEquals(0, count($userPersister->getDeletes()));
  69. // should have an id
  70. $this->assertTrue(is_numeric($user->id));
  71. }
  72. /**
  73. * Tests a scenario where a save() operation is cascaded from a ForumUser
  74. * to its associated ForumAvatar, both entities using IDENTITY id generation.
  75. */
  76. public function testCascadedIdentityColumnInsert()
  77. {
  78. // Setup fake persister and id generator for identity generation
  79. //ForumUser
  80. $userPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumUser"));
  81. $this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumUser', $userPersister);
  82. //$userIdGeneratorMock = new IdentityIdGeneratorMock($this->_emMock);
  83. //$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumUser', $userIdGeneratorMock);
  84. $userPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY);
  85. // ForumAvatar
  86. $avatarPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumAvatar"));
  87. $this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumAvatar', $avatarPersister);
  88. //$avatarIdGeneratorMock = new IdentityIdGeneratorMock($this->_emMock);
  89. //$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumAvatar', $avatarIdGeneratorMock);
  90. $avatarPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY);
  91. // Test
  92. $user = new ForumUser();
  93. $user->username = 'romanb';
  94. $avatar = new ForumAvatar();
  95. $user->avatar = $avatar;
  96. $this->_unitOfWork->persist($user); // save cascaded to avatar
  97. $this->_unitOfWork->commit();
  98. $this->assertTrue(is_numeric($user->id));
  99. $this->assertTrue(is_numeric($avatar->id));
  100. $this->assertEquals(1, count($userPersister->getInserts()));
  101. $this->assertEquals(0, count($userPersister->getUpdates()));
  102. $this->assertEquals(0, count($userPersister->getDeletes()));
  103. $this->assertEquals(1, count($avatarPersister->getInserts()));
  104. $this->assertEquals(0, count($avatarPersister->getUpdates()));
  105. $this->assertEquals(0, count($avatarPersister->getDeletes()));
  106. }
  107. public function testChangeTrackingNotify()
  108. {
  109. $persister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\ORM\NotifyChangedEntity"));
  110. $this->_unitOfWork->setEntityPersister('Doctrine\Tests\ORM\NotifyChangedEntity', $persister);
  111. $itemPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\ORM\NotifyChangedRelatedItem"));
  112. $this->_unitOfWork->setEntityPersister('Doctrine\Tests\ORM\NotifyChangedRelatedItem', $itemPersister);
  113. $entity = new NotifyChangedEntity;
  114. $entity->setData('thedata');
  115. $this->_unitOfWork->persist($entity);
  116. $this->_unitOfWork->commit();
  117. $this->assertEquals(1, count($persister->getInserts()));
  118. $persister->reset();
  119. $this->assertTrue($this->_unitOfWork->isInIdentityMap($entity));
  120. $entity->setData('newdata');
  121. $entity->setTransient('newtransientvalue');
  122. $this->assertTrue($this->_unitOfWork->isScheduledForDirtyCheck($entity));
  123. $this->assertEquals(array('data' => array('thedata', 'newdata')), $this->_unitOfWork->getEntityChangeSet($entity));
  124. $item = new NotifyChangedRelatedItem();
  125. $entity->getItems()->add($item);
  126. $item->setOwner($entity);
  127. $this->_unitOfWork->persist($item);
  128. $this->_unitOfWork->commit();
  129. $this->assertEquals(1, count($itemPersister->getInserts()));
  130. $persister->reset();
  131. $itemPersister->reset();
  132. $entity->getItems()->removeElement($item);
  133. $item->setOwner(null);
  134. $this->assertTrue($entity->getItems()->isDirty());
  135. $this->_unitOfWork->commit();
  136. $updates = $itemPersister->getUpdates();
  137. $this->assertEquals(1, count($updates));
  138. $this->assertTrue($updates[0] === $item);
  139. }
  140. public function testGetEntityStateOnVersionedEntityWithAssignedIdentifier()
  141. {
  142. $persister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\ORM\VersionedAssignedIdentifierEntity"));
  143. $this->_unitOfWork->setEntityPersister('Doctrine\Tests\ORM\VersionedAssignedIdentifierEntity', $persister);
  144. $e = new VersionedAssignedIdentifierEntity();
  145. $e->id = 42;
  146. $this->assertEquals(UnitOfWork::STATE_NEW, $this->_unitOfWork->getEntityState($e));
  147. $this->assertFalse($persister->isExistsCalled());
  148. }
  149. public function testGetEntityStateWithAssignedIdentity()
  150. {
  151. $persister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\CMS\CmsPhonenumber"));
  152. $this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\CMS\CmsPhonenumber', $persister);
  153. $ph = new \Doctrine\Tests\Models\CMS\CmsPhonenumber();
  154. $ph->phonenumber = '12345';
  155. $this->assertEquals(UnitOfWork::STATE_NEW, $this->_unitOfWork->getEntityState($ph));
  156. $this->assertTrue($persister->isExistsCalled());
  157. $persister->reset();
  158. // if the entity is already managed the exists() check should be skipped
  159. $this->_unitOfWork->registerManaged($ph, array('phonenumber' => '12345'), array());
  160. $this->assertEquals(UnitOfWork::STATE_MANAGED, $this->_unitOfWork->getEntityState($ph));
  161. $this->assertFalse($persister->isExistsCalled());
  162. $ph2 = new \Doctrine\Tests\Models\CMS\CmsPhonenumber();
  163. $ph2->phonenumber = '12345';
  164. $this->assertEquals(UnitOfWork::STATE_DETACHED, $this->_unitOfWork->getEntityState($ph2));
  165. $this->assertFalse($persister->isExistsCalled());
  166. }
  167. /**
  168. * DDC-2086 [GH-484] Prevented "Undefined index" notice when updating.
  169. */
  170. public function testNoUndefinedIndexNoticeOnScheduleForUpdateWithoutChanges()
  171. {
  172. // Setup fake persister and id generator
  173. $userPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumUser"));
  174. $userPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY);
  175. $this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumUser', $userPersister);
  176. // Create a test user
  177. $user = new ForumUser();
  178. $user->name = 'Jasper';
  179. $this->_unitOfWork->persist($user);
  180. $this->_unitOfWork->commit();
  181. // Schedule user for update without changes
  182. $this->_unitOfWork->scheduleForUpdate($user);
  183. // This commit should not raise an E_NOTICE
  184. $this->_unitOfWork->commit();
  185. }
  186. /**
  187. * @group DDC-1984
  188. */
  189. public function testLockWithoutEntityThrowsException()
  190. {
  191. $this->setExpectedException('InvalidArgumentException');
  192. $this->_unitOfWork->lock(null, null, null);
  193. }
  194. }
  195. /**
  196. * @Entity
  197. */
  198. class NotifyChangedEntity implements \Doctrine\Common\NotifyPropertyChanged
  199. {
  200. private $_listeners = array();
  201. /**
  202. * @Id
  203. * @Column(type="integer")
  204. * @GeneratedValue
  205. */
  206. private $id;
  207. /**
  208. * @Column(type="string")
  209. */
  210. private $data;
  211. private $transient; // not persisted
  212. /** @OneToMany(targetEntity="NotifyChangedRelatedItem", mappedBy="owner") */
  213. private $items;
  214. public function __construct() {
  215. $this->items = new \Doctrine\Common\Collections\ArrayCollection;
  216. }
  217. public function getId() {
  218. return $this->id;
  219. }
  220. public function getItems() {
  221. return $this->items;
  222. }
  223. public function setTransient($value) {
  224. if ($value != $this->transient) {
  225. $this->_onPropertyChanged('transient', $this->transient, $value);
  226. $this->transient = $value;
  227. }
  228. }
  229. public function getData() {
  230. return $this->data;
  231. }
  232. public function setData($data) {
  233. if ($data != $this->data) {
  234. $this->_onPropertyChanged('data', $this->data, $data);
  235. $this->data = $data;
  236. }
  237. }
  238. public function addPropertyChangedListener(\Doctrine\Common\PropertyChangedListener $listener)
  239. {
  240. $this->_listeners[] = $listener;
  241. }
  242. protected function _onPropertyChanged($propName, $oldValue, $newValue) {
  243. if ($this->_listeners) {
  244. foreach ($this->_listeners as $listener) {
  245. $listener->propertyChanged($this, $propName, $oldValue, $newValue);
  246. }
  247. }
  248. }
  249. }
  250. /** @Entity */
  251. class NotifyChangedRelatedItem
  252. {
  253. /**
  254. * @Id
  255. * @Column(type="integer")
  256. * @GeneratedValue
  257. */
  258. private $id;
  259. /** @ManyToOne(targetEntity="NotifyChangedEntity", inversedBy="items") */
  260. private $owner;
  261. public function getId() {
  262. return $this->id;
  263. }
  264. public function getOwner() {
  265. return $this->owner;
  266. }
  267. public function setOwner($owner) {
  268. $this->owner = $owner;
  269. }
  270. }
  271. /** @Entity */
  272. class VersionedAssignedIdentifierEntity
  273. {
  274. /**
  275. * @Id @Column(type="integer")
  276. */
  277. public $id;
  278. /**
  279. * @Version @Column(type="integer")
  280. */
  281. public $version;
  282. }