Test Failed
Pull Request — 4.2 (#140)
by David
05:30 queued 14s
created

TDBMDaoGenerator::generateAllDaosAndBeans()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 28
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 8.8571
c 0
b 0
f 0
cc 2
eloc 13
nc 2
nop 0
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
14
/**
15
 * This class generates automatically DAOs and Beans for TDBM.
16
 */
17
class TDBMDaoGenerator
18
{
19
    /**
20
     * @var Schema
21
     */
22
    private $schema;
23
24
    /**
25
     * The root directory of the project.
26
     *
27
     * @var string
28
     */
29
    private $rootPath;
30
31
    /**
32
     * Name of composer file.
33
     *
34
     * @var string
35
     */
36
    private $composerFile;
37
38
    /**
39
     * @var TDBMSchemaAnalyzer
40
     */
41
    private $tdbmSchemaAnalyzer;
42
43
    /**
44
     * @var EventDispatcherInterface
45
     */
46
    private $eventDispatcher;
47
48
    /**
49
     * @var NamingStrategyInterface
50
     */
51
    private $namingStrategy;
52
    /**
53
     * @var ConfigurationInterface
54
     */
55
    private $configuration;
56
57
    /**
58
     * Constructor.
59
     *
60
     * @param ConfigurationInterface $configuration
61
     * @param Schema $schema
62
     * @param TDBMSchemaAnalyzer $tdbmSchemaAnalyzer
63
     */
64
    public function __construct(ConfigurationInterface $configuration, Schema $schema, TDBMSchemaAnalyzer $tdbmSchemaAnalyzer)
65
    {
66
        $this->configuration = $configuration;
67
        $this->schema = $schema;
68
        $this->tdbmSchemaAnalyzer = $tdbmSchemaAnalyzer;
69
        $this->rootPath = __DIR__.'/../../../../../../../../';
70
        $this->namingStrategy = $configuration->getNamingStrategy();
71
        $this->eventDispatcher = $configuration->getGeneratorEventDispatcher();
0 ignored issues
show
Documentation Bug introduced by
It seems like $configuration->getGeneratorEventDispatcher() of type object<Mouf\Database\TDB...ratorListenerInterface> is incompatible with the declared type object<Symfony\Component...entDispatcherInterface> of property $eventDispatcher.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
72
    }
73
74
    /**
75
     * Generates all the daos and beans.
76
     *
77
     * @throws TDBMException
78
     */
79
    public function generateAllDaosAndBeans(): void
80
    {
81
        // TODO: check that no class name ends with "Base". Otherwise, there will be name clash.
82
83
        $tableList = $this->schema->getTables();
84
85
        // Remove all beans and daos from junction tables
86
        $junctionTables = $this->configuration->getSchemaAnalyzer()->detectJunctionTables(true);
87
        $junctionTableNames = array_map(function (Table $table) {
88
            return $table->getName();
89
        }, $junctionTables);
90
91
        $tableList = array_filter($tableList, function (Table $table) use ($junctionTableNames) {
92
            return !in_array($table->getName(), $junctionTableNames);
93
        });
94
95
        $beanDescriptors = [];
96
97
        foreach ($tableList as $table) {
98
            $beanDescriptors[] = $this->generateDaoAndBean($table);
99
        }
100
101
102
        $this->generateFactory($tableList);
103
104
        // Let's call the list of listeners
105
        $this->eventDispatcher->onGenerate($this->configuration, $beanDescriptors);
0 ignored issues
show
Bug introduced by
The method onGenerate() does not seem to exist on object<Symfony\Component...entDispatcherInterface>.

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...
106
    }
107
108
    /**
109
     * Generates in one method call the daos and the beans for one table.
110
     *
111
     * @param Table $table
112
     *
113
     * @return BeanDescriptor
114
     * @throws TDBMException
115
     */
116
    private function generateDaoAndBean(Table $table) : BeanDescriptor
117
    {
118
        // TODO: $storeInUtc is NOT USED.
119
        $tableName = $table->getName();
120
        $daoName = $this->namingStrategy->getDaoClassName($tableName);
121
        $beanName = $this->namingStrategy->getBeanClassName($tableName);
122
        $baseBeanName = $this->namingStrategy->getBaseBeanClassName($tableName);
123
        $baseDaoName = $this->namingStrategy->getBaseDaoClassName($tableName);
124
125
        $beanDescriptor = new BeanDescriptor($table, $this->configuration->getSchemaAnalyzer(), $this->schema, $this->tdbmSchemaAnalyzer, $this->namingStrategy);
126
        $this->generateBean($beanDescriptor, $beanName, $baseBeanName, $table);
127
        $this->generateDao($beanDescriptor, $daoName, $baseDaoName, $beanName, $table);
128
        return $beanDescriptor;
129
    }
130
131
    /**
132
     * Writes the PHP bean file with all getters and setters from the table passed in parameter.
133
     *
134
     * @param BeanDescriptor  $beanDescriptor
135
     * @param string          $className       The name of the class
136
     * @param string          $baseClassName   The name of the base class which will be extended (name only, no directory)
137
     * @param Table           $table           The table
138
     *
139
     * @throws TDBMException
140
     */
141
    public function generateBean(BeanDescriptor $beanDescriptor, $className, $baseClassName, Table $table)
142
    {
143
        $beannamespace = $this->configuration->getBeanNamespace();
144
        $str = $beanDescriptor->generatePhpCode($beannamespace);
145
146
        $possibleBaseFileName = $this->configuration->getPathFinder()->getPath($beannamespace.'\\Generated\\'.$baseClassName)->getPathname();
147
148
        $this->ensureDirectoryExist($possibleBaseFileName);
149
        file_put_contents($possibleBaseFileName, $str);
150
        @chmod($possibleBaseFileName, 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...
151
152
        $possibleFileName = $this->configuration->getPathFinder()->getPath($beannamespace.'\\'.$className)->getPathname();
153
154 View Code Duplication
        if (!file_exists($possibleFileName)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
155
            $tableName = $table->getName();
156
            $str = "<?php
157
/*
158
 * This file has been automatically generated by TDBM.
159
 * You can edit this file as it will not be overwritten.
160
 */
161
162
namespace {$beannamespace};
163
164
use {$beannamespace}\\Generated\\{$baseClassName};
165
166
/**
167
 * The $className class maps the '$tableName' table in database.
168
 */
169
class $className extends $baseClassName
170
{
171
}
172
";
173
            $this->ensureDirectoryExist($possibleFileName);
174
            file_put_contents($possibleFileName, $str);
175
            @chmod($possibleFileName, 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...
176
        }
177
    }
178
179
    /**
180
     * Tries to find a @defaultSort annotation in one of the columns.
181
     *
182
     * @param Table $table
183
     *
184
     * @return array First item: column name, Second item: column order (asc/desc)
185
     */
186
    private function getDefaultSortColumnFromAnnotation(Table $table)
187
    {
188
        $defaultSort = null;
189
        $defaultSortDirection = null;
190
        foreach ($table->getColumns() as $column) {
191
            $comments = $column->getComment();
192
            $matches = [];
193
            if (preg_match('/@defaultSort(\((desc|asc)\))*/', $comments, $matches) != 0) {
194
                $defaultSort = $column->getName();
195
                if (count($matches) === 3) {
196
                    $defaultSortDirection = $matches[2];
197
                } else {
198
                    $defaultSortDirection = 'ASC';
199
                }
200
            }
201
        }
202
203
        return [$defaultSort, $defaultSortDirection];
204
    }
205
206
    /**
207
     * Writes the PHP bean DAO with simple functions to create/get/save objects.
208
     *
209
     * @param BeanDescriptor  $beanDescriptor
210
     * @param string          $className       The name of the class
211
     * @param string          $baseClassName
212
     * @param string          $beanClassName
213
     * @param Table           $table
214
     *
215
     * @throws TDBMException
216
     */
217
    private function generateDao(BeanDescriptor $beanDescriptor, string $className, string $baseClassName, string $beanClassName, Table $table)
218
    {
219
        $daonamespace = $this->configuration->getDaoNamespace();
220
        $beannamespace = $this->configuration->getBeanNamespace();
221
        $tableName = $table->getName();
222
        $primaryKeyColumns = $table->getPrimaryKeyColumns();
223
224
        list($defaultSort, $defaultSortDirection) = $this->getDefaultSortColumnFromAnnotation($table);
225
226
        // FIXME: lowercase tables with _ in the name should work!
227
        $tableCamel = self::toSingular(self::toCamelCase($tableName));
228
229
        $beanClassWithoutNameSpace = $beanClassName;
230
        $beanClassName = $beannamespace.'\\'.$beanClassName;
231
232
        list($usedBeans, $findByDaoCode) = $beanDescriptor->generateFindByDaoCode($beannamespace, $beanClassWithoutNameSpace);
233
234
        $usedBeans[] = $beanClassName;
235
        // Let's suppress duplicates in used beans (if any)
236
        $usedBeans = array_flip(array_flip($usedBeans));
237
        $useStatements = array_map(function ($usedBean) {
238
            return "use $usedBean;\n";
239
        }, $usedBeans);
240
241
        $str = "<?php
242
243
/*
244
 * This file has been automatically generated by TDBM.
245
 * DO NOT edit this file, as it might be overwritten.
246
 * If you need to perform changes, edit the $className class instead!
247
 */
248
249
namespace {$daonamespace}\\Generated;
250
251
use Mouf\\Database\\TDBM\\TDBMService;
252
use Mouf\\Database\\TDBM\\ResultIterator;
253
use Mouf\\Database\\TDBM\\ArrayIterator;
254
".implode('', $useStatements)."
255
/**
256
 * The $baseClassName class will maintain the persistence of $beanClassWithoutNameSpace class into the $tableName table.
257
 *
258
 */
259
class $baseClassName
260
{
261
262
    /**
263
     * @var TDBMService
264
     */
265
    protected \$tdbmService;
266
267
    /**
268
     * The default sort column.
269
     *
270
     * @var string
271
     */
272
    private \$defaultSort = ".($defaultSort ? "'$defaultSort'" : 'null').';
273
274
    /**
275
     * The default sort direction.
276
     *
277
     * @var string
278
     */
279
    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...
280
281
    /**
282
     * Sets the TDBM service used by this DAO.
283
     *
284
     * @param TDBMService \$tdbmService
285
     */
286
    public function __construct(TDBMService \$tdbmService)
287
    {
288
        \$this->tdbmService = \$tdbmService;
289
    }
290
291
    /**
292
     * Persist the $beanClassWithoutNameSpace instance.
293
     *
294
     * @param $beanClassWithoutNameSpace \$obj The bean to save.
295
     */
296
    public function save($beanClassWithoutNameSpace \$obj)
297
    {
298
        \$this->tdbmService->save(\$obj);
299
    }
300
301
    /**
302
     * Get all $tableCamel records.
303
     *
304
     * @return {$beanClassWithoutNameSpace}[]|ResultIterator|ResultArray
305
     */
306
    public function findAll() : iterable
307
    {
308
        if (\$this->defaultSort) {
309
            \$orderBy = '$tableName.'.\$this->defaultSort.' '.\$this->defaultDirection;
310
        } else {
311
            \$orderBy = null;
312
        }
313
        return \$this->tdbmService->findObjects('$tableName', null, [], \$orderBy);
314
    }
315
    ";
316
317
        if (count($primaryKeyColumns) === 1) {
318
            $primaryKeyColumn = $primaryKeyColumns[0];
319
            $primaryKeyPhpType = self::dbalTypeToPhpType($table->getColumn($primaryKeyColumn)->getType());
320
            $str .= "
321
    /**
322
     * Get $beanClassWithoutNameSpace specified by its ID (its primary key)
323
     * If the primary key does not exist, an exception is thrown.
324
     *
325
     * @param string|int \$id
326
     * @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.
327
     * @return $beanClassWithoutNameSpace
328
     * @throws TDBMException
329
     */
330
    public function getById($primaryKeyPhpType \$id, \$lazyLoading = false) : $beanClassWithoutNameSpace
331
    {
332
        return \$this->tdbmService->findObjectByPk('$tableName', ['$primaryKeyColumn' => \$id], [], \$lazyLoading);
333
    }
334
    ";
335
        }
336
        $str .= "
337
    /**
338
     * Deletes the $beanClassWithoutNameSpace passed in parameter.
339
     *
340
     * @param $beanClassWithoutNameSpace \$obj object to delete
341
     * @param bool \$cascade if true, it will delete all object linked to \$obj
342
     */
343
    public function delete($beanClassWithoutNameSpace \$obj, \$cascade = false) : void
344
    {
345
        if (\$cascade === true) {
346
            \$this->tdbmService->deleteCascade(\$obj);
347
        } else {
348
            \$this->tdbmService->delete(\$obj);
349
        }
350
    }
351
352
353
    /**
354
     * Get a list of $beanClassWithoutNameSpace specified by its filters.
355
     *
356
     * @param mixed \$filter The filter bag (see TDBMService::findObjects for complete description)
357
     * @param array \$parameters The parameters associated with the filter
358
     * @param mixed \$orderBy The order string
359
     * @param array \$additionalTablesFetch A list of additional tables to fetch (for performance improvement)
360
     * @param int \$mode Either TDBMService::MODE_ARRAY or TDBMService::MODE_CURSOR (for large datasets). Defaults to TDBMService::MODE_ARRAY.
361
     * @return {$beanClassWithoutNameSpace}[]|ResultIterator|ResultArray
362
     */
363
    protected function find(\$filter = null, array \$parameters = [], \$orderBy=null, array \$additionalTablesFetch = [], \$mode = null) : iterable
364
    {
365
        if (\$this->defaultSort && \$orderBy == null) {
366
            \$orderBy = '$tableName.'.\$this->defaultSort.' '.\$this->defaultDirection;
367
        }
368
        return \$this->tdbmService->findObjects('$tableName', \$filter, \$parameters, \$orderBy, \$additionalTablesFetch, \$mode);
369
    }
370
371
    /**
372
     * Get a list of $beanClassWithoutNameSpace specified by its filters.
373
     * Unlike the `find` method that guesses the FROM part of the statement, here you can pass the \$from part.
374
     *
375
     * You should not put an alias on the main table name. So your \$from variable should look like:
376
     *
377
     *   \"$tableName JOIN ... ON ...\"
378
     *
379
     * @param string \$from The sql from statement
380
     * @param mixed \$filter The filter bag (see TDBMService::findObjects for complete description)
381
     * @param array \$parameters The parameters associated with the filter
382
     * @param mixed \$orderBy The order string
383
     * @param int \$mode Either TDBMService::MODE_ARRAY or TDBMService::MODE_CURSOR (for large datasets). Defaults to TDBMService::MODE_ARRAY.
384
     * @return {$beanClassWithoutNameSpace}[]|ResultIterator|ResultArray
385
     */
386
    protected function findFromSql(\$from, \$filter = null, array \$parameters = [], \$orderBy = null, \$mode = null) : iterable
387
    {
388
        if (\$this->defaultSort && \$orderBy == null) {
389
            \$orderBy = '$tableName.'.\$this->defaultSort.' '.\$this->defaultDirection;
390
        }
391
        return \$this->tdbmService->findObjectsFromSql('$tableName', \$from, \$filter, \$parameters, \$orderBy, \$mode);
392
    }
393
394
    /**
395
     * Get a single $beanClassWithoutNameSpace specified by its filters.
396
     *
397
     * @param mixed \$filter The filter bag (see TDBMService::findObjects for complete description)
398
     * @param array \$parameters The parameters associated with the filter
399
     * @param array \$additionalTablesFetch A list of additional tables to fetch (for performance improvement)
400
     * @return $beanClassWithoutNameSpace|null
401
     */
402
    protected function findOne(\$filter = null, array \$parameters = [], array \$additionalTablesFetch = []) : ?$beanClassWithoutNameSpace
403
    {
404
        return \$this->tdbmService->findObject('$tableName', \$filter, \$parameters, \$additionalTablesFetch);
405
    }
406
407
    /**
408
     * Get a single $beanClassWithoutNameSpace specified by its filters.
409
     * Unlike the `find` method that guesses the FROM part of the statement, here you can pass the \$from part.
410
     *
411
     * You should not put an alias on the main table name. So your \$from variable should look like:
412
     *
413
     *   \"$tableName JOIN ... ON ...\"
414
     *
415
     * @param string \$from The sql from statement
416
     * @param mixed \$filter The filter bag (see TDBMService::findObjects for complete description)
417
     * @param array \$parameters The parameters associated with the filter
418
     * @return $beanClassWithoutNameSpace|null
419
     */
420
    protected function findOneFromSql(\$from, \$filter = null, array \$parameters = []) : ?$beanClassWithoutNameSpace
421
    {
422
        return \$this->tdbmService->findObjectFromSql('$tableName', \$from, \$filter, \$parameters);
423
    }
424
425
    /**
426
     * Sets the default column for default sorting.
427
     *
428
     * @param string \$defaultSort
429
     */
430
    public function setDefaultSort(string \$defaultSort) : void
431
    {
432
        \$this->defaultSort = \$defaultSort;
433
    }
434
";
435
436
        $str .= $findByDaoCode;
437
        $str .= '}
438
';
439
440
        $possibleBaseFileName = $this->configuration->getPathFinder()->getPath($daonamespace.'\\Generated\\'.$baseClassName)->getPathname();
441
442
        $this->ensureDirectoryExist($possibleBaseFileName);
443
        file_put_contents($possibleBaseFileName, $str);
444
        @chmod($possibleBaseFileName, 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...
445
446
        $possibleFileName = $this->configuration->getPathFinder()->getPath($daonamespace.'\\'.$className)->getPathname();
447
448
        // Now, let's generate the "editable" class
449 View Code Duplication
        if (!file_exists($possibleFileName)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
450
            $str = "<?php
451
452
/*
453
 * This file has been automatically generated by TDBM.
454
 * You can edit this file as it will not be overwritten.
455
 */
456
457
namespace {$daonamespace};
458
459
use {$daonamespace}\\Generated\\{$baseClassName};
460
461
/**
462
 * The $className class will maintain the persistence of $beanClassWithoutNameSpace class into the $tableName table.
463
 */
464
class $className extends $baseClassName
465
{
466
}
467
";
468
            $this->ensureDirectoryExist($possibleFileName);
469
            file_put_contents($possibleFileName, $str);
470
            @chmod($possibleFileName, 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...
471
        }
472
    }
473
474
    /**
475
     * Generates the factory bean.
476
     *
477
     * @param Table[] $tableList
478
     * @throws TDBMException
479
     */
480
    private function generateFactory(array $tableList) : void
481
    {
482
        $daoNamespace = $this->configuration->getDaoNamespace();
483
        $daoFactoryClassName = $this->namingStrategy->getDaoFactoryClassName();
484
485
        // For each table, let's write a property.
486
487
        $str = "<?php
488
489
/*
490
 * This file has been automatically generated by TDBM.
491
 * DO NOT edit this file, as it might be overwritten.
492
 */
493
494
namespace {$daoNamespace}\\Generated;
495
496
";
497
        foreach ($tableList as $table) {
498
            $tableName = $table->getName();
499
            $daoClassName = $this->namingStrategy->getDaoClassName($tableName);
500
            $str .= "use {$daoNamespace}\\".$daoClassName.";\n";
501
        }
502
503
        $str .= "
504
/**
505
 * The $daoFactoryClassName provides an easy access to all DAOs generated by TDBM.
506
 *
507
 */
508
class $daoFactoryClassName
509
{
510
";
511
512
        foreach ($tableList as $table) {
513
            $tableName = $table->getName();
514
            $daoClassName = $this->namingStrategy->getDaoClassName($tableName);
515
            $daoInstanceName = self::toVariableName($daoClassName);
516
517
            $str .= '    /**
518
     * @var '.$daoClassName.'
519
     */
520
    private $'.$daoInstanceName.';
521
522
    /**
523
     * Returns an instance of the '.$daoClassName.' class.
524
     *
525
     * @return '.$daoClassName.'
526
     */
527
    public function get'.$daoClassName.'() : '.$daoClassName.'
528
    {
529
        return $this->'.$daoInstanceName.';
530
    }
531
532
    /**
533
     * Sets the instance of the '.$daoClassName.' class that will be returned by the factory getter.
534
     *
535
     * @param '.$daoClassName.' $'.$daoInstanceName.'
536
     */
537
    public function set'.$daoClassName.'('.$daoClassName.' $'.$daoInstanceName.') : void
538
    {
539
        $this->'.$daoInstanceName.' = $'.$daoInstanceName.';
540
    }';
541
        }
542
543
        $str .= '
544
}
545
';
546
547
        $possibleFileName = $this->configuration->getPathFinder()->getPath($daoNamespace.'\\Generated\\'.$daoFactoryClassName)->getPathname();
548
549
        $this->ensureDirectoryExist($possibleFileName);
550
        file_put_contents($possibleFileName, $str);
551
        @chmod($possibleFileName, 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...
552
    }
553
554
    /**
555
     * Transforms a string to camelCase (except the first letter will be uppercase too).
556
     * Underscores and spaces are removed and the first letter after the underscore is uppercased.
557
     *
558
     * @param $str string
559
     *
560
     * @return string
561
     */
562
    public static function toCamelCase($str)
563
    {
564
        $str = strtoupper(substr($str, 0, 1)).substr($str, 1);
565
        while (true) {
566
            if (strpos($str, '_') === false && strpos($str, ' ') === false) {
567
                break;
568
            }
569
570
            $pos = strpos($str, '_');
571
            if ($pos === false) {
572
                $pos = strpos($str, ' ');
573
            }
574
            $before = substr($str, 0, $pos);
575
            $after = substr($str, $pos + 1);
576
            $str = $before.strtoupper(substr($after, 0, 1)).substr($after, 1);
577
        }
578
579
        return $str;
580
    }
581
582
    /**
583
     * Tries to put string to the singular form (if it is plural).
584
     * We assume the table names are in english.
585
     *
586
     * @param $str string
587
     *
588
     * @return string
589
     */
590
    public static function toSingular($str)
591
    {
592
        return Inflector::singularize($str);
593
    }
594
595
    /**
596
     * Put the first letter of the string in lower case.
597
     * Very useful to transform a class name into a variable name.
598
     *
599
     * @param $str string
600
     *
601
     * @return string
602
     */
603
    public static function toVariableName($str)
604
    {
605
        return strtolower(substr($str, 0, 1)).substr($str, 1);
606
    }
607
608
    /**
609
     * Ensures the file passed in parameter can be written in its directory.
610
     *
611
     * @param string $fileName
612
     *
613
     * @throws TDBMException
614
     */
615
    private function ensureDirectoryExist($fileName)
616
    {
617
        $dirName = dirname($fileName);
618
        if (!file_exists($dirName)) {
619
            $old = umask(0);
620
            $result = mkdir($dirName, 0775, true);
621
            umask($old);
622
            if ($result === false) {
623
                throw new TDBMException("Unable to create directory: '".$dirName."'.");
624
            }
625
        }
626
    }
627
628
    /**
629
     * Absolute path to composer json file.
630
     *
631
     * @param string $composerFile
632
     */
633
    /*public function setComposerFile($composerFile)
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
634
    {
635
        $this->rootPath = dirname($composerFile).'/';
636
        $this->composerFile = basename($composerFile);
637
    }*/
638
639
    /**
640
     * Transforms a DBAL type into a PHP type (for PHPDoc purpose).
641
     *
642
     * @param Type $type The DBAL type
643
     *
644
     * @return string The PHP type
645
     */
646
    public static function dbalTypeToPhpType(Type $type)
647
    {
648
        $map = [
649
            Type::TARRAY => 'array',
650
            Type::SIMPLE_ARRAY => 'array',
651
            'json' => 'array',  // 'json' is supported from Doctrine DBAL 2.6 only.
652
            Type::JSON_ARRAY => 'array',
653
            Type::BIGINT => 'string',
654
            Type::BOOLEAN => 'bool',
655
            Type::DATETIME => '\DateTimeInterface',
656
            Type::DATETIMETZ => '\DateTimeInterface',
657
            Type::DATE => '\DateTimeInterface',
658
            Type::TIME => '\DateTimeInterface',
659
            Type::DECIMAL => 'float',
660
            Type::INTEGER => 'int',
661
            Type::OBJECT => 'string',
662
            Type::SMALLINT => 'int',
663
            Type::STRING => 'string',
664
            Type::TEXT => 'string',
665
            Type::BINARY => 'string',
666
            Type::BLOB => 'string',
667
            Type::FLOAT => 'float',
668
            Type::GUID => 'string',
669
        ];
670
671
        return isset($map[$type->getName()]) ? $map[$type->getName()] : $type->getName();
672
    }
673
}
674