GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Pull Request — master (#214)
by joseph
20:06
created

MappingHelper::setSimpleStringFields()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 4.1054

Importance

Changes 0
Metric Value
cc 4
eloc 16
nc 3
nop 4
dl 0
loc 27
ccs 13
cts 16
cp 0.8125
crap 4.1054
rs 9.7333
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta;
4
5
use DateTimeImmutable;
6
use Doctrine\Common\Inflector\Inflector;
7
use Doctrine\DBAL\Types\Type;
8
use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder;
9
use Doctrine\ORM\Mapping\Builder\FieldBuilder;
10
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
11
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\TypeHelper;
12
use EdmondsCommerce\DoctrineStaticMeta\Schema\Database;
13
use InvalidArgumentException;
14
use Ramsey\Uuid\Doctrine\UuidBinaryOrderedTimeType;
15
use Ramsey\Uuid\Doctrine\UuidBinaryType;
16
use Ramsey\Uuid\Doctrine\UuidType;
17
use function is_bool;
18
use function is_float;
19
use function is_int;
20
use function is_string;
21
use function str_replace;
22
use function strlen;
23
24
/**
25
 * Class MappingHelper
26
 *
27
 * Helper functions to assist with setting up Doctrine mapping meta data
28
 *
29
 * @package EdmondsCommerce\DoctrineStaticMeta
30
 *
31
 * @SuppressWarnings(PHPMD.StaticAccess)
32
 */
33
class MappingHelper
34
{
35
36
    /**
37
     * Primary Key types (beyond the common types)
38
     */
39
    public const TYPE_UUID                    = UuidBinaryOrderedTimeType::NAME;
40
    public const TYPE_NON_BINARY_UUID         = UuidType::NAME;
41
    public const TYPE_NON_ORDERED_BINARY_UUID = UuidBinaryType::NAME;
42
43
    /**
44
     * Quick accessors for common types that are supported by methods in this helper
45
     *
46
     * Note this is not all of the types supported by Doctrine
47
     */
48
    public const TYPE_STRING   = Type::STRING;
49
    public const TYPE_DATETIME = Type::DATETIME;
50
    public const TYPE_FLOAT    = Type::FLOAT;
51
    public const TYPE_DECIMAL  = Type::DECIMAL;
52
    public const TYPE_INTEGER  = Type::INTEGER;
53
    public const TYPE_TEXT     = Type::TEXT;
54
    public const TYPE_BOOLEAN  = Type::BOOLEAN;
55
    public const TYPE_JSON     = Type::JSON;
56
57
58
    /**
59
     * This is the list of common types, listed above
60
     */
61
    public const COMMON_TYPES = [
62
        self::TYPE_STRING,
63
        self::TYPE_DATETIME,
64
        self::TYPE_FLOAT,
65
        self::TYPE_DECIMAL,
66
        self::TYPE_INTEGER,
67
        self::TYPE_TEXT,
68
        self::TYPE_BOOLEAN,
69
        self::TYPE_JSON,
70
    ];
71
72
    /**
73
     * Which types do we support marking as unique
74
     */
75
    public const UNIQUEABLE_TYPES = [
76
        self::TYPE_STRING,
77
        self::TYPE_INTEGER,
78
    ];
79
80
    public const PHP_TYPE_STRING   = 'string';
81
    public const PHP_TYPE_DATETIME = '\\' . DateTimeImmutable::class;
82
    public const PHP_TYPE_FLOAT    = 'float';
83
    public const PHP_TYPE_INTEGER  = 'int';
84
    public const PHP_TYPE_TEXT     = 'string';
85
    public const PHP_TYPE_BOOLEAN  = 'bool';
86
87
    public const PHP_TYPES = [
88
        self::PHP_TYPE_STRING,
89
        self::PHP_TYPE_DATETIME,
90
        self::PHP_TYPE_FLOAT,
91
        self::PHP_TYPE_INTEGER,
92
        self::PHP_TYPE_TEXT,
93
        self::PHP_TYPE_BOOLEAN,
94
    ];
95
96
    /**
97
     * The PHP type associated with the mapping type
98
     */
99
    public const COMMON_TYPES_TO_PHP_TYPES = [
100
        self::TYPE_STRING   => self::PHP_TYPE_STRING,
101
        self::TYPE_DATETIME => self::PHP_TYPE_DATETIME,
102
        self::TYPE_FLOAT    => self::PHP_TYPE_FLOAT,
103
        self::TYPE_DECIMAL  => self::PHP_TYPE_STRING,
104
        self::TYPE_INTEGER  => self::PHP_TYPE_INTEGER,
105
        self::TYPE_TEXT     => self::PHP_TYPE_TEXT,
106
        self::TYPE_BOOLEAN  => self::PHP_TYPE_BOOLEAN,
107
        self::TYPE_JSON     => self::PHP_TYPE_STRING,
108
    ];
109
110
    /**
111
     * This is the full list of mapping types
112
     *
113
     * @see \Doctrine\DBAL\Types\Type
114
     */
115
    public const ALL_DBAL_TYPES = [
116
        Type::TARRAY,
117
        Type::SIMPLE_ARRAY,
118
        Type::JSON,
119
        Type::BIGINT,
120
        Type::BOOLEAN,
121
        Type::DATETIME,
122
        Type::DATETIME_IMMUTABLE,
123
        Type::DATETIMETZ,
124
        Type::DATETIMETZ_IMMUTABLE,
125
        Type::DATE,
126
        Type::DATE_IMMUTABLE,
127
        Type::TIME,
128
        Type::TIME_IMMUTABLE,
129
        Type::DECIMAL,
130
        Type::INTEGER,
131
        Type::OBJECT,
132
        Type::SMALLINT,
133
        Type::STRING,
134
        Type::TEXT,
135
        Type::BINARY,
136
        Type::BLOB,
137
        Type::FLOAT,
138
        Type::GUID,
139
        Type::DATEINTERVAL,
140
    ];
141
142
    public const MIXED_TYPES = [
143
        // Doctrine hydrates decimal values as strings.
144
        // However, setting these using an int or float is also valid.
145
        Type::DECIMAL,
146
    ];
147
148
    /**
149
     * @param string $entityFqn
150
     *
151
     * @return string
152
     */
153 2
    public static function getPluralForFqn(string $entityFqn): string
154
    {
155 2
        $singular = self::getSingularForFqn($entityFqn);
156
157 2
        $plural = self::pluralize($singular);
158 2
        if ($plural === $singular) {
159
            $plural = $singular . 's';
160
        }
161
162 2
        return $plural;
163
    }
164
165
    /**
166
     * @param string $entityFqn
167
     *
168
     * @return string
169
     */
170 14
    public static function getSingularForFqn(string $entityFqn): string
171
    {
172 14
        $shortName = self::getShortNameForFqn($entityFqn);
173 14
        $singular  = self::singularize($shortName);
174
175 14
        return lcfirst($singular);
176
    }
177
178
    /**
179
     * @param string $entityFqn
180
     *
181
     * @return string
182
     */
183 14
    public static function getShortNameForFqn(string $entityFqn): string
184
    {
185 14
        return substr($entityFqn, strrpos($entityFqn, '\\') + 1);
186
    }
187
188 14
    public static function singularize(string $item): string
189
    {
190 14
        $singular = Inflector::singularize($item);
191 14
        if ('datum' === strtolower(substr($singular, -5))) {
192 2
            $singular = $item;
193
        }
194
195 14
        return $singular;
196
    }
197
198 2
    public static function pluralize(string $item): string
199
    {
200 2
        $plural = Inflector::pluralize($item);
201 2
        if ($plural === $item) {
202 2
            $plural = $item . 's';
203
        }
204
205 2
        return $plural;
206
    }
207
208
    /**
209
     * @param string $entityFqn
210
     *
211
     * @return string
212
     */
213 4
    public static function getTableNameForEntityFqn(
214
        string $entityFqn
215
    ): string {
216 4
        $namespaceHelper = new NamespaceHelper();
217 4
        $subFqn          = $namespaceHelper->getEntitySubNamespace(
218 4
            $entityFqn
219
        );
220 4
        $tableName       = str_replace('\\', '', $subFqn);
221 4
        $tableName       = self::backticks(Inflector::tableize($tableName));
222 4
        if (strlen($tableName) > Database::MAX_IDENTIFIER_LENGTH) {
223
            $tableName = substr($tableName, -Database::MAX_IDENTIFIER_LENGTH);
224
        }
225
226 4
        return $tableName;
227
    }
228
229
    /**
230
     * Wrap the name in backticks
231
     *
232
     * @param string $name
233
     *
234
     * @return string
235
     */
236 6
    public static function backticks(string $name): string
237
    {
238 6
        return '`' . $name . '`';
239
    }
240
241
    /**
242
     * Set bog standard string fields quickly in bulk
243
     *
244
     * @param array                $fields
245
     * @param ClassMetadataBuilder $builder
246
     * @param mixed                $default
247
     * @param bool                 $isUnique
248
     * In this case the boolean argument is simply data
249
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
250
     */
251 2
    public static function setSimpleStringFields(
252
        array $fields,
253
        ClassMetadataBuilder $builder,
254
        $default = null,
255
        bool $isUnique = false
256
    ): void {
257 2
        if (null !== $default && !is_string($default)) {
258
            throw new InvalidArgumentException(
259
                'Invalid default value ' . $default
260
                . ' with type ' . self::getType($default)
261
            );
262
        }
263 2
        foreach ($fields as $field) {
264 2
            $fieldBuilder = new FieldBuilder(
265 2
                $builder,
266
                [
267 2
                    'fieldName' => $field,
268 2
                    'type'      => Type::STRING,
269 2
                    'default'   => $default,
270
                ]
271
            );
272
            $fieldBuilder
273 2
                ->columnName(self::getColumnNameForField($field))
274 2
                ->nullable(null === $default)
275 2
                ->unique($isUnique)
276 2
                ->length(Database::MAX_VARCHAR_LENGTH)
277 2
                ->build();
278
        }
279 2
    }
280
281
    private static function getType($var): string
282
    {
283
        static $typeHelper;
284
        if (null === $typeHelper) {
285
            $typeHelper = new TypeHelper();
286
        }
287
288
        return $typeHelper->getType($var);
289
    }
290
291
    /**
292
     * Get the properly backticked and formatted column name for a field
293
     *
294
     * @param string $field
295
     *
296
     * @return string
297
     */
298 4
    public static function getColumnNameForField(string $field): string
299
    {
300 4
        return self::backticks(Inflector::tableize($field));
301
    }
302
303
    /**
304
     * Set bog standard text fields quickly in bulk
305
     *
306
     * @param array                $fields
307
     * @param ClassMetadataBuilder $builder
308
     * @param mixed                $default
309
     * In this case the boolean argument is simply data
310
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
311
     */
312 2
    public static function setSimpleTextFields(
313
        array $fields,
314
        ClassMetadataBuilder $builder,
315
        $default = null
316
    ): void {
317 2
        if (null !== $default && !is_string($default)) {
318
            throw new InvalidArgumentException(
319
                'Invalid default value ' . $default
320
                . ' with type ' . self::getType($default)
321
            );
322
        }
323 2
        foreach ($fields as $field) {
324 2
            $fieldBuilder = new FieldBuilder(
325 2
                $builder,
326
                [
327 2
                    'fieldName' => $field,
328 2
                    'type'      => Type::TEXT,
329 2
                    'default'   => $default,
330
                ]
331
            );
332 2
            $fieldBuilder->columnName(self::getColumnNameForField($field))
333 2
                         ->nullable(null === $default)
334 2
                         ->build();
335
        }
336 2
    }
337
338
339
    /**
340
     * Set bog standard float fields quickly in bulk
341
     *
342
     * @param array                $fields
343
     * @param ClassMetadataBuilder $builder
344
     * @param mixed                $default
345
     * In this case the boolean argument is simply data
346
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
347
     */
348 2
    public static function setSimpleFloatFields(
349
        array $fields,
350
        ClassMetadataBuilder $builder,
351
        $default = null
352
    ): void {
353 2
        if (null !== $default && !is_float($default)) {
354
            throw new InvalidArgumentException(
355
                'Invalid default value ' . $default
356
                . ' with type ' . self::getType($default)
357
            );
358
        }
359 2
        foreach ($fields as $field) {
360 2
            $fieldBuilder = new FieldBuilder(
361 2
                $builder,
362
                [
363 2
                    'fieldName' => $field,
364 2
                    'type'      => Type::FLOAT,
365 2
                    'default'   => $default,
366
                ]
367
            );
368
            $fieldBuilder
369 2
                ->columnName(self::getColumnNameForField($field))
370 2
                ->nullable(null === $default)
371 2
                ->build();
372
        }
373 2
    }
374
375
    /**
376
     * Set bog standard decimal fields quickly in bulk
377
     *
378
     * @param array                $fields
379
     * @param ClassMetadataBuilder $builder
380
     * @param mixed                $default
381
     * In this case the boolean argument is simply data
382
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
383
     */
384 2
    public static function setSimpleDecimalFields(
385
        array $fields,
386
        ClassMetadataBuilder $builder,
387
        $default = null
388
    ): void {
389 2
        if (null !== $default && !is_string($default)) {
390
            throw new InvalidArgumentException(
391
                'Invalid default value ' . $default
392
                . ' with type ' . self::getType($default)
393
            );
394
        }
395 2
        if (null !== $default && !is_numeric($default)) {
396
            throw new InvalidArgumentException(
397
                'Invalid default value ' . $default
398
                . ', even though it is a string, it must be numeric '
399
            );
400
        }
401 2
        foreach ($fields as $field) {
402 2
            $fieldBuilder = new FieldBuilder(
403 2
                $builder,
404
                [
405 2
                    'fieldName' => $field,
406 2
                    'type'      => Type::DECIMAL,
407 2
                    'default'   => (string)(float)$default,
408
                ]
409
            );
410
            $fieldBuilder
411 2
                ->columnName(self::getColumnNameForField($field))
412 2
                ->nullable(null === $default)
413 2
                ->precision(Database::MAX_DECIMAL_PRECISION)
414 2
                ->scale(Database::MAX_DECIMAL_SCALE)
415 2
                ->build();
416
        }
417 2
    }
418
419
    /**
420
     * Set bog standard dateTime fields quickly in bulk
421
     *
422
     * @param array                $fields
423
     * @param ClassMetadataBuilder $builder
424
     * @param mixed                $default
425
     * In this case the boolean argument is simply data
426
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
427
     */
428 2
    public static function setSimpleDatetimeFields(
429
        array $fields,
430
        ClassMetadataBuilder $builder,
431
        $default = null
432
    ): void {
433 2
        if (null !== $default) {
434
            throw new InvalidArgumentException('DateTime currently only support null as a default value');
435
        }
436 2
        foreach ($fields as $field) {
437 2
            $fieldBuilder = new FieldBuilder(
438 2
                $builder,
439
                [
440 2
                    'fieldName' => $field,
441 2
                    'type'      => Type::DATETIME_IMMUTABLE,
442 2
                    'default'   => $default,
443
                ]
444
            );
445
            $fieldBuilder
446 2
                ->columnName(self::getColumnNameForField($field))
447 2
                ->nullable(null === $default)
448 2
                ->build();
449
        }
450 2
    }
451
452
    /**
453
     * Set bog standard integer fields quickly in bulk
454
     *
455
     * @param array                $fields
456
     * @param ClassMetadataBuilder $builder
457
     * @param mixed                $default
458
     * @param bool                 $isUnique
459
     * In this case the boolean argument is simply data
460
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
461
     */
462 2
    public static function setSimpleIntegerFields(
463
        array $fields,
464
        ClassMetadataBuilder $builder,
465
        $default = null,
466
        bool $isUnique = false
467
    ): void {
468 2
        if (null !== $default && !is_int($default)) {
469
            throw new InvalidArgumentException(
470
                'Invalid default value ' . $default
471
                . ' with type ' . self::getType($default)
472
            );
473
        }
474 2
        foreach ($fields as $field) {
475 2
            $fieldBuilder = new FieldBuilder(
476 2
                $builder,
477
                [
478 2
                    'fieldName' => $field,
479 2
                    'type'      => Type::INTEGER,
480 2
                    'default'   => $default,
481
                ]
482
            );
483
            $fieldBuilder
484 2
                ->columnName(self::getColumnNameForField($field))
485 2
                ->nullable(null === $default)
486 2
                ->unique($isUnique)
487 2
                ->build();
488
        }
489 2
    }
490
491
    /**
492
     * Set bog standard boolean fields quickly in bulk
493
     *
494
     * @param array                $fields
495
     * @param ClassMetadataBuilder $builder
496
     * @param mixed                $default
497
     * In this case the boolean argument is simply data
498
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
499
     */
500 2
    public static function setSimpleBooleanFields(
501
        array $fields,
502
        ClassMetadataBuilder $builder,
503
        $default = null
504
    ): void {
505 2
        if (null !== $default && !is_bool($default)) {
506
            throw new InvalidArgumentException(
507
                'Invalid default value ' . $default
508
                . ' with type ' . self::getType($default)
509
            );
510
        }
511 2
        foreach ($fields as $field) {
512 2
            $fieldBuilder = new FieldBuilder(
513 2
                $builder,
514
                [
515 2
                    'fieldName' => $field,
516 2
                    'type'      => Type::BOOLEAN,
517 2
                    'default'   => $default,
518
                ]
519
            );
520
            $fieldBuilder
521 2
                ->columnName(self::getColumnNameForField($field))
522 2
                ->nullable(null === $default)
523 2
                ->build();
524
        }
525 2
    }
526
527
    /**
528
     * Create JSON fields
529
     *
530
     * Will use real JSON in the DB engine if it is supported
531
     *
532
     * This should be used for any structured data, arrays, lists, simple objects
533
     *
534
     * @param array                $fields
535
     * @param ClassMetadataBuilder $builder
536
     * @param null                 $default
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $default is correct as it would always require null to be passed?
Loading history...
537
     */
538 2
    public static function setSimpleJsonFields(
539
        array $fields,
540
        ClassMetadataBuilder $builder,
541
        $default = null
542
    ): void {
543 2
        if (null !== $default && !is_string($default)) {
0 ignored issues
show
introduced by
The condition null !== $default is always false.
Loading history...
544
            throw new InvalidArgumentException(
545
                'Invalid default value ' . $default
546
                . ' with type ' . self::getType($default)
547
            );
548
        }
549 2
        foreach ($fields as $field) {
550 2
            $fieldBuilder = new FieldBuilder(
551 2
                $builder,
552
                [
553 2
                    'fieldName' => $field,
554 2
                    'type'      => Type::JSON,
555 2
                    'default'   => $default,
556
                ]
557
            );
558
            $fieldBuilder
559 2
                ->columnName(self::getColumnNameForField($field))
560 2
                ->nullable(null === $default)
561 2
                ->build();
562
        }
563 2
    }
564
565
    /**
566
     * Bulk create multiple fields of different simple types
567
     *
568
     * Always creates nullable fields, if you want to set a default, you must call the type based method
569
     *
570
     * @param array                $fieldToType [
571
     *                                          'fieldName'=>'fieldSimpleType'
572
     *                                          ]
573
     * @param ClassMetadataBuilder $builder
574
     */
575 2
    public static function setSimpleFields(
576
        array $fieldToType,
577
        ClassMetadataBuilder $builder
578
    ): void {
579 2
        foreach ($fieldToType as $field => $type) {
580 2
            $method = "setSimple$type" . 'fields';
581 2
            static::$method([$field], $builder);
582
        }
583 2
    }
584
}
585