Passed
Pull Request — master (#163)
by Wilmer
19:50 queued 04:50
created

uppercaseConstraintsProviderTrait()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\TestUtility;
6
7
use PDO;
8
use Yiisoft\Db\Constraint\CheckConstraint;
9
use Yiisoft\Db\Constraint\Constraint;
10
use Yiisoft\Db\Constraint\ForeignKeyConstraint;
11
use Yiisoft\Db\Constraint\IndexConstraint;
12
use Yiisoft\Db\Schema\ColumnSchema;
13
use Yiisoft\Db\Schema\Schema;
14
use Yiisoft\Db\Schema\TableSchema;
15
16
use function array_keys;
17
use function fclose;
18
use function fopen;
19
use function gettype;
20
use function is_array;
21
use function json_encode;
22
use function ksort;
23
use function print_r;
24
use function sort;
25
use function sprintf;
26
use function strtolower;
27
28
trait TestSchemaTrait
29
{
30
    public function testGetSchemaNames(): void
31
    {
32
        $schema = $this->getConnection()->getSchema();
0 ignored issues
show
Bug introduced by
It seems like getConnection() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

32
        $schema = $this->/** @scrutinizer ignore-call */ getConnection()->getSchema();
Loading history...
33
34
        $schemas = $schema->getSchemaNames();
35
36
        $this->assertNotEmpty($schemas);
0 ignored issues
show
Bug introduced by
It seems like assertNotEmpty() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

36
        $this->/** @scrutinizer ignore-call */ 
37
               assertNotEmpty($schemas);
Loading history...
37
38
        foreach ($this->expectedSchemas as $schema) {
39
            $this->assertContains($schema, $schemas);
0 ignored issues
show
Bug introduced by
It seems like assertContains() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

39
            $this->/** @scrutinizer ignore-call */ 
40
                   assertContains($schema, $schemas);
Loading history...
40
        }
41
    }
42
43
    public function testGetTableSchemasWithAttrCase(): void
44
    {
45
        $db = $this->getConnection(false);
46
47
        $db->getSlavePdo()->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
48
49
        $this->assertCount(count($db->getSchema()->getTableNames()), $db->getSchema()->getTableSchemas());
0 ignored issues
show
Bug introduced by
It seems like assertCount() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

49
        $this->/** @scrutinizer ignore-call */ 
50
               assertCount(count($db->getSchema()->getTableNames()), $db->getSchema()->getTableSchemas());
Loading history...
50
51
        $db->getSlavePdo()->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);
52
53
        $this->assertCount(count($db->getSchema()->getTableNames()), $db->getSchema()->getTableSchemas());
54
    }
55
56
    public function testGetNonExistingTableSchema(): void
57
    {
58
        $this->assertNull($this->getConnection()->getSchema()->getTableSchema('nonexisting_table'));
0 ignored issues
show
Bug introduced by
It seems like assertNull() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

58
        $this->/** @scrutinizer ignore-call */ 
59
               assertNull($this->getConnection()->getSchema()->getTableSchema('nonexisting_table'));
Loading history...
59
    }
60
61
    public function testSchemaCache(): void
62
    {
63
        $db = $this->getConnection();
64
65
        $schema = $db->getSchema();
66
67
        $schema->getDb()->setEnableSchemaCache(true);
68
        $schema->getDb()->setSchemaCache($this->cache);
69
70
        $noCacheTable = $schema->getTableSchema('type', true);
71
        $cachedTable = $schema->getTableSchema('type', false);
72
73
        $this->assertEquals($noCacheTable, $cachedTable);
0 ignored issues
show
Bug introduced by
It seems like assertEquals() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

73
        $this->/** @scrutinizer ignore-call */ 
74
               assertEquals($noCacheTable, $cachedTable);
Loading history...
74
75
        $db->createCommand()->renameTable('type', 'type_test');
76
77
        $noCacheTable = $schema->getTableSchema('type', true);
78
79
        $this->assertNotSame($noCacheTable, $cachedTable);
0 ignored issues
show
Bug introduced by
It seems like assertNotSame() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

79
        $this->/** @scrutinizer ignore-call */ 
80
               assertNotSame($noCacheTable, $cachedTable);
Loading history...
80
81
        $db->createCommand()->renameTable('type_test', 'type');
82
    }
83
84
    /**
85
     * @depends testSchemaCache
86
     */
87
    public function testRefreshTableSchema(): void
88
    {
89
        $schema = $this->getConnection()->getSchema();
90
91
        $schema->getDb()->setEnableSchemaCache(true);
92
        $schema->getDb()->setSchemaCache($this->cache);
93
94
        $noCacheTable = $schema->getTableSchema('type', true);
95
96
        $schema->refreshTableSchema('type');
97
98
        $refreshedTable = $schema->getTableSchema('type', false);
99
100
        $this->assertNotSame($noCacheTable, $refreshedTable);
101
    }
102
103
    public function testCompositeFk(): void
104
    {
105
        $schema = $this->getConnection()->getSchema();
106
107
        $table = $schema->getTableSchema('composite_fk');
108
109
        $fk = $table->getForeignKeys();
110
111
        $this->assertCount(1, $fk);
112
        $this->assertTrue(isset($fk['FK_composite_fk_order_item']));
0 ignored issues
show
Bug introduced by
It seems like assertTrue() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

112
        $this->/** @scrutinizer ignore-call */ 
113
               assertTrue(isset($fk['FK_composite_fk_order_item']));
Loading history...
113
        $this->assertEquals('order_item', $fk['FK_composite_fk_order_item'][0]);
114
        $this->assertEquals('order_id', $fk['FK_composite_fk_order_item']['order_id']);
115
        $this->assertEquals('item_id', $fk['FK_composite_fk_order_item']['item_id']);
116
    }
117
118
    public function testGetPDOType(): void
119
    {
120
        $values = [
121
            [null, PDO::PARAM_NULL],
122
            ['', PDO::PARAM_STR],
123
            ['hello', PDO::PARAM_STR],
124
            [0, PDO::PARAM_INT],
125
            [1, PDO::PARAM_INT],
126
            [1337, PDO::PARAM_INT],
127
            [true, PDO::PARAM_BOOL],
128
            [false, PDO::PARAM_BOOL],
129
            [$fp = fopen(__FILE__, 'rb'), PDO::PARAM_LOB],
130
        ];
131
132
        $schema = $this->getConnection()->getSchema();
133
134
        foreach ($values as $value) {
135
            $this->assertEquals($value[1], $schema->getPdoType($value[0]), 'type for value ' . print_r($value[0], true) . ' does not match.');
136
        }
137
138
        fclose($fp);
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

138
        fclose(/** @scrutinizer ignore-type */ $fp);
Loading history...
139
    }
140
141
    public function testColumnSchema(): void
142
    {
143
        $columns = $this->getExpectedColumns();
0 ignored issues
show
Bug introduced by
It seems like getExpectedColumns() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

143
        /** @scrutinizer ignore-call */ 
144
        $columns = $this->getExpectedColumns();
Loading history...
144
145
        $table = $this->getConnection(false)->getSchema()->getTableSchema('type', true);
146
147
        $expectedColNames = array_keys($columns);
148
149
        sort($expectedColNames);
150
151
        $colNames = $table->getColumnNames();
152
153
        sort($colNames);
154
155
        $this->assertEquals($expectedColNames, $colNames);
156
157
        foreach ($table->getColumns() as $name => $column) {
158
            $expected = $columns[$name];
159
            $this->assertSame(
0 ignored issues
show
Bug introduced by
It seems like assertSame() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

159
            $this->/** @scrutinizer ignore-call */ 
160
                   assertSame(
Loading history...
160
                $expected['dbType'],
161
                $column->getDbType(),
162
                "dbType of column $name does not match. type is {$column->getType()}, dbType is {$column->getDbType()}."
163
            );
164
            $this->assertSame(
165
                $expected['phpType'],
166
                $column->getPhpType(),
167
                "phpType of column $name does not match. type is {$column->getType()}, dbType is {$column->getDbType()}."
168
            );
169
            $this->assertSame($expected['type'], $column->getType(), "type of column $name does not match.");
170
            $this->assertSame(
171
                $expected['allowNull'],
172
                $column->isAllowNull(),
173
                "allowNull of column $name does not match."
174
            );
175
            $this->assertSame(
176
                $expected['autoIncrement'],
177
                $column->isAutoIncrement(),
178
                "autoIncrement of column $name does not match."
179
            );
180
            $this->assertSame(
181
                $expected['enumValues'],
182
                $column->getEnumValues(),
183
                "enumValues of column $name does not match."
184
            );
185
            $this->assertSame($expected['size'], $column->getSize(), "size of column $name does not match.");
186
            $this->assertSame(
187
                $expected['precision'],
188
                $column->getPrecision(),
189
                "precision of column $name does not match."
190
            );
191
            $this->assertSame($expected['scale'], $column->getScale(), "scale of column $name does not match.");
192
            if (\is_object($expected['defaultValue'])) {
193
                $this->assertIsObject(
0 ignored issues
show
Bug introduced by
It seems like assertIsObject() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

193
                $this->/** @scrutinizer ignore-call */ 
194
                       assertIsObject(
Loading history...
194
                    $column->getDefaultValue(),
195
                    "defaultValue of column $name is expected to be an object but it is not."
196
                );
197
                $this->assertEquals(
198
                    (string) $expected['defaultValue'],
199
                    (string) $column->getDefaultValue(),
200
                    "defaultValue of column $name does not match."
201
                );
202
            } else {
203
                $this->assertEquals(
204
                    $expected['defaultValue'],
205
                    $column->getDefaultValue(),
206
                    "defaultValue of column $name does not match."
207
                );
208
            }
209
            /* Pgsql only */
210
            if (isset($expected['dimension'])) {
211
                $this->assertSame(
212
                    $expected['dimension'],
213
                    $column->getDimension(),
214
                    "dimension of column $name does not match"
215
                );
216
            }
217
        }
218
    }
219
220
    public function testColumnSchemaDbTypecastWithEmptyCharType(): void
221
    {
222
        $columnSchema = new ColumnSchema();
223
224
        $columnSchema->setType(Schema::TYPE_CHAR);
225
226
        $this->assertSame('', $columnSchema->dbTypecast(''));
227
    }
228
229
    public function testNegativeDefaultValues(): void
230
    {
231
        $schema = $this->getConnection()->getSchema();
232
233
        $table = $schema->getTableSchema('negative_default_values');
234
235
        $this->assertEquals(-123, $table->getColumn('tinyint_col')->getDefaultValue());
236
        $this->assertEquals(-123, $table->getColumn('smallint_col')->getDefaultValue());
237
        $this->assertEquals(-123, $table->getColumn('int_col')->getDefaultValue());
238
        $this->assertEquals(-123, $table->getColumn('bigint_col')->getDefaultValue());
239
        $this->assertEquals(-12345.6789, $table->getColumn('float_col')->getDefaultValue());
240
        $this->assertEquals(-33.22, $table->getColumn('numeric_col')->getDefaultValue());
241
    }
242
243
    public function testContraintTablesExistance(): void
244
    {
245
        $tableNames = [
246
            'T_constraints_1',
247
            'T_constraints_2',
248
            'T_constraints_3',
249
            'T_constraints_4',
250
        ];
251
252
        $schema = $this->getConnection()->getSchema();
253
254
        foreach ($tableNames as $tableName) {
255
            $tableSchema = $schema->getTableSchema($tableName);
256
            $this->assertInstanceOf(TableSchema::class, $tableSchema, $tableName);
0 ignored issues
show
Bug introduced by
It seems like assertInstanceOf() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

256
            $this->/** @scrutinizer ignore-call */ 
257
                   assertInstanceOf(TableSchema::class, $tableSchema, $tableName);
Loading history...
257
        }
258
    }
259
260
    private function assertMetadataEquals($expected, $actual): void
261
    {
262
        switch (strtolower(gettype($expected))) {
263
            case 'object':
264
                $this->assertIsObject($actual);
265
                break;
266
            case 'array':
267
                $this->assertIsArray($actual);
0 ignored issues
show
Bug introduced by
It seems like assertIsArray() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

267
                $this->/** @scrutinizer ignore-call */ 
268
                       assertIsArray($actual);
Loading history...
268
                break;
269
            case 'null':
270
                $this->assertNull($actual);
271
                break;
272
        }
273
274
        if (is_array($expected)) {
275
            $this->normalizeArrayKeys($expected, false);
276
            $this->normalizeArrayKeys($actual, false);
277
        }
278
279
        $this->normalizeConstraints($expected, $actual);
280
281
        if (is_array($expected)) {
282
            $this->normalizeArrayKeys($expected, true);
283
            $this->normalizeArrayKeys($actual, true);
284
        }
285
286
        $this->assertEquals($expected, $actual);
287
    }
288
289
    private function normalizeArrayKeys(array &$array, bool $caseSensitive): void
290
    {
291
        $newArray = [];
292
293
        foreach ($array as $value) {
294
            if ($value instanceof Constraint) {
295
                $key = (array) $value;
296
                unset(
297
                    $key["\000Yiisoft\Db\Constraint\Constraint\000name"],
298
                    $key["\u0000Yiisoft\\Db\\Constraint\\ForeignKeyConstraint\u0000foreignSchemaName"]
299
                );
300
301
                foreach ($key as $keyName => $keyValue) {
302
                    if ($keyValue instanceof AnyCaseValue) {
303
                        $key[$keyName] = $keyValue->value;
304
                    } elseif ($keyValue instanceof AnyValue) {
305
                        $key[$keyName] = '[AnyValue]';
306
                    }
307
                }
308
309
                ksort($key, SORT_STRING);
310
311
                $newArray[$caseSensitive
312
                    ? json_encode($key, JSON_THROW_ON_ERROR)
313
                    : strtolower(json_encode($key, JSON_THROW_ON_ERROR))] = $value;
314
            } else {
315
                $newArray[] = $value;
316
            }
317
        }
318
319
        ksort($newArray, SORT_STRING);
320
321
        $array = $newArray;
322
    }
323
324
    private function normalizeConstraints(&$expected, &$actual): void
325
    {
326
        if (is_array($expected)) {
327
            foreach ($expected as $key => $value) {
328
                if (!$value instanceof Constraint || !isset($actual[$key]) || !$actual[$key] instanceof Constraint) {
329
                    continue;
330
                }
331
332
                $this->normalizeConstraintPair($value, $actual[$key]);
333
            }
334
        } elseif ($expected instanceof Constraint && $actual instanceof Constraint) {
335
            $this->normalizeConstraintPair($expected, $actual);
336
        }
337
    }
338
339
    private function normalizeConstraintPair(Constraint $expectedConstraint, Constraint $actualConstraint): void
340
    {
341
        if (get_class($expectedConstraint) !== get_class($actualConstraint)) {
342
            return;
343
        }
344
345
        foreach (array_keys((array) $expectedConstraint) as $name) {
346
            if ($expectedConstraint->getName() instanceof AnyValue) {
347
                $actualConstraint->name($expectedConstraint->getName());
348
            } elseif ($expectedConstraint->getName() instanceof AnyCaseValue) {
349
                $actualConstraint->name(new AnyCaseValue($actualConstraint->getName()));
350
            }
351
        }
352
    }
353
354
    public function constraintsProviderTrait(): array
355
    {
356
        return [
357
            '1: primary key' => [
358
                'T_constraints_1',
359
                'primaryKey',
360
                (new Constraint())
361
                    ->name(AnyValue::getInstance())
362
                    ->columnNames(['C_id'])
363
            ],
364
            '1: check' => [
365
                'T_constraints_1',
366
                'checks',
367
                [
368
                    (new CheckConstraint())
369
                        ->name(AnyValue::getInstance())
370
                        ->columnNames(['C_check'])
371
                        ->expression("C_check <> ''")
372
                ]
373
            ],
374
            '1: unique' => [
375
                'T_constraints_1',
376
                'uniques',
377
                [
378
                    (new Constraint())
379
                        ->name('CN_unique')
380
                        ->columnNames(['C_unique'])
381
                ]
382
            ],
383
            '1: index' => [
384
                'T_constraints_1',
385
                'indexes',
386
                [
387
                    (new IndexConstraint())
388
                        ->name(AnyValue::getInstance())
389
                        ->columnNames(['C_id'])
390
                        ->unique(true)
391
                        ->primary(true),
392
                    (new IndexConstraint())
393
                        ->name('CN_unique')
394
                        ->columnNames(['C_unique'])
395
                        ->primary(false)
396
                        ->unique(true)
397
                ]
398
            ],
399
            '1: default' => ['T_constraints_1', 'defaultValues', false],
400
401
            '2: primary key' => [
402
                'T_constraints_2',
403
                'primaryKey',
404
                (new Constraint())
405
                    ->name('CN_pk')
406
                    ->columnNames(['C_id_1', 'C_id_2'])
407
            ],
408
            '2: unique' => [
409
                'T_constraints_2',
410
                'uniques',
411
                [
412
                    (new Constraint())
413
                        ->name('CN_constraints_2_multi')
414
                        ->columnNames(['C_index_2_1', 'C_index_2_2'])
415
                ]
416
            ],
417
            '2: index' => [
418
                'T_constraints_2',
419
                'indexes',
420
                [
421
                    (new IndexConstraint())
422
                        ->name(AnyValue::getInstance())
423
                        ->columnNames(['C_id_1', 'C_id_2'])
424
                        ->unique(true)
425
                        ->primary(true),
426
                    (new IndexConstraint())
427
                        ->name('CN_constraints_2_single')
428
                        ->columnNames(['C_index_1'])
429
                        ->primary(false)
430
                        ->unique(false),
431
                    (new IndexConstraint())
432
                        ->name('CN_constraints_2_multi')
433
                        ->columnNames(['C_index_2_1', 'C_index_2_2'])
434
                        ->primary(false)
435
                        ->unique(true)
436
                ]
437
            ],
438
            '2: check' => ['T_constraints_2', 'checks', []],
439
            '2: default' => ['T_constraints_2', 'defaultValues', false],
440
441
            '3: primary key' => ['T_constraints_3', 'primaryKey', null],
442
            '3: foreign key' => [
443
                'T_constraints_3',
444
                'foreignKeys',
445
                [
446
                    (new ForeignKeyConstraint())
447
                        ->name('CN_constraints_3')
448
                        ->columnNames(['C_fk_id_1', 'C_fk_id_2'])
449
                        ->foreignTableName('T_constraints_2')
450
                        ->foreignColumnNames(['C_id_1', 'C_id_2'])
451
                        ->onDelete('CASCADE')
452
                        ->onUpdate('CASCADE')
453
                ]
454
            ],
455
            '3: unique' => ['T_constraints_3', 'uniques', []],
456
            '3: index' => [
457
                'T_constraints_3',
458
                'indexes',
459
                [
460
                    (new IndexConstraint())
461
                        ->name('CN_constraints_3')
462
                        ->columnNames(['C_fk_id_1', 'C_fk_id_2'])
463
                        ->unique(false)
464
                        ->primary(false)
465
                ]
466
            ],
467
            '3: check' => ['T_constraints_3', 'checks', []],
468
            '3: default' => ['T_constraints_3', 'defaultValues', false],
469
470
            '4: primary key' => [
471
                'T_constraints_4',
472
                'primaryKey',
473
                (new Constraint())
474
                    ->name(AnyValue::getInstance())
475
                    ->columnNames(['C_id'])
476
            ],
477
            '4: unique' => [
478
                'T_constraints_4',
479
                'uniques',
480
                [
481
                    (new Constraint())
482
                        ->name('CN_constraints_4')
483
                        ->columnNames(['C_col_1', 'C_col_2'])
484
                ]
485
            ],
486
            '4: check' => ['T_constraints_4', 'checks', []],
487
            '4: default' => ['T_constraints_4', 'defaultValues', false],
488
        ];
489
    }
490
491
    public function pdoAttributesProviderTrait(): array
492
    {
493
        return [
494
            [[PDO::ATTR_EMULATE_PREPARES => true]],
495
            [[PDO::ATTR_EMULATE_PREPARES => false]],
496
        ];
497
    }
498
499
    public function tableSchemaCachePrefixesProviderTrait(): array
500
    {
501
        $configs = [
502
            [
503
                'prefix' => '',
504
                'name'   => 'type',
505
            ],
506
            [
507
                'prefix' => '',
508
                'name'   => '{{%type}}',
509
            ],
510
            [
511
                'prefix' => 'ty',
512
                'name'   => '{{%pe}}',
513
            ],
514
        ];
515
516
        $data = [];
517
        foreach ($configs as $config) {
518
            foreach ($configs as $testConfig) {
519
                if ($config === $testConfig) {
520
                    continue;
521
                }
522
523
                $description = sprintf(
524
                    "%s (with '%s' prefix) against %s (with '%s' prefix)",
525
                    $config['name'],
526
                    $config['prefix'],
527
                    $testConfig['name'],
528
                    $testConfig['prefix']
529
                );
530
                $data[$description] = [
531
                    $config['prefix'],
532
                    $config['name'],
533
                    $testConfig['prefix'],
534
                    $testConfig['name'],
535
                ];
536
            }
537
        }
538
539
        return $data;
540
    }
541
542
    public function lowercaseConstraintsProviderTrait(): array
543
    {
544
        return $this->constraintsProvider();
0 ignored issues
show
Bug introduced by
The method constraintsProvider() does not exist on Yiisoft\Db\TestUtility\TestSchemaTrait. Did you maybe mean constraintsProviderTrait()? ( Ignorable by Annotation )

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

544
        return $this->/** @scrutinizer ignore-call */ constraintsProvider();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
545
    }
546
547
    public function uppercaseConstraintsProviderTrait(): array
548
    {
549
        return $this->constraintsProvider();
550
    }
551
}
552