2008-06-16 22:31:21 +04:00
|
|
|
<?php
|
2009-01-04 19:15:32 +03:00
|
|
|
|
2009-01-22 22:38:10 +03:00
|
|
|
namespace Doctrine\Tests\ORM;
|
2009-01-04 19:15:32 +03:00
|
|
|
|
2010-07-04 20:55:49 +04:00
|
|
|
use Doctrine\ORM\UnitOfWork;
|
2009-01-22 22:38:10 +03:00
|
|
|
use Doctrine\Tests\Mocks\ConnectionMock;
|
|
|
|
use Doctrine\Tests\Mocks\EntityManagerMock;
|
|
|
|
use Doctrine\Tests\Mocks\UnitOfWorkMock;
|
|
|
|
use Doctrine\Tests\Mocks\EntityPersisterMock;
|
|
|
|
use Doctrine\Tests\Mocks\IdentityIdGeneratorMock;
|
|
|
|
use Doctrine\Tests\Models\Forum\ForumUser;
|
|
|
|
use Doctrine\Tests\Models\Forum\ForumAvatar;
|
|
|
|
|
2009-01-24 19:56:44 +03:00
|
|
|
require_once __DIR__ . '/../TestInit.php';
|
2009-01-22 22:38:10 +03:00
|
|
|
|
2008-07-21 00:13:24 +04:00
|
|
|
/**
|
|
|
|
* UnitOfWork tests.
|
|
|
|
*/
|
2009-01-22 22:38:10 +03:00
|
|
|
class UnitOfWorkTest extends \Doctrine\Tests\OrmTestCase
|
2008-06-16 22:31:21 +04:00
|
|
|
{
|
2009-01-04 19:15:32 +03:00
|
|
|
// SUT
|
2008-06-16 22:31:21 +04:00
|
|
|
private $_unitOfWork;
|
2008-07-21 00:13:24 +04:00
|
|
|
// Provides a sequence mock to the UnitOfWork
|
|
|
|
private $_connectionMock;
|
2009-01-04 19:15:32 +03:00
|
|
|
// The EntityManager mock that provides the mock persisters
|
2008-07-21 00:13:24 +04:00
|
|
|
private $_emMock;
|
|
|
|
|
2008-06-16 22:31:21 +04:00
|
|
|
protected function setUp() {
|
|
|
|
parent::setUp();
|
2009-02-17 15:25:03 +03:00
|
|
|
$this->_connectionMock = new ConnectionMock(array(), new \Doctrine\Tests\Mocks\DriverMock());
|
2009-02-17 14:02:11 +03:00
|
|
|
$this->_emMock = EntityManagerMock::create($this->_connectionMock);
|
2008-09-07 17:48:40 +04:00
|
|
|
// SUT
|
2009-01-22 22:38:10 +03:00
|
|
|
$this->_unitOfWork = new UnitOfWorkMock($this->_emMock);
|
2009-01-03 22:50:13 +03:00
|
|
|
$this->_emMock->setUnitOfWork($this->_unitOfWork);
|
2008-06-16 22:31:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
protected function tearDown() {
|
|
|
|
}
|
|
|
|
|
2008-07-21 00:13:24 +04:00
|
|
|
public function testRegisterRemovedOnNewEntityIsIgnored()
|
2008-06-16 22:31:21 +04:00
|
|
|
{
|
2009-01-03 22:50:13 +03:00
|
|
|
$user = new ForumUser();
|
|
|
|
$user->username = 'romanb';
|
2009-07-19 20:54:53 +04:00
|
|
|
$this->assertFalse($this->_unitOfWork->isScheduledForDelete($user));
|
|
|
|
$this->_unitOfWork->scheduleForDelete($user);
|
|
|
|
$this->assertFalse($this->_unitOfWork->isScheduledForDelete($user));
|
2008-06-16 22:31:21 +04:00
|
|
|
}
|
|
|
|
|
2008-07-21 00:13:24 +04:00
|
|
|
|
|
|
|
/* Operational tests */
|
|
|
|
|
|
|
|
public function testSavingSingleEntityWithIdentityColumnForcesInsert()
|
2009-01-03 22:50:13 +03:00
|
|
|
{
|
|
|
|
// Setup fake persister and id generator for identity generation
|
2009-01-22 22:38:10 +03:00
|
|
|
$userPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumUser"));
|
2009-02-02 14:55:50 +03:00
|
|
|
$this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumUser', $userPersister);
|
2009-03-30 23:43:05 +04:00
|
|
|
//$idGeneratorMock = new IdentityIdGeneratorMock($this->_emMock);
|
|
|
|
//$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumUser', $idGeneratorMock);
|
2009-01-22 22:38:10 +03:00
|
|
|
$userPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY);
|
2009-01-03 22:50:13 +03:00
|
|
|
|
|
|
|
// Test
|
|
|
|
$user = new ForumUser();
|
|
|
|
$user->username = 'romanb';
|
2009-07-19 20:54:53 +04:00
|
|
|
$this->_unitOfWork->persist($user);
|
2009-01-03 22:50:13 +03:00
|
|
|
|
|
|
|
// Check
|
2009-07-19 20:54:53 +04:00
|
|
|
$this->assertEquals(0, count($userPersister->getInserts()));
|
2009-01-03 22:50:13 +03:00
|
|
|
$this->assertEquals(0, count($userPersister->getUpdates()));
|
|
|
|
$this->assertEquals(0, count($userPersister->getDeletes()));
|
2009-07-19 20:54:53 +04:00
|
|
|
$this->assertFalse($this->_unitOfWork->isInIdentityMap($user));
|
2008-07-21 00:13:24 +04:00
|
|
|
// should no longer be scheduled for insert
|
2009-07-19 20:54:53 +04:00
|
|
|
$this->assertTrue($this->_unitOfWork->isScheduledForInsert($user));
|
2008-07-21 00:13:24 +04:00
|
|
|
|
2008-08-01 22:46:14 +04:00
|
|
|
// Now lets check whether a subsequent commit() does anything
|
2009-01-03 22:50:13 +03:00
|
|
|
$userPersister->reset();
|
|
|
|
|
|
|
|
// Test
|
2009-07-19 20:54:53 +04:00
|
|
|
$this->_unitOfWork->commit();
|
2008-07-21 00:13:24 +04:00
|
|
|
|
2009-07-19 20:54:53 +04:00
|
|
|
// Check.
|
|
|
|
$this->assertEquals(1, count($userPersister->getInserts()));
|
2009-01-03 22:50:13 +03:00
|
|
|
$this->assertEquals(0, count($userPersister->getUpdates()));
|
|
|
|
$this->assertEquals(0, count($userPersister->getDeletes()));
|
2009-07-19 20:54:53 +04:00
|
|
|
|
|
|
|
// should have an id
|
|
|
|
$this->assertTrue(is_numeric($user->id));
|
2008-07-21 00:13:24 +04:00
|
|
|
}
|
2009-01-03 22:50:13 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Tests a scenario where a save() operation is cascaded from a ForumUser
|
|
|
|
* to its associated ForumAvatar, both entities using IDENTITY id generation.
|
|
|
|
*/
|
|
|
|
public function testCascadedIdentityColumnInsert()
|
2008-08-22 13:05:14 +04:00
|
|
|
{
|
2009-01-03 22:50:13 +03:00
|
|
|
// Setup fake persister and id generator for identity generation
|
|
|
|
//ForumUser
|
2009-01-22 22:38:10 +03:00
|
|
|
$userPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumUser"));
|
2009-02-02 14:55:50 +03:00
|
|
|
$this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumUser', $userPersister);
|
2009-03-30 23:43:05 +04:00
|
|
|
//$userIdGeneratorMock = new IdentityIdGeneratorMock($this->_emMock);
|
|
|
|
//$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumUser', $userIdGeneratorMock);
|
2009-01-22 22:38:10 +03:00
|
|
|
$userPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY);
|
2009-01-03 22:50:13 +03:00
|
|
|
// ForumAvatar
|
2009-01-22 22:38:10 +03:00
|
|
|
$avatarPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumAvatar"));
|
2009-02-02 14:55:50 +03:00
|
|
|
$this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumAvatar', $avatarPersister);
|
2009-03-30 23:43:05 +04:00
|
|
|
//$avatarIdGeneratorMock = new IdentityIdGeneratorMock($this->_emMock);
|
|
|
|
//$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumAvatar', $avatarIdGeneratorMock);
|
2009-01-22 22:38:10 +03:00
|
|
|
$avatarPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY);
|
2009-01-03 22:50:13 +03:00
|
|
|
|
|
|
|
// Test
|
|
|
|
$user = new ForumUser();
|
|
|
|
$user->username = 'romanb';
|
2008-08-22 13:05:14 +04:00
|
|
|
$avatar = new ForumAvatar();
|
2009-01-03 22:50:13 +03:00
|
|
|
$user->avatar = $avatar;
|
2009-07-19 20:54:53 +04:00
|
|
|
$this->_unitOfWork->persist($user); // save cascaded to avatar
|
|
|
|
|
|
|
|
$this->_unitOfWork->commit();
|
2009-01-03 22:50:13 +03:00
|
|
|
|
|
|
|
$this->assertTrue(is_numeric($user->id));
|
|
|
|
$this->assertTrue(is_numeric($avatar->id));
|
|
|
|
|
2009-07-19 20:54:53 +04:00
|
|
|
$this->assertEquals(1, count($userPersister->getInserts()));
|
2009-01-03 22:50:13 +03:00
|
|
|
$this->assertEquals(0, count($userPersister->getUpdates()));
|
|
|
|
$this->assertEquals(0, count($userPersister->getDeletes()));
|
|
|
|
|
2009-07-19 20:54:53 +04:00
|
|
|
$this->assertEquals(1, count($avatarPersister->getInserts()));
|
2009-01-03 22:50:13 +03:00
|
|
|
$this->assertEquals(0, count($avatarPersister->getUpdates()));
|
|
|
|
$this->assertEquals(0, count($avatarPersister->getDeletes()));
|
2008-08-22 13:05:14 +04:00
|
|
|
}
|
2009-01-03 22:50:13 +03:00
|
|
|
|
2009-04-25 01:08:59 +04:00
|
|
|
public function testChangeTrackingNotify()
|
2009-01-03 22:50:13 +03:00
|
|
|
{
|
2009-05-19 20:11:08 +04:00
|
|
|
$persister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\ORM\NotifyChangedEntity"));
|
|
|
|
$this->_unitOfWork->setEntityPersister('Doctrine\Tests\ORM\NotifyChangedEntity', $persister);
|
|
|
|
|
2009-04-25 01:08:59 +04:00
|
|
|
$entity = new NotifyChangedEntity;
|
|
|
|
$entity->setData('thedata');
|
2009-07-19 20:54:53 +04:00
|
|
|
$this->_unitOfWork->persist($entity);
|
|
|
|
|
|
|
|
$this->_unitOfWork->commit();
|
2009-04-25 01:08:59 +04:00
|
|
|
|
|
|
|
$this->assertTrue($this->_unitOfWork->isInIdentityMap($entity));
|
|
|
|
|
|
|
|
$entity->setData('newdata');
|
2010-05-01 14:14:16 +04:00
|
|
|
$entity->setTransient('newtransientvalue');
|
2009-04-25 01:08:59 +04:00
|
|
|
|
2009-07-19 20:54:53 +04:00
|
|
|
$this->assertTrue($this->_unitOfWork->isScheduledForUpdate($entity));
|
2009-04-25 01:08:59 +04:00
|
|
|
|
|
|
|
$this->assertEquals(array('data' => array('thedata', 'newdata')), $this->_unitOfWork->getEntityChangeSet($entity));
|
2009-01-03 22:50:13 +03:00
|
|
|
}
|
2009-04-25 01:08:59 +04:00
|
|
|
|
2010-07-04 20:55:49 +04:00
|
|
|
public function testGetEntityStateOnVersionedEntityWithAssignedIdentifier()
|
2008-07-21 00:13:24 +04:00
|
|
|
{
|
2010-07-04 20:55:49 +04:00
|
|
|
$persister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\ORM\VersionedAssignedIdentifierEntity"));
|
|
|
|
$this->_unitOfWork->setEntityPersister('Doctrine\Tests\ORM\VersionedAssignedIdentifierEntity', $persister);
|
|
|
|
|
|
|
|
$e = new VersionedAssignedIdentifierEntity();
|
|
|
|
$e->id = 42;
|
|
|
|
$this->assertEquals(UnitOfWork::STATE_NEW, $this->_unitOfWork->getEntityState($e));
|
|
|
|
$this->assertFalse($persister->isExistsCalled());
|
2008-07-21 00:13:24 +04:00
|
|
|
}
|
2010-07-04 20:55:49 +04:00
|
|
|
|
|
|
|
public function testGetEntityStateWithAssignedIdentity()
|
2008-07-21 00:13:24 +04:00
|
|
|
{
|
2010-07-04 20:55:49 +04:00
|
|
|
$persister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\CMS\CmsPhonenumber"));
|
|
|
|
$this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\CMS\CmsPhonenumber', $persister);
|
|
|
|
|
|
|
|
$ph = new \Doctrine\Tests\Models\CMS\CmsPhonenumber();
|
|
|
|
$ph->phonenumber = '12345';
|
|
|
|
|
|
|
|
$this->assertEquals(UnitOfWork::STATE_NEW, $this->_unitOfWork->getEntityState($ph));
|
|
|
|
$this->assertTrue($persister->isExistsCalled());
|
|
|
|
|
|
|
|
$persister->reset();
|
|
|
|
|
2010-07-08 02:20:54 +04:00
|
|
|
// if the entity is already managed the exists() check should be skipped
|
2010-07-04 20:55:49 +04:00
|
|
|
$this->_unitOfWork->registerManaged($ph, array('phonenumber' => '12345'), array());
|
|
|
|
$this->assertEquals(UnitOfWork::STATE_MANAGED, $this->_unitOfWork->getEntityState($ph));
|
|
|
|
$this->assertFalse($persister->isExistsCalled());
|
|
|
|
$ph2 = new \Doctrine\Tests\Models\CMS\CmsPhonenumber();
|
|
|
|
$ph2->phonenumber = '12345';
|
|
|
|
$this->assertEquals(UnitOfWork::STATE_DETACHED, $this->_unitOfWork->getEntityState($ph2));
|
|
|
|
$this->assertFalse($persister->isExistsCalled());
|
2008-07-21 00:13:24 +04:00
|
|
|
}
|
2009-04-25 01:08:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-05-29 14:23:13 +04:00
|
|
|
* @Entity
|
2009-04-25 01:08:59 +04:00
|
|
|
*/
|
|
|
|
class NotifyChangedEntity implements \Doctrine\Common\NotifyPropertyChanged
|
|
|
|
{
|
|
|
|
private $_listeners = array();
|
|
|
|
/**
|
2009-05-29 14:23:13 +04:00
|
|
|
* @Id
|
|
|
|
* @Column(type="integer")
|
2009-06-07 21:20:37 +04:00
|
|
|
* @GeneratedValue(strategy="AUTO")
|
2009-04-25 01:08:59 +04:00
|
|
|
*/
|
|
|
|
private $id;
|
|
|
|
/**
|
2009-05-29 14:23:13 +04:00
|
|
|
* @Column(type="string")
|
2009-04-25 01:08:59 +04:00
|
|
|
*/
|
|
|
|
private $data;
|
|
|
|
|
2010-05-01 14:14:16 +04:00
|
|
|
private $transient; // not persisted
|
|
|
|
|
2009-04-25 01:08:59 +04:00
|
|
|
public function getId() {
|
|
|
|
return $this->id;
|
|
|
|
}
|
|
|
|
|
2010-05-01 14:14:16 +04:00
|
|
|
public function setTransient($value) {
|
|
|
|
if ($value != $this->transient) {
|
|
|
|
$this->_onPropertyChanged('transient', $this->transient, $value);
|
|
|
|
$this->transient = $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-25 01:08:59 +04:00
|
|
|
public function getData() {
|
|
|
|
return $this->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setData($data) {
|
|
|
|
if ($data != $this->data) {
|
|
|
|
$this->_onPropertyChanged('data', $this->data, $data);
|
|
|
|
$this->data = $data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addPropertyChangedListener(\Doctrine\Common\PropertyChangedListener $listener)
|
|
|
|
{
|
|
|
|
$this->_listeners[] = $listener;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function _onPropertyChanged($propName, $oldValue, $newValue) {
|
|
|
|
if ($this->_listeners) {
|
|
|
|
foreach ($this->_listeners as $listener) {
|
|
|
|
$listener->propertyChanged($this, $propName, $oldValue, $newValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-07-04 20:55:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @Entity */
|
|
|
|
class VersionedAssignedIdentifierEntity
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @Id @Column(type="integer")
|
|
|
|
*/
|
|
|
|
public $id;
|
|
|
|
/**
|
|
|
|
* @Version @Column(type="integer")
|
|
|
|
*/
|
|
|
|
public $version;
|
2008-06-16 22:31:21 +04:00
|
|
|
}
|