Passed
Push — master ( bbc1ed...f4ef0a )
by Marco
62:30
created

Tests/ORM/Mapping/AnnotationDriverTest.php (1 issue)

Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\ORM\Mapping;
6
7
use Doctrine\Common\Annotations\AnnotationException;
8
use Doctrine\ORM\Annotation as ORM;
9
use Doctrine\ORM\Mapping\ClassMetadata;
10
use Doctrine\ORM\Mapping\ClassMetadataFactory;
11
use Doctrine\ORM\Mapping\MappingException;
12
use Doctrine\Tests\Models\CMS\CmsUser;
13
use Doctrine\Tests\Models\DDC1872\DDC1872ExampleEntityWithoutOverride;
14
use Doctrine\Tests\Models\DDC1872\DDC1872ExampleEntityWithOverride;
15
use Doctrine\Tests\Models\DirectoryTree\Directory;
16
use Doctrine\Tests\Models\DirectoryTree\File;
17
use Doctrine\Tests\Models\ECommerce\ECommerceCart;
18
19
class AnnotationDriverTest extends AbstractMappingDriverTest
20
{
21
    /**
22
     * @group DDC-268
23
     */
24
    public function testLoadMetadataForNonEntityThrowsException()
25
    {
26
        $cm = new ClassMetadata('stdClass', $this->metadataBuildingContext);
27
28
        $mappingDriver = $this->loadDriver();
29
30
        $this->expectException(MappingException::class);
31
32
        $mappingDriver->loadMetadataForClass('stdClass', $cm, $this->metadataBuildingContext);
33
    }
34
35
    /**
36
     * @expectedException \Doctrine\ORM\Cache\CacheException
37
     * @expectedExceptionMessage Entity association field "Doctrine\Tests\ORM\Mapping\AnnotationSLC#foo" not configured as part of the second-level cache.
38
     */
39
    public function testFailingSecondLevelCacheAssociation()
40
    {
41
        $mappingDriver = $this->loadDriver();
42
43
        $class = new ClassMetadata(AnnotationSLC::class, $this->metadataBuildingContext);
44
        $mappingDriver->loadMetadataForClass(AnnotationSLC::class, $class, $this->metadataBuildingContext);
45
    }
46
47
    /**
48
     * @group DDC-268
49
     */
50
    public function testColumnWithMissingTypeDefaultsToString()
51
    {
52
        $cm = new ClassMetadata(ColumnWithoutType::class, $this->metadataBuildingContext);
53
54
        $mappingDriver = $this->loadDriver();
55
56
        $mappingDriver->loadMetadataForClass(ColumnWithoutType::class, $cm, $this->metadataBuildingContext);
57
58
        self::assertNotNull($cm->getProperty('id'));
59
60
        $idProperty = $cm->getProperty('id');
61
62
        self::assertEquals('string', $idProperty->getTypeName());
63
    }
64
65
    /**
66
     * @group DDC-318
67
     */
68
    public function testGetAllClassNamesIsIdempotent()
69
    {
70
        $annotationDriver = $this->loadDriverForCMSModels();
71
        $original = $annotationDriver->getAllClassNames();
72
73
        $annotationDriver = $this->loadDriverForCMSModels();
74
        $afterTestReset = $annotationDriver->getAllClassNames();
75
76
        self::assertEquals($original, $afterTestReset);
77
    }
78
79
    /**
80
     * @group DDC-318
81
     */
82
    public function testGetAllClassNamesIsIdempotentEvenWithDifferentDriverInstances()
83
    {
84
        $annotationDriver = $this->loadDriverForCMSModels();
85
        $original = $annotationDriver->getAllClassNames();
86
87
        $annotationDriver = $this->loadDriverForCMSModels();
88
        $afterTestReset = $annotationDriver->getAllClassNames();
89
90
        self::assertEquals($original, $afterTestReset);
91
    }
92
93
    /**
94
     * @group DDC-318
95
     */
96
    public function testGetAllClassNamesReturnsAlreadyLoadedClassesIfAppropriate()
97
    {
98
        $this->ensureIsLoaded(CmsUser::class);
99
100
        $annotationDriver = $this->loadDriverForCMSModels();
101
        $classes = $annotationDriver->getAllClassNames();
102
103
        self::assertContains(CmsUser::class, $classes);
104
    }
105
106
    /**
107
     * @group DDC-318
108
     */
109
    public function testGetClassNamesReturnsOnlyTheAppropriateClasses()
110
    {
111
        $this->ensureIsLoaded(ECommerceCart::class);
112
113
        $annotationDriver = $this->loadDriverForCMSModels();
114
        $classes = $annotationDriver->getAllClassNames();
115
116
        self::assertNotContains(ECommerceCart::class, $classes);
117
    }
118
119
    protected function loadDriverForCMSModels()
120
    {
121
        $annotationDriver = $this->loadDriver();
122
        $annotationDriver->addPaths([__DIR__ . '/../../Models/CMS/']);
123
        return $annotationDriver;
124
    }
125
126
    protected function loadDriver()
127
    {
128
        return $this->createAnnotationDriver();
129
    }
130
131
    protected function ensureIsLoaded($entityClassName)
132
    {
133
        new $entityClassName;
134
    }
135
136
    /**
137
     * @group DDC-671
138
     *
139
     * Entities for this test are in AbstractMappingDriverTest
140
     */
141
    public function testJoinTablesWithMappedSuperclassForAnnotationDriver()
142
    {
143
        $annotationDriver = $this->loadDriver();
144
        $annotationDriver->addPaths([__DIR__ . '/../../Models/DirectoryTree/']);
145
146
        $em = $this->getTestEntityManager();
147
        $em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
148
        $factory = new ClassMetadataFactory();
149
        $factory->setEntityManager($em);
150
151
        $classPage = $factory->getMetadataFor(File::class);
152
        self::assertArrayHasKey('parentDirectory', iterator_to_array($classPage->getDeclaredPropertiesIterator()));
153
        self::assertEquals(File::class, $classPage->getProperty('parentDirectory')->getSourceEntity());
154
155
        $classDirectory = $factory->getMetadataFor(Directory::class);
156
        self::assertArrayHasKey('parentDirectory', iterator_to_array($classDirectory->getDeclaredPropertiesIterator()));
157
        self::assertEquals(Directory::class, $classDirectory->getProperty('parentDirectory')->getSourceEntity());
158
    }
159
160
    /**
161
     * @group DDC-945
162
     */
163
    public function testInvalidMappedSuperClassWithManyToManyAssociation()
164
    {
165
        $annotationDriver = $this->loadDriver();
166
167
        $em = $this->getTestEntityManager();
168
        $em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
169
        $factory = new ClassMetadataFactory();
170
        $factory->setEntityManager($em);
171
172
        $this->expectException(MappingException::class);
173
        $this->expectExceptionMessage(
174
            "It is illegal to put an inverse side one-to-many or many-to-many association on " .
175
            "mapped superclass 'Doctrine\Tests\ORM\Mapping\InvalidMappedSuperClass#users'"
176
        );
177
178
        $usingInvalidMsc = $factory->getMetadataFor(UsingInvalidMappedSuperClass::class);
0 ignored issues
show
The assignment to $usingInvalidMsc is dead and can be removed.
Loading history...
179
    }
180
181
    /**
182
     * @group DDC-1034
183
     */
184
    public function testInheritanceSkipsParentLifecycleCallbacks()
185
    {
186
        $annotationDriver = $this->loadDriver();
187
188
        $em = $this->getTestEntityManager();
189
        $em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
190
        $factory = new ClassMetadataFactory();
191
        $factory->setEntityManager($em);
192
193
        $cm = $factory->getMetadataFor(AnnotationChild::class);
194
        self::assertEquals(["postLoad" => ["postLoad"], "preUpdate" => ["preUpdate"]], $cm->lifecycleCallbacks);
195
196
        $cm = $factory->getMetadataFor(AnnotationParent::class);
197
        self::assertEquals(["postLoad" => ["postLoad"], "preUpdate" => ["preUpdate"]], $cm->lifecycleCallbacks);
198
    }
199
200
    /**
201
     * @group DDC-1156
202
     */
203
    public function testMappedSuperclassInMiddleOfInheritanceHierarchy()
204
    {
205
        $annotationDriver = $this->loadDriver();
206
207
        $em = $this->getTestEntityManager();
208
        $em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
209
210
        $factory = new ClassMetadataFactory();
211
        $factory->setEntityManager($em);
212
213
        self::assertInstanceOf(ClassMetadata::class, $factory->getMetadataFor(ChildEntity::class));
214
    }
215
216
    public function testInvalidFetchOptionThrowsException()
217
    {
218
        $annotationDriver = $this->loadDriver();
219
220
        $em = $this->getTestEntityManager();
221
        $em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
222
        $factory = new ClassMetadataFactory();
223
        $factory->setEntityManager($em);
224
225
        $this->expectException(AnnotationException::class);
226
        $this->expectExceptionMessage('[Enum Error] Attribute "fetch" of @Doctrine\ORM\Annotation\OneToMany declared on property Doctrine\Tests\ORM\Mapping\InvalidFetchOption::$collection accept only [LAZY, EAGER, EXTRA_LAZY], but got eager.');
227
228
        $factory->getMetadataFor(InvalidFetchOption::class);
229
    }
230
231
    public function testAttributeOverridesMappingWithTrait()
232
    {
233
        $factory = $this->createClassMetadataFactory();
234
235
        $metadataWithoutOverride = $factory->getMetadataFor(DDC1872ExampleEntityWithoutOverride::class);
236
        $metadataWithOverride = $factory->getMetadataFor(DDC1872ExampleEntityWithOverride::class);
237
238
        self::assertNotNull($metadataWithoutOverride->getProperty('foo'));
239
        self::assertNotNull($metadataWithOverride->getProperty('foo'));
240
241
        $fooPropertyWithoutOverride = $metadataWithoutOverride->getProperty('foo');
242
        $fooPropertyWithOverride    = $metadataWithOverride->getProperty('foo');
243
244
        self::assertEquals('trait_foo', $fooPropertyWithoutOverride->getColumnName());
245
        self::assertEquals('foo_overridden', $fooPropertyWithOverride->getColumnName());
246
247
        $barPropertyWithoutOverride = $metadataWithoutOverride->getProperty('bar');
248
        $barPropertyWithOverride    = $metadataWithOverride->getProperty('bar');
249
250
        $barPropertyWithoutOverrideFirstJoinColumn = $barPropertyWithoutOverride->getJoinColumns()[0];
251
        $barPropertyWithOverrideFirstJoinColumn    = $barPropertyWithOverride->getJoinColumns()[0];
252
253
        self::assertEquals('example_trait_bar_id', $barPropertyWithoutOverrideFirstJoinColumn->getColumnName());
254
        self::assertEquals('example_entity_overridden_bar_id', $barPropertyWithOverrideFirstJoinColumn->getColumnName());
255
    }
256
}
257
258
/**
259
 * @ORM\MappedSuperclass
260
 */
261
class InvalidMappedSuperClass
262
{
263
    /**
264
     * @ORM\ManyToMany(targetEntity=CmsUser::class, mappedBy="invalid")
265
     */
266
    private $users;
267
}
268
269
/**
270
 * @ORM\Entity
271
 */
272
class UsingInvalidMappedSuperClass extends InvalidMappedSuperClass
273
{
274
    /**
275
     * @ORM\Id @ORM\Column(type="integer") @ORM\GeneratedValue
276
     */
277
    private $id;
278
}
279
280
/**
281
 * @ORM\Entity
282
 */
283
class ColumnWithoutType
284
{
285
    /** @ORM\Id @ORM\Column */
286
    public $id;
287
}
288
289
/**
290
 * @ORM\Entity
291
 * @ORM\InheritanceType("JOINED")
292
 * @ORM\DiscriminatorMap({"parent" = AnnotationParent::class, "child" = AnnotationChild::class})
293
 * @ORM\HasLifecycleCallbacks
294
 */
295
class AnnotationParent
296
{
297
    /**
298
     * @ORM\Id @ORM\Column(type="integer") @ORM\GeneratedValue
299
     */
300
    private $id;
301
302
    /**
303
     * @ORM\PostLoad
304
     */
305
    public function postLoad()
306
    {
307
    }
308
309
    /**
310
     * @ORM\PreUpdate
311
     */
312
    public function preUpdate()
313
    {
314
    }
315
}
316
317
/**
318
 * @ORM\Entity
319
 * @ORM\HasLifecycleCallbacks
320
 */
321
class AnnotationChild extends AnnotationParent
322
{
323
}
324
325
/**
326
 * @ORM\Entity
327
 * @ORM\InheritanceType("SINGLE_TABLE")
328
 * @ORM\DiscriminatorMap({"s"=SuperEntity::class, "c"=ChildEntity::class})
329
 */
330
class SuperEntity
331
{
332
    /** @ORM\Id @ORM\Column(type="string") */
333
    private $id;
334
}
335
336
/**
337
 * @ORM\MappedSuperclass
338
 */
339
class MiddleMappedSuperclass extends SuperEntity
340
{
341
    /** @ORM\Column(type="string") */
342
    private $name;
343
}
344
345
/**
346
 * @ORM\Entity
347
 */
348
class ChildEntity extends MiddleMappedSuperclass
349
{
350
    /**
351
     * @ORM\Column(type="string")
352
     */
353
    private $text;
354
}
355
356
/**
357
 * @ORM\Entity
358
 */
359
class InvalidFetchOption
360
{
361
    /**
362
     * @ORM\OneToMany(targetEntity=CmsUser::class, fetch="eager")
363
     */
364
    private $collection;
365
}
366
367
/**
368
 * @ORM\Entity
369
 * @ORM\Cache
370
 */
371
class AnnotationSLC
372
{
373
    /**
374
     * @ORM\Id
375
     * @ORM\ManyToOne(targetEntity=AnnotationSLCFoo::class)
376
     */
377
    public $foo;
378
}
379
/**
380
 * @ORM\Entity
381
 */
382
class AnnotationSLCFoo
383
{
384
    /**
385
     * @ORM\Column(type="string")
386
     */
387
    public $id;
388
}
389