Passed
Pull Request — master (#271)
by
unknown
14:18 queued 10:07
created

TDBMDaoGenerator::toPlural()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
rs 10
1
<?php
2
declare(strict_types=1);
3
4
namespace TheCodingMachine\TDBM\Utils;
5
6
use Doctrine\Inflector\Inflector;
7
use Doctrine\DBAL\Schema\Schema;
8
use Doctrine\DBAL\Schema\Table;
9
use Doctrine\DBAL\Types\Type;
10
use Doctrine\Inflector\InflectorFactory;
11
use Psr\Container\ContainerInterface;
12
use TheCodingMachine\TDBM\Schema\ForeignKeys;
13
use TheCodingMachine\TDBM\TDBMService;
14
use Laminas\Code\Generator\AbstractMemberGenerator;
15
use Laminas\Code\Generator\ClassGenerator;
16
use Laminas\Code\Generator\DocBlock\Tag\VarTag;
17
use Laminas\Code\Generator\DocBlockGenerator;
18
use Laminas\Code\Generator\FileGenerator;
19
use Laminas\Code\Generator\MethodGenerator;
20
use Laminas\Code\Generator\ParameterGenerator;
21
use Laminas\Code\Generator\PropertyGenerator;
22
use function str_replace;
23
use TheCodingMachine\TDBM\ConfigurationInterface;
24
use TheCodingMachine\TDBM\TDBMException;
25
use TheCodingMachine\TDBM\TDBMSchemaAnalyzer;
26
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
27
use Symfony\Component\Filesystem\Filesystem;
28
use function strpos;
29
use function substr;
30
use function var_export;
31
use const PHP_EOL;
32
33
/**
34
 * This class generates automatically DAOs and Beans for TDBM.
35
 */
36
class TDBMDaoGenerator
37
{
38
    /**
39
     * @var TDBMSchemaAnalyzer
40
     */
41
    private $tdbmSchemaAnalyzer;
42
43
    /**
44
     * @var GeneratorListenerInterface
45
     */
46
    private $eventDispatcher;
47
48
    /**
49
     * @var NamingStrategyInterface
50
     */
51
    private $namingStrategy;
52
    /**
53
     * @var ConfigurationInterface
54
     */
55
    private $configuration;
56
    /**
57
     * @var Inflector
58
     */
59
    private static $inflector;
60
61
    /**
62
     * Constructor.
63
     *
64
     * @param ConfigurationInterface $configuration
65
     * @param TDBMSchemaAnalyzer $tdbmSchemaAnalyzer
66
     */
67
    public function __construct(ConfigurationInterface $configuration, TDBMSchemaAnalyzer $tdbmSchemaAnalyzer)
68
    {
69
        $this->configuration = $configuration;
70
        $this->tdbmSchemaAnalyzer = $tdbmSchemaAnalyzer;
71
        $this->namingStrategy = $configuration->getNamingStrategy();
72
        $this->eventDispatcher = $configuration->getGeneratorEventDispatcher();
73
    }
74
75
    /**
76
     * Generates all the daos and beans.
77
     *
78
     * @throws TDBMException
79
     */
80
    public function generateAllDaosAndBeans(bool $fromLock = false): void
81
    {
82
        if (!$fromLock) {
83
            $this->tdbmSchemaAnalyzer->generateLockFile();
0 ignored issues
show
Deprecated Code introduced by
The function TheCodingMachine\TDBM\TD...zer::generateLockFile() has been deprecated. ( Ignorable by Annotation )

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

83
            /** @scrutinizer ignore-deprecated */ $this->tdbmSchemaAnalyzer->generateLockFile();
Loading history...
84
        }
85
        $schema = $this->tdbmSchemaAnalyzer->getSchema();
0 ignored issues
show
Deprecated Code introduced by
The function TheCodingMachine\TDBM\TD...maAnalyzer::getSchema() has been deprecated. ( Ignorable by Annotation )

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

85
        $schema = /** @scrutinizer ignore-deprecated */ $this->tdbmSchemaAnalyzer->getSchema();
Loading history...
86
87
        // TODO: check that no class name ends with "Base". Otherwise, there will be name clash.
88
        $tableList = $schema->getTables();
89
90
        // Remove all beans and daos from junction tables
91
        $junctionTables = $this->configuration->getSchemaAnalyzer()->detectJunctionTables(true);
92
        $junctionTableNames = array_map(function (Table $table) {
93
            return $table->getName();
94
        }, $junctionTables);
95
96
        $tableList = array_filter($tableList, function (Table $table) use ($junctionTableNames) {
97
            return !in_array($table->getName(), $junctionTableNames, true);
98
        });
99
100
        $this->cleanUpGenerated();
101
102
        $beanDescriptors = [];
103
104
        $beanRegistry = new BeanRegistry($this->configuration, $schema, $this->tdbmSchemaAnalyzer, $this->namingStrategy);
105
        foreach ($tableList as $table) {
106
            $beanDescriptors[] = $beanRegistry->addBeanForTable($table);
107
        }
108
        foreach ($beanDescriptors as $beanDescriptor) {
109
            $beanDescriptor->initBeanPropertyDescriptors();
110
        }
111
        foreach ($beanDescriptors as $beanDescriptor) {
112
            $this->generateBean($beanDescriptor);
113
            $this->generateDao($beanDescriptor);
114
            $this->generateResultIterator($beanDescriptor);
115
        }
116
117
        $this->generateFactory($beanDescriptors);
118
119
        // Let's call the list of listeners
120
        $this->eventDispatcher->onGenerate($this->configuration, $beanDescriptors);
121
    }
122
123
    /**
124
     * Removes all files from the Generated folders.
125
     * This is a way to ensure that when a table is deleted, the matching bean/dao are deleted.
126
     * Note: only abstract generated classes are deleted. We do not delete the code that might have been customized
127
     * by the user. The user will need to delete this code him/herself
128
     */
129
    private function cleanUpGenerated(): void
130
    {
131
        $generatedBeanDir = $this->configuration->getPathFinder()->getPath($this->configuration->getBeanNamespace().'\\Generated\\Xxx')->getPath();
132
        $this->deleteAllPhpFiles($generatedBeanDir);
133
134
        $generatedDaoDir = $this->configuration->getPathFinder()->getPath($this->configuration->getDaoNamespace().'\\Generated\\Xxx')->getPath();
135
        $this->deleteAllPhpFiles($generatedDaoDir);
136
137
        $generatedResultIteratorDir = $this->configuration->getPathFinder()->getPath($this->configuration->getResultIteratorNamespace().'\\Generated\\Xxx')->getPath();
138
        $this->deleteAllPhpFiles($generatedResultIteratorDir);
139
    }
140
141
    private function deleteAllPhpFiles(string $directory): void
142
    {
143
        $files = glob($directory.'/*.php', GLOB_NOSORT);
144
        if ($files === false) {
145
            return;
146
        }
147
        $fileSystem = new Filesystem();
148
        $fileSystem->remove($files);
149
    }
150
151
    /**
152
     * Writes the PHP bean file with all getters and setters from the table passed in parameter.
153
     *
154
     * @param BeanDescriptor  $beanDescriptor
155
     *
156
     * @throws TDBMException
157
     */
158
    public function generateBean(BeanDescriptor $beanDescriptor): void
159
    {
160
        $className = $beanDescriptor->getBeanClassName();
161
        $baseClassName = $beanDescriptor->getBaseBeanClassName();
162
        $table = $beanDescriptor->getTable();
163
        $beannamespace = $this->configuration->getBeanNamespace();
164
        $file = $beanDescriptor->generatePhpCode();
165
        if ($file === null) {
166
            return;
167
        }
168
169
        $possibleBaseFileName = $this->configuration->getPathFinder()->getPath($beannamespace.'\\Generated\\'.$baseClassName)->getPathname();
170
171
        $fileContent = $file->generate();
172
173
        // Hard code PSR-2 fix
174
        $fileContent = $this->psr2Fix($fileContent);
175
        // Add the declare strict-types directive
176
        $commentEnd = strpos($fileContent, ' */') + 3;
177
        $fileContent = substr($fileContent, 0, $commentEnd) . "\n\ndeclare(strict_types=1);" . substr($fileContent, $commentEnd + 1);
178
179
        $this->dumpFile($possibleBaseFileName, $fileContent);
180
181
        $possibleFileName = $this->configuration->getPathFinder()->getPath($beannamespace.'\\'.$className)->getPathname();
182
183
        if (!file_exists($possibleFileName)) {
184
            $tableName = $table->getName();
185
            $str = "<?php
186
/*
187
 * This file has been automatically generated by TDBM.
188
 * You can edit this file as it will not be overwritten.
189
 */
190
191
declare(strict_types=1);
192
193
namespace {$beannamespace};
194
195
use {$beannamespace}\\Generated\\{$baseClassName};
196
197
/**
198
 * The $className class maps the '$tableName' table in database.
199
 */
200
class $className extends $baseClassName
201
{
202
}
203
";
204
205
            $this->dumpFile($possibleFileName, $str);
206
        }
207
    }
208
209
    /**
210
     * Writes the PHP bean DAO with simple functions to create/get/save objects.
211
     *
212
     * @param BeanDescriptor  $beanDescriptor
213
     *
214
     * @throws TDBMException
215
     */
216
    private function generateDao(BeanDescriptor $beanDescriptor): void
217
    {
218
        $className = $beanDescriptor->getDaoClassName();
219
        $baseClassName = $beanDescriptor->getBaseDaoClassName();
220
        $beanClassName = $beanDescriptor->getBeanClassName();
221
        $table = $beanDescriptor->getTable();
222
        $file = $beanDescriptor->generateDaoPhpCode();
223
        if ($file === null) {
224
            return;
225
        }
226
        $daonamespace = $this->configuration->getDaoNamespace();
227
        $tableName = $table->getName();
228
229
        $beanClassWithoutNameSpace = $beanClassName;
230
231
        $possibleBaseFileName = $this->configuration->getPathFinder()->getPath($daonamespace.'\\Generated\\'.$baseClassName)->getPathname();
232
233
        $fileContent = $file->generate();
234
235
        // Hard code PSR-2 fix
236
        $fileContent = $this->psr2Fix($fileContent);
237
        // Add the declare strict-types directive
238
        $commentEnd = strpos($fileContent, ' */') + 3;
239
        $fileContent = substr($fileContent, 0, $commentEnd) . "\n\ndeclare(strict_types=1);" . substr($fileContent, $commentEnd + 1);
240
241
        $this->dumpFile($possibleBaseFileName, $fileContent);
242
243
244
        $possibleFileName = $this->configuration->getPathFinder()->getPath($daonamespace.'\\'.$className)->getPathname();
245
246
        // Now, let's generate the "editable" class
247
        if (!file_exists($possibleFileName)) {
248
            $str = "<?php
249
/*
250
 * This file has been automatically generated by TDBM.
251
 * You can edit this file as it will not be overwritten.
252
 */
253
254
declare(strict_types=1);
255
256
namespace {$daonamespace};
257
258
use {$daonamespace}\\Generated\\{$baseClassName};
259
260
/**
261
 * The $className class will maintain the persistence of $beanClassWithoutNameSpace class into the $tableName table.
262
 */
263
class $className extends $baseClassName
264
{
265
}
266
";
267
            $this->dumpFile($possibleFileName, $str);
268
        }
269
    }
270
271
    /**
272
     * Fixes PSR-2 for files generated by Zend-Code
273
     */
274
    private function psr2Fix(string $content): string
275
    {
276
        // Removes the extra blank line at the end (before: `\n\n`, after: `\n`)
277
        return rtrim($content, PHP_EOL) . PHP_EOL;
278
    }
279
280
    /**
281
     * Writes the PHP ResultIterator file with typed accessors.
282
     */
283
    private function generateResultIterator(BeanDescriptor $beanDescriptor) : void
284
    {
285
        $resultIteratorClassName = $beanDescriptor->getResultIteratorClassName();
286
        $resultIteratorBaseClassName = $beanDescriptor->getBaseResultIteratorClassName();
287
        $resultIteratorNamespace = $this->configuration->getResultIteratorNamespace();
288
        $resultIteratorBaseNamespace = $resultIteratorNamespace . '\\Generated';
289
        $beanClassWithoutNameSpace = $beanDescriptor->getBeanClassName();
290
        $file = $beanDescriptor->generateResultIteratorPhpCode();
291
        if ($file === null) {
292
            return;
293
        }
294
295
        $fileContent = $this->psr2Fix($file->generate());
296
        $commentEnd = strpos($fileContent, ' */') + 3;
297
        $fileContent = substr($fileContent, 0, $commentEnd) . "\n\ndeclare(strict_types=1);" . substr($fileContent, $commentEnd + 1);
298
299
        $baseResultIteratorFilePath = $this->configuration->getPathFinder()->getPath($resultIteratorBaseNamespace.'\\'.$resultIteratorBaseClassName)->getPathname();
300
        $this->dumpFile($baseResultIteratorFilePath, $fileContent);
301
302
        $resultIteratorFilePath = $this->configuration->getPathFinder()->getPath($resultIteratorNamespace.'\\'.$resultIteratorClassName)->getPathname();
303
        // Now, let's generate the "editable" class
304
        if (!file_exists($resultIteratorFilePath)) {
305
            $str = "<?php
306
/*
307
 * This file has been automatically generated by TDBM.
308
 * You can edit this file as it will not be overwritten.
309
 */
310
311
declare(strict_types=1);
312
313
namespace {$resultIteratorNamespace};
314
315
use {$resultIteratorBaseNamespace}\\{$resultIteratorBaseClassName};
316
317
/**
318
 * The $resultIteratorClassName class will iterate over results of $beanClassWithoutNameSpace class.
319
 */
320
class $resultIteratorClassName extends $resultIteratorBaseClassName
321
{
322
}
323
";
324
            $this->dumpFile($resultIteratorFilePath, $str);
325
        }
326
    }
327
328
    /**
329
     * Generates the factory bean.
330
     *
331
     * @param BeanDescriptor[] $beanDescriptors
332
     * @throws TDBMException
333
     */
334
    private function generateFactory(array $beanDescriptors) : void
335
    {
336
        $daoNamespace = $this->configuration->getDaoNamespace();
337
        $daoFactoryClassName = $this->namingStrategy->getDaoFactoryClassName();
338
339
        $file = new FileGenerator();
340
        $file->setDocBlock(
341
            new DocBlockGenerator(
342
                <<<DOC
343
This file has been automatically generated by TDBM.
344
DO NOT edit this file, as it might be overwritten.
345
DOC
346
            )
347
        );
348
        $class = new ClassGenerator();
349
        $file->setClass($class);
350
        $class->setName($daoFactoryClassName);
351
        $file->setNamespace($daoNamespace.'\\Generated');
352
353
        $class->setDocBlock(new DocBlockGenerator("The $daoFactoryClassName provides an easy access to all DAOs generated by TDBM."));
354
355
        $containerProperty = new PropertyGenerator('container');
356
        $containerProperty->setVisibility(AbstractMemberGenerator::VISIBILITY_PRIVATE);
357
        $containerProperty->setDocBlock(new DocBlockGenerator(null, null, [new VarTag(null, ['\\'.ContainerInterface::class])]));
358
        $class->addPropertyFromGenerator($containerProperty);
359
360
        $constructorMethod = new MethodGenerator(
361
            '__construct',
362
            [ new ParameterGenerator('container', ContainerInterface::class) ],
363
            MethodGenerator::FLAG_PUBLIC,
364
            '$this->container = $container;'
365
        );
366
        $constructorMethod = $this->configuration->getCodeGeneratorListener()->onDaoFactoryConstructorGenerated($constructorMethod, $beanDescriptors, $this->configuration, $class);
367
        if ($constructorMethod !== null) {
368
            $class->addMethodFromGenerator($constructorMethod);
369
        }
370
371
        // For each table, let's write a property.
372
        foreach ($beanDescriptors as $beanDescriptor) {
373
            $daoClassName = $beanDescriptor->getDaoClassName();
374
            $daoInstanceName = self::toVariableName($daoClassName);
375
376
            $daoInstanceProperty = new PropertyGenerator($daoInstanceName);
377
            $daoInstanceProperty->setVisibility(AbstractMemberGenerator::VISIBILITY_PRIVATE);
378
            $daoInstanceProperty->setDocBlock(new DocBlockGenerator(null, null, [new VarTag(null, ['\\' . $daoNamespace . '\\' . $daoClassName, 'null'])]));
379
            $class->addPropertyFromGenerator($daoInstanceProperty);
380
381
            $fullClassNameVarExport = var_export($daoNamespace.'\\'.$daoClassName, true);
382
            $getterBody = <<<BODY
383
if (!\$this->$daoInstanceName) {
384
    \$this->$daoInstanceName = \$this->container->get($fullClassNameVarExport);
385
}
386
387
return \$this->$daoInstanceName;
388
BODY;
389
390
            $getterMethod = new MethodGenerator(
391
                'get' . $daoClassName,
392
                [],
393
                MethodGenerator::FLAG_PUBLIC,
394
                $getterBody
395
            );
396
            $getterMethod->setReturnType($daoNamespace.'\\'.$daoClassName);
397
            $getterMethod = $this->configuration->getCodeGeneratorListener()->onDaoFactoryGetterGenerated($getterMethod, $beanDescriptor, $this->configuration, $class);
398
            if ($getterMethod !== null) {
399
                $class->addMethodFromGenerator($getterMethod);
400
            }
401
402
            $setterMethod = new MethodGenerator(
403
                'set' . $daoClassName,
404
                [new ParameterGenerator($daoInstanceName, '\\' . $daoNamespace . '\\' . $daoClassName)],
405
                MethodGenerator::FLAG_PUBLIC,
406
                '$this->' . $daoInstanceName . ' = $' . $daoInstanceName . ';'
407
            );
408
            $setterMethod->setReturnType('void');
409
            $setterMethod = $this->configuration->getCodeGeneratorListener()->onDaoFactorySetterGenerated($setterMethod, $beanDescriptor, $this->configuration, $class);
410
            if ($setterMethod !== null) {
411
                $class->addMethodFromGenerator($setterMethod);
412
            }
413
        }
414
415
        $file = $this->configuration->getCodeGeneratorListener()->onDaoFactoryGenerated($file, $beanDescriptors, $this->configuration);
416
417
        if ($file !== null) {
418
            $possibleFileName = $this->configuration->getPathFinder()->getPath($daoNamespace.'\\Generated\\'.$daoFactoryClassName)->getPathname();
419
420
            $fileContent = $file->generate();
421
422
            // Hard code PSR-2 fix
423
            $fileContent = $this->psr2Fix($fileContent);
424
            // Add the declare strict-types directive
425
            $commentEnd = strpos($fileContent, ' */') + 3;
426
            $fileContent = substr($fileContent, 0, $commentEnd) . "\n\ndeclare(strict_types=1);" . substr($fileContent, $commentEnd + 1);
427
428
            $this->dumpFile($possibleFileName, $fileContent);
429
        }
430
    }
431
432
    /**
433
     * Transforms a string to camelCase (except the first letter will be uppercase too).
434
     * Underscores and spaces are removed and the first letter after the underscore is uppercased.
435
     * Quoting is removed if present.
436
     *
437
     * @param string $str
438
     *
439
     * @return string
440
     */
441
    public static function toCamelCase(string $str) : string
442
    {
443
        $str = str_replace(array('`', '"', '[', ']'), '', $str);
444
445
        $str = strtoupper(substr($str, 0, 1)).substr($str, 1);
446
        while (true) {
447
            $pos = strpos($str, '_');
448
            if ($pos === false) {
449
                $pos = strpos($str, ' ');
450
                if ($pos === false) {
451
                    break;
452
                }
453
            }
454
455
            $before = substr($str, 0, $pos);
456
            $after = substr($str, $pos + 1);
457
            $str = $before.strtoupper(substr($after, 0, 1)).substr($after, 1);
458
        }
459
460
        return $str;
461
    }
462
463
    /**
464
     * Tries to put string to the singular form (if it is plural).
465
     * We assume the table names are in english.
466
     *
467
     * @param string $str
468
     *
469
     * @return string
470
     */
471
    public static function toSingular(string $str): string
472
    {
473
        if (self::$inflector === null) {
474
            self::$inflector = InflectorFactory::create()->build();
475
        }
476
477
        return self::$inflector->singularize($str);
478
    }
479
480
    /**
481
     * Tries to put string to the plural form (if it is singular).
482
     * We assume the string is in english.
483
     */
484
    public static function toPlural(string $str): string
485
    {
486
        if (self::$inflector === null) {
487
            self::$inflector = InflectorFactory::create()->build();
488
        }
489
490
        return self::$inflector->pluralize($str);
491
    }
492
493
    /**
494
     * Put the first letter of the string in lower case.
495
     * Very useful to transform a class name into a variable name.
496
     *
497
     * @param string $str
498
     *
499
     * @return string
500
     */
501
    public static function toVariableName(string $str): string
502
    {
503
        return strtolower(substr($str, 0, 1)).substr($str, 1);
504
    }
505
506
    /**
507
     * Ensures the file passed in parameter can be written in its directory.
508
     *
509
     * @param string $fileName
510
     *
511
     * @throws TDBMException
512
     */
513
    private function ensureDirectoryExist(string $fileName): void
514
    {
515
        $dirName = dirname($fileName);
516
        if (!file_exists($dirName)) {
517
            $old = umask(0);
518
            $result = mkdir($dirName, 0775, true);
519
            umask($old);
520
            if ($result === false) {
521
                throw new TDBMException("Unable to create directory: '".$dirName."'.");
522
            }
523
        }
524
    }
525
526
    private function dumpFile(string $fileName, string $content) : void
527
    {
528
        $this->ensureDirectoryExist($fileName);
529
        $fileSystem = new Filesystem();
530
        $fileSystem->dumpFile($fileName, $content);
531
        @chmod($fileName, 0664);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

531
        /** @scrutinizer ignore-unhandled */ @chmod($fileName, 0664);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
532
    }
533
534
    /**
535
     * Transforms a DBAL type into a PHP type (for PHPDoc purpose).
536
     *
537
     * @param Type $type The DBAL type
538
     *
539
     * @return string The PHP type
540
     */
541
    public static function dbalTypeToPhpType(Type $type) : string
542
    {
543
        $map = [
544
            Type::TARRAY => 'array',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::TARRAY has been deprecated: Use {@see Types::ARRAY} instead. ( Ignorable by Annotation )

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

544
            /** @scrutinizer ignore-deprecated */ Type::TARRAY => 'array',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
545
            Type::SIMPLE_ARRAY => 'array',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::SIMPLE_ARRAY has been deprecated: Use {@see Types::SIMPLE_ARRAY} instead. ( Ignorable by Annotation )

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

545
            /** @scrutinizer ignore-deprecated */ Type::SIMPLE_ARRAY => 'array',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
546
            'json' => 'array',  // 'json' is supported from Doctrine DBAL 2.6 only.
547
            Type::JSON_ARRAY => 'array',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::JSON_ARRAY has been deprecated: Use {@see Types::JSON_ARRAY} instead. ( Ignorable by Annotation )

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

547
            /** @scrutinizer ignore-deprecated */ Type::JSON_ARRAY => 'array',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
548
            Type::BIGINT => 'string',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::BIGINT has been deprecated: Use {@see Types::BIGINT} instead. ( Ignorable by Annotation )

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

548
            /** @scrutinizer ignore-deprecated */ Type::BIGINT => 'string',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
549
            Type::BOOLEAN => 'bool',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::BOOLEAN has been deprecated: Use {@see Types::BOOLEAN} instead. ( Ignorable by Annotation )

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

549
            /** @scrutinizer ignore-deprecated */ Type::BOOLEAN => 'bool',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
550
            Type::DATETIME_IMMUTABLE => '\DateTimeImmutable',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::DATETIME_IMMUTABLE has been deprecated: Use {@see Types::DATETIME_IMMUTABLE} instead. ( Ignorable by Annotation )

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

550
            /** @scrutinizer ignore-deprecated */ Type::DATETIME_IMMUTABLE => '\DateTimeImmutable',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
551
            Type::DATETIMETZ_IMMUTABLE => '\DateTimeImmutable',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::DATETIMETZ_IMMUTABLE has been deprecated: Use {@see Types::DATETIMETZ_IMMUTABLE} instead. ( Ignorable by Annotation )

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

551
            /** @scrutinizer ignore-deprecated */ Type::DATETIMETZ_IMMUTABLE => '\DateTimeImmutable',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
552
            Type::DATE_IMMUTABLE => '\DateTimeImmutable',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::DATE_IMMUTABLE has been deprecated: Use {@see Types::DATE_IMMUTABLE} instead. ( Ignorable by Annotation )

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

552
            /** @scrutinizer ignore-deprecated */ Type::DATE_IMMUTABLE => '\DateTimeImmutable',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
553
            Type::TIME_IMMUTABLE => '\DateTimeImmutable',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::TIME_IMMUTABLE has been deprecated: Use {@see Types::TIME_IMMUTABLE} instead. ( Ignorable by Annotation )

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

553
            /** @scrutinizer ignore-deprecated */ Type::TIME_IMMUTABLE => '\DateTimeImmutable',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
554
            Type::DECIMAL => 'string',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::DECIMAL has been deprecated: Use {@see Types::DECIMAL} instead. ( Ignorable by Annotation )

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

554
            /** @scrutinizer ignore-deprecated */ Type::DECIMAL => 'string',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
555
            Type::INTEGER => 'int',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::INTEGER has been deprecated: Use {@see Types::INTEGER} instead. ( Ignorable by Annotation )

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

555
            /** @scrutinizer ignore-deprecated */ Type::INTEGER => 'int',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
556
            Type::OBJECT => 'string',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::OBJECT has been deprecated: Use {@see Types::OBJECT} instead. ( Ignorable by Annotation )

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

556
            /** @scrutinizer ignore-deprecated */ Type::OBJECT => 'string',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
557
            Type::SMALLINT => 'int',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::SMALLINT has been deprecated: Use {@see Types::SMALLINT} instead. ( Ignorable by Annotation )

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

557
            /** @scrutinizer ignore-deprecated */ Type::SMALLINT => 'int',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
558
            Type::STRING => 'string',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::STRING has been deprecated: Use {@see Types::STRING} instead. ( Ignorable by Annotation )

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

558
            /** @scrutinizer ignore-deprecated */ Type::STRING => 'string',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
559
            Type::TEXT => 'string',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::TEXT has been deprecated: Use {@see Types::TEXT} instead. ( Ignorable by Annotation )

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

559
            /** @scrutinizer ignore-deprecated */ Type::TEXT => 'string',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
560
            Type::BINARY => 'resource',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::BINARY has been deprecated: Use {@see Types::BINARY} instead. ( Ignorable by Annotation )

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

560
            /** @scrutinizer ignore-deprecated */ Type::BINARY => 'resource',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
561
            Type::BLOB => 'resource',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::BLOB has been deprecated: Use {@see Types::BLOB} instead. ( Ignorable by Annotation )

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

561
            /** @scrutinizer ignore-deprecated */ Type::BLOB => 'resource',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
562
            Type::FLOAT => 'float',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::FLOAT has been deprecated: Use {@see Types::FLOAT} instead. ( Ignorable by Annotation )

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

562
            /** @scrutinizer ignore-deprecated */ Type::FLOAT => 'float',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
563
            Type::GUID => 'string',
0 ignored issues
show
Deprecated Code introduced by
The constant Doctrine\DBAL\Types\Type::GUID has been deprecated: Use {@see Types::GUID} instead. ( Ignorable by Annotation )

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

563
            /** @scrutinizer ignore-deprecated */ Type::GUID => 'string',

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
564
        ];
565
566
        return $map[$type->getName()] ?? $type->getName();
567
    }
568
569
    /**
570
     * @param Table $table
571
     * @return string[]
572
     * @throws TDBMException
573
     */
574
    public static function getPrimaryKeyColumnsOrFail(Table $table): array
575
    {
576
        if ($table->getPrimaryKey() === null) {
577
            // Security check: a table MUST have a primary key
578
            throw new TDBMException(sprintf('Table "%s" does not have any primary key', $table->getName()));
579
        }
580
        return $table->getPrimaryKey()->getUnquotedColumns();
581
    }
582
}
583