Passed
Push — 4.3 ( 06c551...66bb88 )
by David
01:20
created

TDBMDaoGenerator::dumpFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 2
1
<?php
2
3
namespace Mouf\Database\TDBM\Utils;
4
5
use Doctrine\Common\Inflector\Inflector;
6
use Doctrine\DBAL\Schema\Schema;
7
use Doctrine\DBAL\Schema\Table;
8
use Doctrine\DBAL\Types\Type;
9
use Mouf\Database\TDBM\ConfigurationInterface;
10
use Mouf\Database\TDBM\TDBMException;
11
use Mouf\Database\TDBM\TDBMSchemaAnalyzer;
12
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
13
use Symfony\Component\Filesystem\Filesystem;
14
15
/**
16
 * This class generates automatically DAOs and Beans for TDBM.
17
 */
18
class TDBMDaoGenerator
19
{
20
    /**
21
     * @var Schema
22
     */
23
    private $schema;
24
25
    /**
26
     * Name of composer file.
27
     *
28
     * @var string
29
     */
30
    private $composerFile;
31
32
    /**
33
     * @var TDBMSchemaAnalyzer
34
     */
35
    private $tdbmSchemaAnalyzer;
36
37
    /**
38
     * @var GeneratorListenerInterface
39
     */
40
    private $eventDispatcher;
41
42
    /**
43
     * @var NamingStrategyInterface
44
     */
45
    private $namingStrategy;
46
    /**
47
     * @var ConfigurationInterface
48
     */
49
    private $configuration;
50
51
    /**
52
     * Constructor.
53
     *
54
     * @param ConfigurationInterface $configuration
55
     * @param TDBMSchemaAnalyzer $tdbmSchemaAnalyzer
56
     */
57
    public function __construct(ConfigurationInterface $configuration, TDBMSchemaAnalyzer $tdbmSchemaAnalyzer)
58
    {
59
        $this->configuration = $configuration;
60
        $this->schema = $tdbmSchemaAnalyzer->getSchema();
61
        $this->tdbmSchemaAnalyzer = $tdbmSchemaAnalyzer;
62
        $this->namingStrategy = $configuration->getNamingStrategy();
63
        $this->eventDispatcher = $configuration->getGeneratorEventDispatcher();
64
    }
65
66
    /**
67
     * Generates all the daos and beans.
68
     *
69
     * @throws TDBMException
70
     */
71
    public function generateAllDaosAndBeans(): void
72
    {
73
        // TODO: check that no class name ends with "Base". Otherwise, there will be name clash.
74
75
        $tableList = $this->schema->getTables();
76
77
        // Remove all beans and daos from junction tables
78
        $junctionTables = $this->configuration->getSchemaAnalyzer()->detectJunctionTables(true);
79
        $junctionTableNames = array_map(function (Table $table) {
80
            return $table->getName();
81
        }, $junctionTables);
82
83
        $tableList = array_filter($tableList, function (Table $table) use ($junctionTableNames) {
84
            return !in_array($table->getName(), $junctionTableNames);
85
        });
86
87
        $beanDescriptors = [];
88
89
        foreach ($tableList as $table) {
90
            $beanDescriptors[] = $this->generateDaoAndBean($table);
91
        }
92
93
94
        $this->generateFactory($tableList);
95
96
        // Let's call the list of listeners
97
        $this->eventDispatcher->onGenerate($this->configuration, $beanDescriptors);
98
    }
99
100
    /**
101
     * Generates in one method call the daos and the beans for one table.
102
     *
103
     * @param Table $table
104
     *
105
     * @return BeanDescriptor
106
     * @throws TDBMException
107
     */
108
    private function generateDaoAndBean(Table $table) : BeanDescriptor
109
    {
110
        $tableName = $table->getName();
111
        $daoName = $this->namingStrategy->getDaoClassName($tableName);
112
        $beanName = $this->namingStrategy->getBeanClassName($tableName);
113
        $baseBeanName = $this->namingStrategy->getBaseBeanClassName($tableName);
114
        $baseDaoName = $this->namingStrategy->getBaseDaoClassName($tableName);
115
116
        $beanDescriptor = new BeanDescriptor($table, $this->configuration->getSchemaAnalyzer(), $this->schema, $this->tdbmSchemaAnalyzer, $this->namingStrategy);
117
        $this->generateBean($beanDescriptor, $beanName, $baseBeanName, $table);
118
        $this->generateDao($beanDescriptor, $daoName, $baseDaoName, $beanName, $table);
119
        return $beanDescriptor;
120
    }
121
122
    /**
123
     * Writes the PHP bean file with all getters and setters from the table passed in parameter.
124
     *
125
     * @param BeanDescriptor  $beanDescriptor
126
     * @param string          $className       The name of the class
127
     * @param string          $baseClassName   The name of the base class which will be extended (name only, no directory)
128
     * @param Table           $table           The table
129
     *
130
     * @throws TDBMException
131
     */
132
    public function generateBean(BeanDescriptor $beanDescriptor, $className, $baseClassName, Table $table)
133
    {
134
        $beannamespace = $this->configuration->getBeanNamespace();
135
        $str = $beanDescriptor->generatePhpCode($beannamespace);
136
137
        $possibleBaseFileName = $this->configuration->getPathFinder()->getPath($beannamespace.'\\Generated\\'.$baseClassName)->getPathname();
138
139
        $this->dumpFile($possibleBaseFileName, $str);
140
141
        $possibleFileName = $this->configuration->getPathFinder()->getPath($beannamespace.'\\'.$className)->getPathname();
142
143
        if (!file_exists($possibleFileName)) {
144
            $tableName = $table->getName();
145
            $str = "<?php
146
/*
147
 * This file has been automatically generated by TDBM.
148
 * You can edit this file as it will not be overwritten.
149
 */
150
151
namespace {$beannamespace};
152
153
use {$beannamespace}\\Generated\\{$baseClassName};
154
155
/**
156
 * The $className class maps the '$tableName' table in database.
157
 */
158
class $className extends $baseClassName
159
{
160
}
161
";
162
163
            $this->dumpFile($possibleFileName, $str);
164
        }
165
    }
166
167
    /**
168
     * Tries to find a @defaultSort annotation in one of the columns.
169
     *
170
     * @param Table $table
171
     *
172
     * @return array First item: column name, Second item: column order (asc/desc)
173
     */
174
    private function getDefaultSortColumnFromAnnotation(Table $table)
175
    {
176
        $defaultSort = null;
177
        $defaultSortDirection = null;
178
        foreach ($table->getColumns() as $column) {
179
            $comments = $column->getComment();
180
            $matches = [];
181
            if (preg_match('/@defaultSort(\((desc|asc)\))*/', $comments, $matches) != 0) {
182
                $defaultSort = $column->getName();
183
                if (count($matches) === 3) {
184
                    $defaultSortDirection = $matches[2];
185
                } else {
186
                    $defaultSortDirection = 'ASC';
187
                }
188
            }
189
        }
190
191
        return [$defaultSort, $defaultSortDirection];
192
    }
193
194
    /**
195
     * Writes the PHP bean DAO with simple functions to create/get/save objects.
196
     *
197
     * @param BeanDescriptor  $beanDescriptor
198
     * @param string          $className       The name of the class
199
     * @param string          $baseClassName
200
     * @param string          $beanClassName
201
     * @param Table           $table
202
     *
203
     * @throws TDBMException
204
     */
205
    private function generateDao(BeanDescriptor $beanDescriptor, string $className, string $baseClassName, string $beanClassName, Table $table)
206
    {
207
        $daonamespace = $this->configuration->getDaoNamespace();
208
        $beannamespace = $this->configuration->getBeanNamespace();
209
        $tableName = $table->getName();
210
        $primaryKeyColumns = $table->getPrimaryKeyColumns();
211
212
        list($defaultSort, $defaultSortDirection) = $this->getDefaultSortColumnFromAnnotation($table);
213
214
        // FIXME: lowercase tables with _ in the name should work!
215
        $tableCamel = self::toSingular(self::toCamelCase($tableName));
216
217
        $beanClassWithoutNameSpace = $beanClassName;
218
        $beanClassName = $beannamespace.'\\'.$beanClassName;
219
220
        list($usedBeans, $findByDaoCode) = $beanDescriptor->generateFindByDaoCode($beannamespace, $beanClassWithoutNameSpace);
221
222
        $usedBeans[] = $beanClassName;
223
        // Let's suppress duplicates in used beans (if any)
224
        $usedBeans = array_flip(array_flip($usedBeans));
225
        $useStatements = array_map(function ($usedBean) {
226
            return "use $usedBean;\n";
227
        }, $usedBeans);
228
229
        $str = "<?php
230
231
/*
232
 * This file has been automatically generated by TDBM.
233
 * DO NOT edit this file, as it might be overwritten.
234
 * If you need to perform changes, edit the $className class instead!
235
 */
236
237
namespace {$daonamespace}\\Generated;
238
239
use Mouf\\Database\\TDBM\\TDBMService;
240
use Mouf\\Database\\TDBM\\ResultIterator;
241
use Mouf\\Database\\TDBM\\ArrayIterator;
242
".implode('', $useStatements)."
243
/**
244
 * The $baseClassName class will maintain the persistence of $beanClassWithoutNameSpace class into the $tableName table.
245
 *
246
 */
247
class $baseClassName
248
{
249
250
    /**
251
     * @var TDBMService
252
     */
253
    protected \$tdbmService;
254
255
    /**
256
     * The default sort column.
257
     *
258
     * @var string
259
     */
260
    private \$defaultSort = ".($defaultSort ? "'$defaultSort'" : 'null').';
261
262
    /**
263
     * The default sort direction.
264
     *
265
     * @var string
266
     */
267
    private $defaultDirection = '.($defaultSort && $defaultSortDirection ? "'$defaultSortDirection'" : "'asc'").";
0 ignored issues
show
Bug Best Practice introduced by
The expression $defaultSort of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $defaultSortDirection of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
268
269
    /**
270
     * Sets the TDBM service used by this DAO.
271
     *
272
     * @param TDBMService \$tdbmService
273
     */
274
    public function __construct(TDBMService \$tdbmService)
275
    {
276
        \$this->tdbmService = \$tdbmService;
277
    }
278
279
    /**
280
     * Persist the $beanClassWithoutNameSpace instance.
281
     *
282
     * @param $beanClassWithoutNameSpace \$obj The bean to save.
283
     */
284
    public function save($beanClassWithoutNameSpace \$obj)
285
    {
286
        \$this->tdbmService->save(\$obj);
287
    }
288
289
    /**
290
     * Get all $tableCamel records.
291
     *
292
     * @return {$beanClassWithoutNameSpace}[]|ResultIterator|ResultArray
293
     */
294
    public function findAll() : iterable
295
    {
296
        if (\$this->defaultSort) {
297
            \$orderBy = '$tableName.'.\$this->defaultSort.' '.\$this->defaultDirection;
298
        } else {
299
            \$orderBy = null;
300
        }
301
        return \$this->tdbmService->findObjects('$tableName', null, [], \$orderBy);
302
    }
303
    ";
304
305
        if (count($primaryKeyColumns) === 1) {
306
            $primaryKeyColumn = $primaryKeyColumns[0];
307
            $primaryKeyPhpType = self::dbalTypeToPhpType($table->getColumn($primaryKeyColumn)->getType());
308
            $str .= "
309
    /**
310
     * Get $beanClassWithoutNameSpace specified by its ID (its primary key)
311
     * If the primary key does not exist, an exception is thrown.
312
     *
313
     * @param string|int \$id
314
     * @param bool \$lazyLoading If set to true, the object will not be loaded right away. Instead, it will be loaded when you first try to access a method of the object.
315
     * @return $beanClassWithoutNameSpace
316
     * @throws TDBMException
317
     */
318
    public function getById($primaryKeyPhpType \$id, \$lazyLoading = false) : $beanClassWithoutNameSpace
319
    {
320
        return \$this->tdbmService->findObjectByPk('$tableName', ['$primaryKeyColumn' => \$id], [], \$lazyLoading);
321
    }
322
    ";
323
        }
324
        $str .= "
325
    /**
326
     * Deletes the $beanClassWithoutNameSpace passed in parameter.
327
     *
328
     * @param $beanClassWithoutNameSpace \$obj object to delete
329
     * @param bool \$cascade if true, it will delete all object linked to \$obj
330
     */
331
    public function delete($beanClassWithoutNameSpace \$obj, \$cascade = false) : void
332
    {
333
        if (\$cascade === true) {
334
            \$this->tdbmService->deleteCascade(\$obj);
335
        } else {
336
            \$this->tdbmService->delete(\$obj);
337
        }
338
    }
339
340
341
    /**
342
     * Get a list of $beanClassWithoutNameSpace specified by its filters.
343
     *
344
     * @param mixed \$filter The filter bag (see TDBMService::findObjects for complete description)
345
     * @param array \$parameters The parameters associated with the filter
346
     * @param mixed \$orderBy The order string
347
     * @param array \$additionalTablesFetch A list of additional tables to fetch (for performance improvement)
348
     * @param int \$mode Either TDBMService::MODE_ARRAY or TDBMService::MODE_CURSOR (for large datasets). Defaults to TDBMService::MODE_ARRAY.
349
     * @return {$beanClassWithoutNameSpace}[]|ResultIterator|ResultArray
350
     */
351
    protected function find(\$filter = null, array \$parameters = [], \$orderBy=null, array \$additionalTablesFetch = [], \$mode = null) : iterable
352
    {
353
        if (\$this->defaultSort && \$orderBy == null) {
354
            \$orderBy = '$tableName.'.\$this->defaultSort.' '.\$this->defaultDirection;
355
        }
356
        return \$this->tdbmService->findObjects('$tableName', \$filter, \$parameters, \$orderBy, \$additionalTablesFetch, \$mode);
357
    }
358
359
    /**
360
     * Get a list of $beanClassWithoutNameSpace specified by its filters.
361
     * Unlike the `find` method that guesses the FROM part of the statement, here you can pass the \$from part.
362
     *
363
     * You should not put an alias on the main table name. So your \$from variable should look like:
364
     *
365
     *   \"$tableName JOIN ... ON ...\"
366
     *
367
     * @param string \$from The sql from statement
368
     * @param mixed \$filter The filter bag (see TDBMService::findObjects for complete description)
369
     * @param array \$parameters The parameters associated with the filter
370
     * @param mixed \$orderBy The order string
371
     * @param int \$mode Either TDBMService::MODE_ARRAY or TDBMService::MODE_CURSOR (for large datasets). Defaults to TDBMService::MODE_ARRAY.
372
     * @return {$beanClassWithoutNameSpace}[]|ResultIterator|ResultArray
373
     */
374
    protected function findFromSql(\$from, \$filter = null, array \$parameters = [], \$orderBy = null, \$mode = null) : iterable
375
    {
376
        if (\$this->defaultSort && \$orderBy == null) {
377
            \$orderBy = '$tableName.'.\$this->defaultSort.' '.\$this->defaultDirection;
378
        }
379
        return \$this->tdbmService->findObjectsFromSql('$tableName', \$from, \$filter, \$parameters, \$orderBy, \$mode);
380
    }
381
382
    /**
383
     * Get a single $beanClassWithoutNameSpace specified by its filters.
384
     *
385
     * @param mixed \$filter The filter bag (see TDBMService::findObjects for complete description)
386
     * @param array \$parameters The parameters associated with the filter
387
     * @param array \$additionalTablesFetch A list of additional tables to fetch (for performance improvement)
388
     * @return $beanClassWithoutNameSpace|null
389
     */
390
    protected function findOne(\$filter = null, array \$parameters = [], array \$additionalTablesFetch = []) : ?$beanClassWithoutNameSpace
391
    {
392
        return \$this->tdbmService->findObject('$tableName', \$filter, \$parameters, \$additionalTablesFetch);
393
    }
394
395
    /**
396
     * Get a single $beanClassWithoutNameSpace specified by its filters.
397
     * Unlike the `find` method that guesses the FROM part of the statement, here you can pass the \$from part.
398
     *
399
     * You should not put an alias on the main table name. So your \$from variable should look like:
400
     *
401
     *   \"$tableName JOIN ... ON ...\"
402
     *
403
     * @param string \$from The sql from statement
404
     * @param mixed \$filter The filter bag (see TDBMService::findObjects for complete description)
405
     * @param array \$parameters The parameters associated with the filter
406
     * @return $beanClassWithoutNameSpace|null
407
     */
408
    protected function findOneFromSql(\$from, \$filter = null, array \$parameters = []) : ?$beanClassWithoutNameSpace
409
    {
410
        return \$this->tdbmService->findObjectFromSql('$tableName', \$from, \$filter, \$parameters);
411
    }
412
413
    /**
414
     * Sets the default column for default sorting.
415
     *
416
     * @param string \$defaultSort
417
     */
418
    public function setDefaultSort(string \$defaultSort) : void
419
    {
420
        \$this->defaultSort = \$defaultSort;
421
    }
422
";
423
424
        $str .= $findByDaoCode;
425
        $str .= '}
426
';
427
428
        $possibleBaseFileName = $this->configuration->getPathFinder()->getPath($daonamespace.'\\Generated\\'.$baseClassName)->getPathname();
429
430
        $this->dumpFile($possibleBaseFileName, $str);
431
432
        $possibleFileName = $this->configuration->getPathFinder()->getPath($daonamespace.'\\'.$className)->getPathname();
433
434
        // Now, let's generate the "editable" class
435
        if (!file_exists($possibleFileName)) {
436
            $str = "<?php
437
438
/*
439
 * This file has been automatically generated by TDBM.
440
 * You can edit this file as it will not be overwritten.
441
 */
442
443
namespace {$daonamespace};
444
445
use {$daonamespace}\\Generated\\{$baseClassName};
446
447
/**
448
 * The $className class will maintain the persistence of $beanClassWithoutNameSpace class into the $tableName table.
449
 */
450
class $className extends $baseClassName
451
{
452
}
453
";
454
            $this->dumpFile($possibleFileName, $str);
455
        }
456
    }
457
458
    /**
459
     * Generates the factory bean.
460
     *
461
     * @param Table[] $tableList
462
     * @throws TDBMException
463
     */
464
    private function generateFactory(array $tableList) : void
465
    {
466
        $daoNamespace = $this->configuration->getDaoNamespace();
467
        $daoFactoryClassName = $this->namingStrategy->getDaoFactoryClassName();
468
469
        // For each table, let's write a property.
470
471
        $str = "<?php
472
473
/*
474
 * This file has been automatically generated by TDBM.
475
 * DO NOT edit this file, as it might be overwritten.
476
 */
477
478
namespace {$daoNamespace}\\Generated;
479
480
";
481
        foreach ($tableList as $table) {
482
            $tableName = $table->getName();
483
            $daoClassName = $this->namingStrategy->getDaoClassName($tableName);
484
            $str .= "use {$daoNamespace}\\".$daoClassName.";\n";
485
        }
486
487
        $str .= "
488
/**
489
 * The $daoFactoryClassName provides an easy access to all DAOs generated by TDBM.
490
 *
491
 */
492
class $daoFactoryClassName
493
{
494
";
495
496
        foreach ($tableList as $table) {
497
            $tableName = $table->getName();
498
            $daoClassName = $this->namingStrategy->getDaoClassName($tableName);
499
            $daoInstanceName = self::toVariableName($daoClassName);
500
501
            $str .= '    /**
502
     * @var '.$daoClassName.'
503
     */
504
    private $'.$daoInstanceName.';
505
506
    /**
507
     * Returns an instance of the '.$daoClassName.' class.
508
     *
509
     * @return '.$daoClassName.'
510
     */
511
    public function get'.$daoClassName.'() : '.$daoClassName.'
512
    {
513
        return $this->'.$daoInstanceName.';
514
    }
515
516
    /**
517
     * Sets the instance of the '.$daoClassName.' class that will be returned by the factory getter.
518
     *
519
     * @param '.$daoClassName.' $'.$daoInstanceName.'
520
     */
521
    public function set'.$daoClassName.'('.$daoClassName.' $'.$daoInstanceName.') : void
522
    {
523
        $this->'.$daoInstanceName.' = $'.$daoInstanceName.';
524
    }';
525
        }
526
527
        $str .= '
528
}
529
';
530
531
        $possibleFileName = $this->configuration->getPathFinder()->getPath($daoNamespace.'\\Generated\\'.$daoFactoryClassName)->getPathname();
532
533
        $this->dumpFile($possibleFileName, $str);
534
    }
535
536
    /**
537
     * Transforms a string to camelCase (except the first letter will be uppercase too).
538
     * Underscores and spaces are removed and the first letter after the underscore is uppercased.
539
     *
540
     * @param $str string
541
     *
542
     * @return string
543
     */
544
    public static function toCamelCase($str)
545
    {
546
        $str = strtoupper(substr($str, 0, 1)).substr($str, 1);
547
        while (true) {
548
            if (strpos($str, '_') === false && strpos($str, ' ') === false) {
549
                break;
550
            }
551
552
            $pos = strpos($str, '_');
553
            if ($pos === false) {
554
                $pos = strpos($str, ' ');
555
            }
556
            $before = substr($str, 0, $pos);
557
            $after = substr($str, $pos + 1);
558
            $str = $before.strtoupper(substr($after, 0, 1)).substr($after, 1);
559
        }
560
561
        return $str;
562
    }
563
564
    /**
565
     * Tries to put string to the singular form (if it is plural).
566
     * We assume the table names are in english.
567
     *
568
     * @param $str string
569
     *
570
     * @return string
571
     */
572
    public static function toSingular($str)
573
    {
574
        return Inflector::singularize($str);
575
    }
576
577
    /**
578
     * Put the first letter of the string in lower case.
579
     * Very useful to transform a class name into a variable name.
580
     *
581
     * @param $str string
582
     *
583
     * @return string
584
     */
585
    public static function toVariableName($str)
586
    {
587
        return strtolower(substr($str, 0, 1)).substr($str, 1);
588
    }
589
590
    /**
591
     * Ensures the file passed in parameter can be written in its directory.
592
     *
593
     * @param string $fileName
594
     *
595
     * @throws TDBMException
596
     */
597
    private function ensureDirectoryExist(string $fileName)
598
    {
599
        $dirName = dirname($fileName);
600
        if (!file_exists($dirName)) {
601
            $old = umask(0);
602
            $result = mkdir($dirName, 0775, true);
603
            umask($old);
604
            if ($result === false) {
605
                throw new TDBMException("Unable to create directory: '".$dirName."'.");
606
            }
607
        }
608
    }
609
610
    private function dumpFile(string $fileName, string $content) : void
611
    {
612
        $this->ensureDirectoryExist($fileName);
613
        $fileSystem = new Filesystem();
614
        $fileSystem->dumpFile($fileName, $content);
615
        @chmod($fileName, 0664);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
616
    }
617
618
    /**
619
     * Transforms a DBAL type into a PHP type (for PHPDoc purpose).
620
     *
621
     * @param Type $type The DBAL type
622
     *
623
     * @return string The PHP type
624
     */
625
    public static function dbalTypeToPhpType(Type $type)
626
    {
627
        $map = [
628
            Type::TARRAY => 'array',
629
            Type::SIMPLE_ARRAY => 'array',
630
            'json' => 'array',  // 'json' is supported from Doctrine DBAL 2.6 only.
631
            Type::JSON_ARRAY => 'array',
632
            Type::BIGINT => 'string',
633
            Type::BOOLEAN => 'bool',
634
            Type::DATETIME => '\DateTimeInterface',
635
            Type::DATETIMETZ => '\DateTimeInterface',
636
            Type::DATE => '\DateTimeInterface',
637
            Type::TIME => '\DateTimeInterface',
638
            Type::DECIMAL => 'float',
639
            Type::INTEGER => 'int',
640
            Type::OBJECT => 'string',
641
            Type::SMALLINT => 'int',
642
            Type::STRING => 'string',
643
            Type::TEXT => 'string',
644
            Type::BINARY => 'string',
645
            Type::BLOB => 'string',
646
            Type::FLOAT => 'float',
647
            Type::GUID => 'string',
648
        ];
649
650
        return isset($map[$type->getName()]) ? $map[$type->getName()] : $type->getName();
651
    }
652
}
653