Completed
Pull Request — master (#6151)
by Andy
09:42
created

testNestedEmbeddableAttributeOverrides()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 10
nc 1
nop 0
1
<?php
2
3
namespace Doctrine\Tests\ORM\Mapping;
4
5
use Doctrine\Common\Annotations\AnnotationException;
6
use Doctrine\Common\Annotations\AnnotationReader;
7
use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService;
8
use Doctrine\ORM\Mapping\ClassMetadata;
9
use Doctrine\ORM\Mapping\ClassMetadataFactory;
10
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
11
use Doctrine\ORM\Mapping\MappingException;
12
13
class AnnotationDriverTest extends AbstractMappingDriverTest
14
{
15
    /**
16
     * @group DDC-268
17
     */
18
    public function testLoadMetadataForNonEntityThrowsException()
19
    {
20
        $cm = new ClassMetadata('stdClass');
21
        $cm->initializeReflection(new RuntimeReflectionService());
22
        $reader = new AnnotationReader();
23
        $annotationDriver = new AnnotationDriver($reader);
24
25
        $this->expectException(\Doctrine\ORM\Mapping\MappingException::class);
26
        $annotationDriver->loadMetadataForClass('stdClass', $cm);
27
    }
28
29
    /**
30
     * @expectedException Doctrine\ORM\Cache\CacheException
31
     * @expectedExceptionMessage Entity association field "Doctrine\Tests\ORM\Mapping\AnnotationSLC#foo" not configured as part of the second-level cache.
32
     */
33
    public function testFailingSecondLevelCacheAssociation()
34
    {
35
        $className = 'Doctrine\Tests\ORM\Mapping\AnnotationSLC';
36
        $mappingDriver = $this->_loadDriver();
37
38
        $class = new ClassMetadata($className);
39
        $mappingDriver->loadMetadataForClass($className, $class);
40
    }
41
42
    /**
43
     * @group DDC-268
44
     */
45
    public function testColumnWithMissingTypeDefaultsToString()
46
    {
47
        $cm = new ClassMetadata('Doctrine\Tests\ORM\Mapping\ColumnWithoutType');
48
        $cm->initializeReflection(new RuntimeReflectionService());
49
        $annotationDriver = $this->_loadDriver();
50
51
        $annotationDriver->loadMetadataForClass('Doctrine\Tests\ORM\Mapping\InvalidColumn', $cm);
52
        $this->assertEquals('string', $cm->fieldMappings['id']['type']);
53
    }
54
55
    /**
56
     * @group DDC-318
57
     */
58
    public function testGetAllClassNamesIsIdempotent()
59
    {
60
        $annotationDriver = $this->_loadDriverForCMSModels();
61
        $original = $annotationDriver->getAllClassNames();
62
63
        $annotationDriver = $this->_loadDriverForCMSModels();
64
        $afterTestReset = $annotationDriver->getAllClassNames();
65
66
        $this->assertEquals($original, $afterTestReset);
67
    }
68
69
    /**
70
     * @group DDC-318
71
     */
72
    public function testGetAllClassNamesIsIdempotentEvenWithDifferentDriverInstances()
73
    {
74
        $annotationDriver = $this->_loadDriverForCMSModels();
75
        $original = $annotationDriver->getAllClassNames();
76
77
        $annotationDriver = $this->_loadDriverForCMSModels();
78
        $afterTestReset = $annotationDriver->getAllClassNames();
79
80
        $this->assertEquals($original, $afterTestReset);
81
    }
82
83
    /**
84
     * @group DDC-318
85
     */
86
    public function testGetAllClassNamesReturnsAlreadyLoadedClassesIfAppropriate()
87
    {
88
        $rightClassName = 'Doctrine\Tests\Models\CMS\CmsUser';
89
        $this->_ensureIsLoaded($rightClassName);
90
91
        $annotationDriver = $this->_loadDriverForCMSModels();
92
        $classes = $annotationDriver->getAllClassNames();
93
94
        $this->assertContains($rightClassName, $classes);
95
    }
96
97
    /**
98
     * @group DDC-318
99
     */
100
    public function testGetClassNamesReturnsOnlyTheAppropriateClasses()
101
    {
102
        $extraneousClassName = 'Doctrine\Tests\Models\ECommerce\ECommerceCart';
103
        $this->_ensureIsLoaded($extraneousClassName);
104
105
        $annotationDriver = $this->_loadDriverForCMSModels();
106
        $classes = $annotationDriver->getAllClassNames();
107
108
        $this->assertNotContains($extraneousClassName, $classes);
109
    }
110
111
    protected function _loadDriverForCMSModels()
112
    {
113
        $annotationDriver = $this->_loadDriver();
114
        $annotationDriver->addPaths(array(__DIR__ . '/../../Models/CMS/'));
115
        return $annotationDriver;
116
    }
117
118
    protected function _loadDriver()
119
    {
120
        return $this->createAnnotationDriver();
121
    }
122
123
    protected function _ensureIsLoaded($entityClassName)
124
    {
125
        new $entityClassName;
126
    }
127
128
    /**
129
     * @group DDC-671
130
     *
131
     * Entities for this test are in AbstractMappingDriverTest
132
     */
133
    public function testJoinTablesWithMappedSuperclassForAnnotationDriver()
134
    {
135
        $annotationDriver = $this->_loadDriver();
136
        $annotationDriver->addPaths(array(__DIR__ . '/../../Models/DirectoryTree/'));
137
138
        $em = $this->_getTestEntityManager();
139
        $em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
140
        $factory = new ClassMetadataFactory();
141
        $factory->setEntityManager($em);
142
143
        $classPage = $factory->getMetadataFor('Doctrine\Tests\Models\DirectoryTree\File');
144
        $this->assertEquals('Doctrine\Tests\Models\DirectoryTree\File', $classPage->associationMappings['parentDirectory']['sourceEntity']);
145
146
        $classDirectory = $factory->getMetadataFor('Doctrine\Tests\Models\DirectoryTree\Directory');
147
        $this->assertEquals('Doctrine\Tests\Models\DirectoryTree\Directory', $classDirectory->associationMappings['parentDirectory']['sourceEntity']);
148
    }
149
150
    /**
151
     * @group DDC-945
152
     */
153
    public function testInvalidMappedSuperClassWithManyToManyAssociation()
154
    {
155
        $annotationDriver = $this->_loadDriver();
156
157
        $em = $this->_getTestEntityManager();
158
        $em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
159
        $factory = new ClassMetadataFactory();
160
        $factory->setEntityManager($em);
161
162
        $this->expectException(MappingException::class);
163
        $this->expectExceptionMessage(
164
            "It is illegal to put an inverse side one-to-many or many-to-many association on " .
165
            "mapped superclass 'Doctrine\Tests\ORM\Mapping\InvalidMappedSuperClass#users'"
166
        );
167
168
        $usingInvalidMsc = $factory->getMetadataFor('Doctrine\Tests\ORM\Mapping\UsingInvalidMappedSuperClass');
169
    }
170
171
    /**
172
     * @group DDC-1050
173
     */
174
    public function testInvalidMappedSuperClassWithInheritanceInformation()
175
    {
176
        $annotationDriver = $this->_loadDriver();
177
178
        $em = $this->_getTestEntityManager();
179
        $em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
180
        $factory = new ClassMetadataFactory();
181
        $factory->setEntityManager($em);
182
183
        $this->expectException(MappingException::class);
184
        $this->expectExceptionMessage(
185
            "It is not supported to define inheritance information on a mapped " .
186
            "superclass 'Doctrine\Tests\ORM\Mapping\MappedSuperClassInheritence'."
187
        );
188
189
        $usingInvalidMsc = $factory->getMetadataFor('Doctrine\Tests\ORM\Mapping\MappedSuperClassInheritence');
190
    }
191
192
    /**
193
     * @group DDC-1034
194
     */
195
    public function testInheritanceSkipsParentLifecycleCallbacks()
196
    {
197
        $annotationDriver = $this->_loadDriver();
198
199
        $em = $this->_getTestEntityManager();
200
        $em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
201
        $factory = new ClassMetadataFactory();
202
        $factory->setEntityManager($em);
203
204
        $cm = $factory->getMetadataFor('Doctrine\Tests\ORM\Mapping\AnnotationChild');
205
        $this->assertEquals(array("postLoad" => array("postLoad"), "preUpdate" => array("preUpdate")), $cm->lifecycleCallbacks);
206
207
        $cm = $factory->getMetadataFor('Doctrine\Tests\ORM\Mapping\AnnotationParent');
208
        $this->assertEquals(array("postLoad" => array("postLoad"), "preUpdate" => array("preUpdate")), $cm->lifecycleCallbacks);
209
    }
210
211
    /**
212
     * @group DDC-1156
213
     */
214
    public function testMappedSuperclassInMiddleOfInheritanceHierarchy()
215
    {
216
        $annotationDriver = $this->_loadDriver();
217
218
        $em = $this->_getTestEntityManager();
219
        $em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
220
        $factory = new ClassMetadataFactory();
221
        $factory->setEntityManager($em);
222
223
        $cm = $factory->getMetadataFor('Doctrine\Tests\ORM\Mapping\ChildEntity');
224
    }
225
226
    public function testInvalidFetchOptionThrowsException()
227
    {
228
        $annotationDriver = $this->_loadDriver();
229
230
        $em = $this->_getTestEntityManager();
231
        $em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
232
        $factory = new ClassMetadataFactory();
233
        $factory->setEntityManager($em);
234
235
        $this->expectException(AnnotationException::class);
236
        $this->expectExceptionMessage('[Enum Error] Attribute "fetch" of @Doctrine\ORM\Mapping\OneToMany declared on property Doctrine\Tests\ORM\Mapping\InvalidFetchOption::$collection accept only [LAZY, EAGER, EXTRA_LAZY], but got eager.');
237
238
        $factory->getMetadataFor('Doctrine\Tests\ORM\Mapping\InvalidFetchOption');
239
    }
240
241
    public function testAttributeOverridesMappingWithTrait()
242
    {
243
        $factory       = $this->createClassMetadataFactory();
244
245
        $metadataWithoutOverride = $factory->getMetadataFor('Doctrine\Tests\Models\DDC1872\DDC1872ExampleEntityWithoutOverride');
246
        $metadataWithOverride = $factory->getMetadataFor('Doctrine\Tests\Models\DDC1872\DDC1872ExampleEntityWithOverride');
247
248
        $this->assertEquals('trait_foo', $metadataWithoutOverride->fieldMappings['foo']['columnName']);
249
        $this->assertEquals('foo_overridden', $metadataWithOverride->fieldMappings['foo']['columnName']);
250
        $this->assertArrayHasKey('example_trait_bar_id', $metadataWithoutOverride->associationMappings['bar']['joinColumnFieldNames']);
251
        $this->assertArrayHasKey('example_entity_overridden_bar_id', $metadataWithOverride->associationMappings['bar']['joinColumnFieldNames']);
252
    }
253
254
    public function testEmbeddableAttributeOverride()
255
    {
256
        $metadata = $this->createClassMetadata('Doctrine\Tests\Models\Overrides\EntityWithEmbeddableOverriddenAttribute');
257
258
        $this->assertArrayHasKey('valueObject', $metadata->embeddedClasses);
259
        $this->assertArrayHasKey('attributeOverrides', $metadata->embeddedClasses['valueObject']);
260
        $this->assertNotNull($metadata->embeddedClasses['valueObject']['attributeOverrides']);
261
        $this->assertArrayHasKey('value', $metadata->embeddedClasses['valueObject']['attributeOverrides']);
262
        $this->assertEquals($metadata->embeddedClasses['valueObject']['attributeOverrides']['value']['columnName'], 'value_override');
263
    }
264
265
    public function testEmbeddableAttributeRemoval()
266
    {
267
        $metadata = $this->createClassMetadata('Doctrine\Tests\Models\Overrides\EntityWithEmbeddableRemovedAttribute');
268
269
        $this->assertArrayHasKey('valueObject', $metadata->embeddedClasses);
270
        $this->assertArrayHasKey('attributeOverrides', $metadata->embeddedClasses['valueObject']);
271
        $this->assertNotNull($metadata->embeddedClasses['valueObject']['attributeOverrides']);
272
        $this->assertArrayHasKey('value', $metadata->embeddedClasses['valueObject']['attributeOverrides']);
273
        $this->assertNull($metadata->embeddedClasses['valueObject']['attributeOverrides']['value']);
274
    }
275
276
    public function testEmbeddableAttributeOverrides()
277
    {
278
        $metadata = $this->createClassMetadata('Doctrine\Tests\Models\Overrides\EntityWithEmbeddableOverriddenAndRemovedAttributes');
279
280
        $this->assertArrayHasKey('valueObject', $metadata->embeddedClasses);
281
        $this->assertArrayHasKey('attributeOverrides', $metadata->embeddedClasses['valueObject']);
282
        $this->assertNotNull($metadata->embeddedClasses['valueObject']['attributeOverrides']);
283
        $this->assertArrayHasKey('value', $metadata->embeddedClasses['valueObject']['attributeOverrides']);
284
        $this->assertTrue(is_array($metadata->embeddedClasses['valueObject']['attributeOverrides']['value']));
285
        $this->assertEquals($metadata->embeddedClasses['valueObject']['attributeOverrides']['value']['columnName'], 'value_override');
286
        $this->assertArrayHasKey('count', $metadata->embeddedClasses['valueObject']['attributeOverrides']);
287
        $this->assertNull($metadata->embeddedClasses['valueObject']['attributeOverrides']['count']);
288
    }
289
290
    public function testNestedEmbeddableAttributeOverrides()
291
    {
292
        $metadata = $this->createClassMetadata('Doctrine\Tests\Models\Overrides\EntityWithNestedEmbeddableOverriddenAndRemovedAttributes');
293
294
        $this->assertArrayHasKey('nestedValueObject', $metadata->embeddedClasses);
295
        $this->assertArrayHasKey('attributeOverrides', $metadata->embeddedClasses['nestedValueObject']);
296
        $this->assertNotNull($metadata->embeddedClasses['nestedValueObject']['attributeOverrides']);
297
        $this->assertArrayHasKey('nested.value', $metadata->embeddedClasses['nestedValueObject']['attributeOverrides']);
298
        $this->assertTrue(is_array($metadata->embeddedClasses['nestedValueObject']['attributeOverrides']['nested.value']));
299
        $this->assertEquals($metadata->embeddedClasses['nestedValueObject']['attributeOverrides']['nested.value']['columnName'], 'value_override');
300
        $this->assertArrayHasKey('nested.count', $metadata->embeddedClasses['nestedValueObject']['attributeOverrides']);
301
        $this->assertNull($metadata->embeddedClasses['nestedValueObject']['attributeOverrides']['nested.count']);
302
    }
303
}
304
305
/**
306
 * @Entity
307
 */
308
class ColumnWithoutType
309
{
310
    /** @Id @Column */
311
    public $id;
312
}
313
314
/**
315
 * @MappedSuperclass
316
 */
317
class InvalidMappedSuperClass
318
{
319
    /**
320
     * @ManyToMany(targetEntity="Doctrine\Tests\Models\CMS\CmsUser", mappedBy="invalid")
321
     */
322
    private $users;
323
}
324
325
/**
326
 * @Entity
327
 */
328
class UsingInvalidMappedSuperClass extends InvalidMappedSuperClass
329
{
330
    /**
331
     * @Id @Column(type="integer") @GeneratedValue
332
     */
333
    private $id;
334
}
335
336
/**
337
 * @MappedSuperclass
338
 * @InheritanceType("JOINED")
339
 * @DiscriminatorMap({"test" = "ColumnWithoutType"})
340
 */
341
class MappedSuperClassInheritence
342
{
343
344
}
345
346
/**
347
 * @Entity
348
 * @InheritanceType("JOINED")
349
 * @DiscriminatorMap({"parent" = "AnnotationParent", "child" = "AnnotationChild"})
350
 * @HasLifecycleCallbacks
351
 */
352
class AnnotationParent
353
{
354
    /**
355
     * @Id @Column(type="integer") @GeneratedValue
356
     */
357
    private $id;
358
359
    /**
360
     * @PostLoad
361
     */
362
    public function postLoad()
363
    {
364
365
    }
366
367
    /**
368
     * @PreUpdate
369
     */
370
    public function preUpdate()
371
    {
372
373
    }
374
}
375
376
/**
377
 * @Entity
378
 * @HasLifecycleCallbacks
379
 */
380
class AnnotationChild extends AnnotationParent
381
{
382
383
}
384
385
/**
386
 * @Entity
387
 * @InheritanceType("SINGLE_TABLE")
388
 * @DiscriminatorMap({"s"="SuperEntity", "c"="ChildEntity"})
389
 */
390
class SuperEntity
391
{
392
    /** @Id @Column(type="string") */
393
    private $id;
394
}
395
396
/**
397
 * @MappedSuperclass
398
 */
399
class MiddleMappedSuperclass extends SuperEntity
400
{
401
    /** @Column(type="string") */
402
    private $name;
403
}
404
405
/**
406
 * @Entity
407
 */
408
class ChildEntity extends MiddleMappedSuperclass
409
{
410
    /**
411
     * @Column(type="string")
412
     */
413
    private $text;
414
}
415
416
/**
417
 * @Entity
418
 */
419
class InvalidFetchOption
420
{
421
    /**
422
     * @OneToMany(targetEntity="Doctrine\Tests\Models\CMS\CmsUser", fetch="eager")
423
     */
424
    private $collection;
425
}
426
427
/**
428
 * @Entity
429
 * @Cache
430
 */
431
class AnnotationSLC
432
{
433
    /**
434
     * @Id
435
     * @ManyToOne(targetEntity="AnnotationSLCFoo")
436
     */
437
    public $foo;
438
}
439
/**
440
 * @Entity
441
 */
442
class AnnotationSLCFoo
443
{
444
    /**
445
     * @Column(type="string")
446
     */
447
    public $id;
448
}
449