3 namespace Doctrine\Tests\ORM\Mapping;
5 use Doctrine\Tests\Mocks\MetadataDriverMock;
6 use Doctrine\Tests\Mocks\EntityManagerMock;
7 use Doctrine\Tests\Mocks\ConnectionMock;
8 use Doctrine\Tests\Mocks\DriverMock;
9 use Doctrine\ORM\Mapping\ClassMetadata;
10 use Doctrine\Common\EventManager;
11 use Doctrine\ORM\Mapping\ClassMetadataFactory;
13 require_once __DIR__ . '/../../TestInit.php';
15 class ClassMetadataFactoryTest extends \Doctrine\Tests\OrmTestCase
17 public function testGetMetadataForSingleClass()
19 $mockDriver = new MetadataDriverMock();
20 $entityManager = $this->_createEntityManager($mockDriver);
22 $conn = $entityManager->getConnection();
23 $mockPlatform = $conn->getDatabasePlatform();
24 $mockPlatform->setPrefersSequences(true);
25 $mockPlatform->setPrefersIdentityColumns(false);
27 $cm1 = $this->_createValidClassMetadata();
30 $cmf = new \Doctrine\ORM\Mapping\ClassMetadataFactory();
31 $cmf->setEntityManager($entityManager);
32 $cmf->setMetadataFor($cm1->name, $cm1);
35 $this->assertEquals(array(), $cm1->parentClasses);
36 $this->assertEquals(ClassMetadata::INHERITANCE_TYPE_NONE, $cm1->inheritanceType);
37 $this->assertTrue($cm1->hasField('name'));
38 $this->assertEquals(2, count($cm1->associationMappings));
39 $this->assertEquals(ClassMetadata::GENERATOR_TYPE_AUTO, $cm1->generatorType);
40 $this->assertEquals('group', $cm1->table['name']);
43 $cmMap1 = $cmf->getMetadataFor($cm1->name);
45 $this->assertSame($cm1, $cmMap1);
46 $this->assertEquals('group', $cmMap1->table['name']);
47 $this->assertTrue($cmMap1->table['quoted']);
48 $this->assertEquals(array(), $cmMap1->parentClasses);
49 $this->assertTrue($cmMap1->hasField('name'));
52 public function testGetMetadataFor_ReturnsLoadedCustomIdGenerator()
54 $cm1 = $this->_createValidClassMetadata();
55 $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_CUSTOM);
56 $cm1->customGeneratorDefinition = array(
57 "class" => "Doctrine\Tests\ORM\Mapping\CustomIdGenerator");
58 $cmf = $this->_createTestFactory();
59 $cmf->setMetadataForClass($cm1->name, $cm1);
61 $actual = $cmf->getMetadataFor($cm1->name);
63 $this->assertEquals(ClassMetadata::GENERATOR_TYPE_CUSTOM,
64 $actual->generatorType);
65 $this->assertInstanceOf("Doctrine\Tests\ORM\Mapping\CustomIdGenerator",
66 $actual->idGenerator);
69 public function testGetMetadataFor_ThrowsExceptionOnUnknownCustomGeneratorClass()
71 $cm1 = $this->_createValidClassMetadata();
72 $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_CUSTOM);
73 $cm1->customGeneratorDefinition = array("class" => "NotExistingGenerator");
74 $cmf = $this->_createTestFactory();
75 $cmf->setMetadataForClass($cm1->name, $cm1);
76 $this->setExpectedException("Doctrine\ORM\ORMException");
78 $actual = $cmf->getMetadataFor($cm1->name);
81 public function testGetMetadataFor_ThrowsExceptionOnMissingCustomGeneratorDefinition()
83 $cm1 = $this->_createValidClassMetadata();
84 $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_CUSTOM);
85 $cmf = $this->_createTestFactory();
86 $cmf->setMetadataForClass($cm1->name, $cm1);
87 $this->setExpectedException("Doctrine\ORM\ORMException");
89 $actual = $cmf->getMetadataFor($cm1->name);
92 public function testHasGetMetadata_NamespaceSeperatorIsNotNormalized()
94 require_once __DIR__."/../../Models/Global/GlobalNamespaceModel.php";
96 $metadataDriver = $this->createAnnotationDriver(array(__DIR__ . '/../../Models/Global/'));
98 $entityManager = $this->_createEntityManager($metadataDriver);
100 $mf = $entityManager->getMetadataFactory();
101 $m1 = $mf->getMetadataFor("DoctrineGlobal_Article");
102 $h1 = $mf->hasMetadataFor("DoctrineGlobal_Article");
103 $h2 = $mf->hasMetadataFor("\DoctrineGlobal_Article");
104 $m2 = $mf->getMetadataFor("\DoctrineGlobal_Article");
106 $this->assertNotSame($m1, $m2);
107 $this->assertFalse($h2);
108 $this->assertTrue($h1);
114 public function testIsTransient()
116 $cmf = new ClassMetadataFactory();
117 $driver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver');
118 $driver->expects($this->at(0))
119 ->method('isTransient')
120 ->with($this->equalTo('Doctrine\Tests\Models\CMS\CmsUser'))
121 ->will($this->returnValue(true));
122 $driver->expects($this->at(1))
123 ->method('isTransient')
124 ->with($this->equalTo('Doctrine\Tests\Models\CMS\CmsArticle'))
125 ->will($this->returnValue(false));
127 $em = $this->_createEntityManager($driver);
129 $this->assertTrue($em->getMetadataFactory()->isTransient('Doctrine\Tests\Models\CMS\CmsUser'));
130 $this->assertFalse($em->getMetadataFactory()->isTransient('Doctrine\Tests\Models\CMS\CmsArticle'));
136 public function testIsTransientEntityNamespace()
138 $cmf = new ClassMetadataFactory();
139 $driver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver');
140 $driver->expects($this->at(0))
141 ->method('isTransient')
142 ->with($this->equalTo('Doctrine\Tests\Models\CMS\CmsUser'))
143 ->will($this->returnValue(true));
144 $driver->expects($this->at(1))
145 ->method('isTransient')
146 ->with($this->equalTo('Doctrine\Tests\Models\CMS\CmsArticle'))
147 ->will($this->returnValue(false));
149 $em = $this->_createEntityManager($driver);
150 $em->getConfiguration()->addEntityNamespace('CMS', 'Doctrine\Tests\Models\CMS');
152 $this->assertTrue($em->getMetadataFactory()->isTransient('CMS:CmsUser'));
153 $this->assertFalse($em->getMetadataFactory()->isTransient('CMS:CmsArticle'));
156 public function testAddDefaultDiscriminatorMap()
158 $cmf = new ClassMetadataFactory();
159 $driver = $this->createAnnotationDriver(array(__DIR__ . '/../../Models/JoinedInheritanceType/'));
160 $em = $this->_createEntityManager($driver);
161 $cmf->setEntityManager($em);
163 $rootMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\JoinedInheritanceType\RootClass');
164 $childMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\JoinedInheritanceType\ChildClass');
165 $anotherChildMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\JoinedInheritanceType\AnotherChildClass');
166 $rootDiscriminatorMap = $rootMetadata->discriminatorMap;
167 $childDiscriminatorMap = $childMetadata->discriminatorMap;
168 $anotherChildDiscriminatorMap = $anotherChildMetadata->discriminatorMap;
170 $rootClass = 'Doctrine\Tests\Models\JoinedInheritanceType\RootClass';
171 $childClass = 'Doctrine\Tests\Models\JoinedInheritanceType\ChildClass';
172 $anotherChildClass = 'Doctrine\Tests\Models\JoinedInheritanceType\AnotherChildClass';
174 $rootClassKey = array_search($rootClass, $rootDiscriminatorMap);
175 $childClassKey = array_search($childClass, $rootDiscriminatorMap);
176 $anotherChildClassKey = array_search($anotherChildClass, $rootDiscriminatorMap);
178 $this->assertEquals('rootclass', $rootClassKey);
179 $this->assertEquals('childclass', $childClassKey);
180 $this->assertEquals('anotherchildclass', $anotherChildClassKey);
182 $this->assertEquals($childDiscriminatorMap, $rootDiscriminatorMap);
183 $this->assertEquals($anotherChildDiscriminatorMap, $rootDiscriminatorMap);
185 // ClassMetadataFactory::addDefaultDiscriminatorMap shouldn't be called again, because the
186 // discriminator map is already cached
187 $cmf = $this->getMock('Doctrine\ORM\Mapping\ClassMetadataFactory', array('addDefaultDiscriminatorMap'));
188 $cmf->setEntityManager($em);
189 $cmf->expects($this->never())
190 ->method('addDefaultDiscriminatorMap');
192 $rootMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\JoinedInheritanceType\RootClass');
195 protected function _createEntityManager($metadataDriver)
197 $driverMock = new DriverMock();
198 $config = new \Doctrine\ORM\Configuration();
199 $config->setProxyDir(__DIR__ . '/../../Proxies');
200 $config->setProxyNamespace('Doctrine\Tests\Proxies');
201 $eventManager = new EventManager();
202 $conn = new ConnectionMock(array(), $driverMock, $config, $eventManager);
203 $mockDriver = new MetadataDriverMock();
204 $config->setMetadataDriverImpl($metadataDriver);
206 return EntityManagerMock::create($conn, $config, $eventManager);
210 * @return ClassMetadataFactoryTestSubject
212 protected function _createTestFactory()
214 $mockDriver = new MetadataDriverMock();
215 $entityManager = $this->_createEntityManager($mockDriver);
216 $cmf = new ClassMetadataFactoryTestSubject();
217 $cmf->setEntityManager($entityManager);
222 * @param string $class
223 * @return ClassMetadata
225 protected function _createValidClassMetadata()
227 // Self-made metadata
228 $cm1 = new ClassMetadata('Doctrine\Tests\ORM\Mapping\TestEntity1');
229 $cm1->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
230 $cm1->setPrimaryTable(array('name' => '`group`'));
231 // Add a mapped field
232 $cm1->mapField(array('fieldName' => 'name', 'type' => 'varchar'));
233 // Add a mapped field
234 $cm1->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true));
235 // and a mapped association
236 $cm1->mapOneToOne(array('fieldName' => 'other', 'targetEntity' => 'TestEntity1', 'mappedBy' => 'this'));
237 // and an association on the owning side
238 $joinColumns = array(
239 array('name' => 'other_id', 'referencedColumnName' => 'id')
241 $cm1->mapOneToOne(array('fieldName' => 'association', 'targetEntity' => 'TestEntity1', 'joinColumns' => $joinColumns));
242 // and an id generator type
243 $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_AUTO);
250 public function testQuoteMetadata()
252 $cmf = new ClassMetadataFactory();
253 $driver = $this->createAnnotationDriver(array(__DIR__ . '/../../Models/Quote/'));
254 $em = $this->_createEntityManager($driver);
255 $cmf->setEntityManager($em);
258 $userMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\Quote\User');
259 $phoneMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\Quote\Phone');
260 $groupMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\Quote\Group');
261 $addressMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\Quote\Address');
264 // Phone Class Metadata
265 $this->assertTrue($phoneMetadata->fieldMappings['number']['quoted']);
266 $this->assertEquals('phone-number', $phoneMetadata->fieldMappings['number']['columnName']);
268 $user = $phoneMetadata->associationMappings['user'];
269 $this->assertTrue($user['joinColumns'][0]['quoted']);
270 $this->assertEquals('user-id', $user['joinColumns'][0]['name']);
271 $this->assertEquals('user-id', $user['joinColumns'][0]['referencedColumnName']);
275 // User Group Metadata
276 $this->assertTrue($groupMetadata->fieldMappings['id']['quoted']);
277 $this->assertTrue($groupMetadata->fieldMappings['name']['quoted']);
279 $this->assertEquals('user-id', $userMetadata->fieldMappings['id']['columnName']);
280 $this->assertEquals('user-name', $userMetadata->fieldMappings['name']['columnName']);
282 $user = $groupMetadata->associationMappings['parent'];
283 $this->assertTrue($user['joinColumns'][0]['quoted']);
284 $this->assertEquals('parent-id', $user['joinColumns'][0]['name']);
285 $this->assertEquals('group-id', $user['joinColumns'][0]['referencedColumnName']);
288 // Address Class Metadata
289 $this->assertTrue($addressMetadata->fieldMappings['id']['quoted']);
290 $this->assertTrue($addressMetadata->fieldMappings['zip']['quoted']);
292 $this->assertEquals('address-id', $addressMetadata->fieldMappings['id']['columnName']);
293 $this->assertEquals('address-zip', $addressMetadata->fieldMappings['zip']['columnName']);
295 $user = $addressMetadata->associationMappings['user'];
296 $this->assertTrue($user['joinColumns'][0]['quoted']);
297 $this->assertEquals('user-id', $user['joinColumns'][0]['name']);
298 $this->assertEquals('user-id', $user['joinColumns'][0]['referencedColumnName']);
302 // User Class Metadata
303 $this->assertTrue($userMetadata->fieldMappings['id']['quoted']);
304 $this->assertTrue($userMetadata->fieldMappings['name']['quoted']);
306 $this->assertEquals('user-id', $userMetadata->fieldMappings['id']['columnName']);
307 $this->assertEquals('user-name', $userMetadata->fieldMappings['name']['columnName']);
310 $address = $userMetadata->associationMappings['address'];
311 $this->assertTrue($address['joinColumns'][0]['quoted']);
312 $this->assertEquals('address-id', $address['joinColumns'][0]['name']);
313 $this->assertEquals('address-id', $address['joinColumns'][0]['referencedColumnName']);
315 $groups = $userMetadata->associationMappings['groups'];
316 $this->assertTrue($groups['joinTable']['quoted']);
317 $this->assertTrue($groups['joinTable']['joinColumns'][0]['quoted']);
318 $this->assertEquals('quote-users-groups', $groups['joinTable']['name']);
319 $this->assertEquals('user-id', $groups['joinTable']['joinColumns'][0]['name']);
320 $this->assertEquals('user-id', $groups['joinTable']['joinColumns'][0]['referencedColumnName']);
322 $this->assertTrue($groups['joinTable']['inverseJoinColumns'][0]['quoted']);
323 $this->assertEquals('group-id', $groups['joinTable']['inverseJoinColumns'][0]['name']);
324 $this->assertEquals('group-id', $groups['joinTable']['inverseJoinColumns'][0]['referencedColumnName']);
328 /* Test subject class with overriden factory method for mocking purposes */
329 class ClassMetadataFactoryTestSubject extends \Doctrine\ORM\Mapping\ClassMetadataFactory
331 private $mockMetadata = array();
332 private $requestedClasses = array();
335 protected function newClassMetadataInstance($className)
337 $this->requestedClasses[] = $className;
338 if ( ! isset($this->mockMetadata[$className])) {
339 throw new InvalidArgumentException("No mock metadata found for class $className.");
341 return $this->mockMetadata[$className];
344 public function setMetadataForClass($className, $metadata)
346 $this->mockMetadata[$className] = $metadata;
349 public function getRequestedClasses()
351 return $this->requestedClasses;
360 private $association;
363 class CustomIdGenerator extends \Doctrine\ORM\Id\AbstractIdGenerator
365 public function generate(\Doctrine\ORM\EntityManager $em, $entity)