Failed Conditions
Push — master ( b210c1...4c8949 )
by Marco
12:15
created

SchemaToolTest::testDerivedCompositeKey()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 41
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 25
nc 2
nop 0
dl 0
loc 41
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace Doctrine\Tests\ORM\Tools;
4
5
use Doctrine\ORM\Mapping\ClassMetadata;
6
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
7
use Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs;
8
use Doctrine\ORM\Tools\SchemaTool;
9
use Doctrine\ORM\Tools\ToolEvents;
10
use Doctrine\Tests\Models\CMS\CmsAddress;
11
use Doctrine\Tests\Models\CMS\CmsArticle;
12
use Doctrine\Tests\Models\CMS\CmsComment;
13
use Doctrine\Tests\Models\CMS\CmsEmployee;
14
use Doctrine\Tests\Models\CMS\CmsGroup;
15
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
16
use Doctrine\Tests\Models\CMS\CmsUser;
17
use Doctrine\Tests\Models\CompositeKeyInheritance\JoinedDerivedChildClass;
18
use Doctrine\Tests\Models\CompositeKeyInheritance\JoinedDerivedIdentityClass;
19
use Doctrine\Tests\Models\CompositeKeyInheritance\JoinedDerivedRootClass;
20
use Doctrine\Tests\Models\Forum\ForumAvatar;
21
use Doctrine\Tests\Models\Forum\ForumUser;
22
use Doctrine\Tests\Models\NullDefault\NullDefaultColumn;
23
use Doctrine\Tests\OrmTestCase;
24
25
class SchemaToolTest extends OrmTestCase
26
{
27
    public function testAddUniqueIndexForUniqueFieldAnnotation()
28
    {
29
        $em = $this->_getTestEntityManager();
30
        $schemaTool = new SchemaTool($em);
31
32
        $classes = [
33
            $em->getClassMetadata(CmsAddress::class),
34
            $em->getClassMetadata(CmsArticle::class),
35
            $em->getClassMetadata(CmsComment::class),
36
            $em->getClassMetadata(CmsEmployee::class),
37
            $em->getClassMetadata(CmsGroup::class),
38
            $em->getClassMetadata(CmsPhonenumber::class),
39
            $em->getClassMetadata(CmsUser::class),
40
        ];
41
42
        $schema = $schemaTool->getSchemaFromMetadata($classes);
43
44
        $this->assertTrue($schema->hasTable('cms_users'), "Table cms_users should exist.");
45
        $this->assertTrue($schema->getTable('cms_users')->columnsAreIndexed(['username']), "username column should be indexed.");
46
    }
47
48
    public function testAnnotationOptionsAttribute()
49
    {
50
        $em = $this->_getTestEntityManager();
51
        $schemaTool = new SchemaTool($em);
52
53
        $classes = [
54
            $em->getClassMetadata(TestEntityWithAnnotationOptionsAttribute::class),
55
        ];
56
57
        $schema = $schemaTool->getSchemaFromMetadata($classes);
58
59
        $expected = ['foo' => 'bar', 'baz' => ['key' => 'val']];
60
61
        $this->assertEquals($expected, $schema->getTable('TestEntityWithAnnotationOptionsAttribute')->getOptions(), "options annotation are passed to the tables options");
62
        $this->assertEquals($expected, $schema->getTable('TestEntityWithAnnotationOptionsAttribute')->getColumn('test')->getCustomSchemaOptions(), "options annotation are passed to the columns customSchemaOptions");
63
    }
64
65
    /**
66
     * @group DDC-200
67
     */
68
    public function testPassColumnDefinitionToJoinColumn()
69
    {
70
        $customColumnDef = "MEDIUMINT(6) UNSIGNED NOT NULL";
71
72
        $em = $this->_getTestEntityManager();
73
        $schemaTool = new SchemaTool($em);
74
75
        $avatar = $em->getClassMetadata(ForumAvatar::class);
76
        $avatar->fieldMappings['id']['columnDefinition'] = $customColumnDef;
77
        $user = $em->getClassMetadata(ForumUser::class);
78
79
        $classes = [$avatar, $user];
80
81
        $schema = $schemaTool->getSchemaFromMetadata($classes);
82
83
        $this->assertTrue($schema->hasTable('forum_users'));
84
        $table = $schema->getTable("forum_users");
85
        $this->assertTrue($table->hasColumn('avatar_id'));
86
        $this->assertEquals($customColumnDef, $table->getColumn('avatar_id')->getColumnDefinition());
87
    }
88
89
    /**
90
     * @group DDC-283
91
     */
92
    public function testPostGenerateEvents()
93
    {
94
        $listener = new GenerateSchemaEventListener();
95
96
        $em = $this->_getTestEntityManager();
97
        $em->getEventManager()->addEventListener(
98
            [ToolEvents::postGenerateSchemaTable, ToolEvents::postGenerateSchema], $listener
99
        );
100
        $schemaTool = new SchemaTool($em);
101
102
        $classes = [
103
            $em->getClassMetadata(CmsAddress::class),
104
            $em->getClassMetadata(CmsArticle::class),
105
            $em->getClassMetadata(CmsComment::class),
106
            $em->getClassMetadata(CmsEmployee::class),
107
            $em->getClassMetadata(CmsGroup::class),
108
            $em->getClassMetadata(CmsPhonenumber::class),
109
            $em->getClassMetadata(CmsUser::class),
110
        ];
111
112
        $schema = $schemaTool->getSchemaFromMetadata($classes);
0 ignored issues
show
Unused Code introduced by
The assignment to $schema is dead and can be removed.
Loading history...
113
114
        $this->assertEquals(count($classes), $listener->tableCalls);
115
        $this->assertTrue($listener->schemaCalled);
116
    }
117
118
    public function testNullDefaultNotAddedToCustomSchemaOptions()
119
    {
120
        $em = $this->_getTestEntityManager();
121
        $schemaTool = new SchemaTool($em);
122
123
        $customSchemaOptions = $schemaTool->getSchemaFromMetadata([$em->getClassMetadata(NullDefaultColumn::class)])
124
            ->getTable('NullDefaultColumn')
125
            ->getColumn('nullDefault')
126
            ->getCustomSchemaOptions();
127
128
        $this->assertSame([], $customSchemaOptions);
129
    }
130
131
    /**
132
     * @group DDC-3671
133
     */
134
    public function testSchemaHasProperIndexesFromUniqueConstraintAnnotation()
135
    {
136
        $em         = $this->_getTestEntityManager();
137
        $schemaTool = new SchemaTool($em);
138
        $classes    = [
139
            $em->getClassMetadata(UniqueConstraintAnnotationModel::class),
140
        ];
141
142
        $schema = $schemaTool->getSchemaFromMetadata($classes);
143
144
        $this->assertTrue($schema->hasTable('unique_constraint_annotation_table'));
145
        $table = $schema->getTable('unique_constraint_annotation_table');
146
147
        $this->assertEquals(2, count($table->getIndexes()));
148
        $this->assertTrue($table->hasIndex('primary'));
149
        $this->assertTrue($table->hasIndex('uniq_hash'));
150
    }
151
152
    public function testRemoveUniqueIndexOverruledByPrimaryKey()
153
    {
154
        $em         = $this->_getTestEntityManager();
155
        $schemaTool = new SchemaTool($em);
156
        $classes    = [
157
            $em->getClassMetadata(FirstEntity::class),
158
            $em->getClassMetadata(SecondEntity::class)
159
        ];
160
161
        $schema = $schemaTool->getSchemaFromMetadata($classes);
162
163
        $this->assertTrue($schema->hasTable('first_entity'), "Table first_entity should exist.");
164
165
        $indexes = $schema->getTable('first_entity')->getIndexes();
166
167
        $this->assertCount(1, $indexes, "there should be only one index");
168
        $this->assertTrue(current($indexes)->isPrimary(), "index should be primary");
169
    }
170
171
    public function testSetDiscriminatorColumnWithoutLength() : void
172
    {
173
        $em         = $this->_getTestEntityManager();
174
        $schemaTool = new SchemaTool($em);
175
        $metadata   = $em->getClassMetadata(FirstEntity::class);
176
177
        $metadata->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE);
178
        $metadata->setDiscriminatorColumn(['name' => 'discriminator', 'type' => 'string']);
179
180
        $schema = $schemaTool->getSchemaFromMetadata([$metadata]);
181
182
        $this->assertTrue($schema->hasTable('first_entity'));
183
        $table = $schema->getTable('first_entity');
184
185
        $this->assertTrue($table->hasColumn('discriminator'));
186
        $column = $table->getColumn('discriminator');
187
188
        $this->assertEquals(255, $column->getLength());
189
    }
190
191
    public function testDerivedCompositeKey() : void
192
    {
193
        $em         = $this->_getTestEntityManager();
194
        $schemaTool = new SchemaTool($em);
195
196
        $schema = $schemaTool->getSchemaFromMetadata(
197
            [
198
                $em->getClassMetadata(JoinedDerivedIdentityClass::class),
199
                $em->getClassMetadata(JoinedDerivedRootClass::class),
200
                $em->getClassMetadata(JoinedDerivedChildClass::class),
201
            ]
202
        );
203
204
        self::assertTrue($schema->hasTable('joined_derived_identity'));
205
        self::assertTrue($schema->hasTable('joined_derived_root'));
206
        self::assertTrue($schema->hasTable('joined_derived_child'));
207
208
        $rootTable = $schema->getTable('joined_derived_root');
209
        self::assertNotNull($rootTable->getPrimaryKey());
210
        self::assertSame(['keyPart1_id', 'keyPart2'], $rootTable->getPrimaryKey()->getColumns());
211
212
        $childTable = $schema->getTable('joined_derived_child');
213
        self::assertNotNull($childTable->getPrimaryKey());
214
        self::assertSame(['keyPart1_id', 'keyPart2'], $childTable->getPrimaryKey()->getColumns());
215
216
        $childTableForeignKeys = $childTable->getForeignKeys();
217
218
        self::assertCount(2, $childTableForeignKeys);
219
220
        $expectedColumns = [
221
            'joined_derived_identity' => [['keyPart1_id'], ['id']],
222
            'joined_derived_root'     => [['keyPart1_id', 'keyPart2'], ['keyPart1_id', 'keyPart2']],
223
        ];
224
225
        foreach ($childTableForeignKeys as $foreignKey) {
226
            self::assertArrayHasKey($foreignKey->getForeignTableName(), $expectedColumns);
227
228
            [$localColumns, $foreignColumns] = $expectedColumns[$foreignKey->getForeignTableName()];
229
230
            self::assertSame($localColumns, $foreignKey->getLocalColumns());
231
            self::assertSame($foreignColumns, $foreignKey->getForeignColumns());
232
        }
233
    }
234
}
235
236
/**
237
 * @Entity
238
 * @Table(options={"foo": "bar", "baz": {"key": "val"}})
239
 */
240
class TestEntityWithAnnotationOptionsAttribute
241
{
242
    /** @Id @Column */
243
    private $id;
0 ignored issues
show
introduced by
The private property $id is not used, and could be removed.
Loading history...
244
245
    /**
246
     * @Column(type="string", options={"foo": "bar", "baz": {"key": "val"}})
247
     */
248
    private $test;
0 ignored issues
show
introduced by
The private property $test is not used, and could be removed.
Loading history...
249
}
250
251
class GenerateSchemaEventListener
252
{
253
    public $tableCalls = 0;
254
    public $schemaCalled = false;
255
256
    public function postGenerateSchemaTable(GenerateSchemaTableEventArgs $eventArgs)
0 ignored issues
show
Unused Code introduced by
The parameter $eventArgs is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

256
    public function postGenerateSchemaTable(/** @scrutinizer ignore-unused */ GenerateSchemaTableEventArgs $eventArgs)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
257
    {
258
        $this->tableCalls++;
259
    }
260
261
    public function postGenerateSchema(GenerateSchemaEventArgs $eventArgs)
0 ignored issues
show
Unused Code introduced by
The parameter $eventArgs is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

261
    public function postGenerateSchema(/** @scrutinizer ignore-unused */ GenerateSchemaEventArgs $eventArgs)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
262
    {
263
        $this->schemaCalled = true;
264
    }
265
}
266
267
/**
268
 * @Entity
269
 * @Table(name="unique_constraint_annotation_table", uniqueConstraints={
270
 *   @UniqueConstraint(name="uniq_hash", columns={"hash"})
271
 * })
272
 */
273
class UniqueConstraintAnnotationModel
274
{
275
    /** @Id @Column */
276
    private $id;
277
278
    /**
279
     * @Column(name="hash", type="string", length=8, nullable=false, unique=true)
280
     */
281
    private $hash;
0 ignored issues
show
introduced by
The private property $hash is not used, and could be removed.
Loading history...
282
}
283
284
/**
285
 * @Entity
286
 * @Table(name="first_entity")
287
 */
288
class FirstEntity
289
{
290
    /**
291
     * @Id
292
     * @Column(name="id")
293
     */
294
    public $id;
295
296
    /**
297
     * @OneToOne(targetEntity="SecondEntity")
298
     * @JoinColumn(name="id", referencedColumnName="fist_entity_id")
299
     */
300
    public $secondEntity;
301
302
    /**
303
     * @Column(name="name")
304
     */
305
    public $name;
306
}
307
308
/**
309
 * @Entity
310
 * @Table(name="second_entity")
311
 */
312
class SecondEntity
313
{
314
    /**
315
     * @Id
316
     * @Column(name="fist_entity_id")
317
     */
318
    public $fist_entity_id;
319
320
    /**
321
     * @Column(name="name")
322
     */
323
    public $name;
324
}
325