Completed
Push — master ( 3ef80d...6fc5d4 )
by David
04:15 queued 57s
created

BeanDescriptor::getExposedProperties()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 0
1
<?php
2
3
namespace TheCodingMachine\TDBM\Utils;
4
5
use Doctrine\DBAL\Schema\Column;
6
use Doctrine\DBAL\Schema\Index;
7
use Doctrine\DBAL\Schema\Schema;
8
use Doctrine\DBAL\Schema\Table;
9
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
10
use Mouf\Database\SchemaAnalyzer\SchemaAnalyzer;
11
use TheCodingMachine\TDBM\TDBMException;
12
use TheCodingMachine\TDBM\TDBMSchemaAnalyzer;
13
14
/**
15
 * This class represents a bean.
16
 */
17
class BeanDescriptor implements BeanDescriptorInterface
18
{
19
    /**
20
     * @var Table
21
     */
22
    private $table;
23
24
    /**
25
     * @var SchemaAnalyzer
26
     */
27
    private $schemaAnalyzer;
28
29
    /**
30
     * @var Schema
31
     */
32
    private $schema;
33
34
    /**
35
     * @var AbstractBeanPropertyDescriptor[]
36
     */
37
    private $beanPropertyDescriptors = [];
38
39
    /**
40
     * @var TDBMSchemaAnalyzer
41
     */
42
    private $tdbmSchemaAnalyzer;
43
44
    /**
45
     * @var NamingStrategyInterface
46
     */
47
    private $namingStrategy;
48
    /**
49
     * @var string
50
     */
51
    private $beanNamespace;
52
    /**
53
     * @var string
54
     */
55
    private $generatedBeanNamespace;
56
57
    /**
58
     * @param Table $table
59
     * @param string $beanNamespace
60
     * @param string $generatedBeanNamespace
61
     * @param SchemaAnalyzer $schemaAnalyzer
62
     * @param Schema $schema
63
     * @param TDBMSchemaAnalyzer $tdbmSchemaAnalyzer
64
     * @param NamingStrategyInterface $namingStrategy
65
     */
66
    public function __construct(Table $table, string $beanNamespace, string $generatedBeanNamespace, SchemaAnalyzer $schemaAnalyzer, Schema $schema, TDBMSchemaAnalyzer $tdbmSchemaAnalyzer, NamingStrategyInterface $namingStrategy)
67
    {
68
        $this->table = $table;
69
        $this->beanNamespace = $beanNamespace;
70
        $this->generatedBeanNamespace = $generatedBeanNamespace;
71
        $this->schemaAnalyzer = $schemaAnalyzer;
72
        $this->schema = $schema;
73
        $this->tdbmSchemaAnalyzer = $tdbmSchemaAnalyzer;
74
        $this->namingStrategy = $namingStrategy;
75
        $this->initBeanPropertyDescriptors();
76
    }
77
78
    private function initBeanPropertyDescriptors()
79
    {
80
        $this->beanPropertyDescriptors = $this->getProperties($this->table);
81
    }
82
83
    /**
84
     * Returns the foreign-key the column is part of, if any. null otherwise.
85
     *
86
     * @param Table  $table
87
     * @param Column $column
88
     *
89
     * @return ForeignKeyConstraint|null
90
     */
91
    private function isPartOfForeignKey(Table $table, Column $column)
92
    {
93
        $localColumnName = $column->getName();
94
        foreach ($table->getForeignKeys() as $foreignKey) {
95
            foreach ($foreignKey->getColumns() as $columnName) {
96
                if ($columnName === $localColumnName) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $columnName (integer) and $localColumnName (string) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
97
                    return $foreignKey;
98
                }
99
            }
100
        }
101
102
        return;
103
    }
104
105
    /**
106
     * @return AbstractBeanPropertyDescriptor[]
107
     */
108
    public function getBeanPropertyDescriptors()
109
    {
110
        return $this->beanPropertyDescriptors;
111
    }
112
113
    /**
114
     * Returns the list of columns that are not nullable and not autogenerated for a given table and its parent.
115
     *
116
     * @return AbstractBeanPropertyDescriptor[]
117
     */
118
    public function getConstructorProperties()
119
    {
120
        $constructorProperties = array_filter($this->beanPropertyDescriptors, function (AbstractBeanPropertyDescriptor $property) {
121
            return $property->isCompulsory();
122
        });
123
124
        return $constructorProperties;
125
    }
126
127
    /**
128
     * Returns the list of columns that have default values for a given table.
129
     *
130
     * @return AbstractBeanPropertyDescriptor[]
131
     */
132
    public function getPropertiesWithDefault()
133
    {
134
        $properties = $this->getPropertiesForTable($this->table);
135
        $defaultProperties = array_filter($properties, function (AbstractBeanPropertyDescriptor $property) {
136
            return $property->hasDefault();
137
        });
138
139
        return $defaultProperties;
140
    }
141
142
    /**
143
     * Returns the list of properties exposed as getters and setters in this class.
144
     *
145
     * @return AbstractBeanPropertyDescriptor[]
146
     */
147
    public function getExposedProperties(): array
148
    {
149
        $exposedProperties = array_filter($this->beanPropertyDescriptors, function (AbstractBeanPropertyDescriptor $property) {
150
            return $property->getTable()->getName() == $this->table->getName();
151
        });
152
153
        return $exposedProperties;
154
    }
155
156
    /**
157
     * Returns the list of properties for this table (including parent tables).
158
     *
159
     * @param Table $table
160
     *
161
     * @return AbstractBeanPropertyDescriptor[]
162
     */
163
    private function getProperties(Table $table)
164
    {
165
        $parentRelationship = $this->schemaAnalyzer->getParentRelationship($table->getName());
166
        if ($parentRelationship) {
167
            $parentTable = $this->schema->getTable($parentRelationship->getForeignTableName());
168
            $properties = $this->getProperties($parentTable);
169
            // we merge properties by overriding property names.
170
            $localProperties = $this->getPropertiesForTable($table);
171
            foreach ($localProperties as $name => $property) {
172
                // We do not override properties if this is a primary key!
173
                if ($property->isPrimaryKey()) {
174
                    continue;
175
                }
176
                $properties[$name] = $property;
177
            }
178
        } else {
179
            $properties = $this->getPropertiesForTable($table);
180
        }
181
182
        return $properties;
183
    }
184
185
    /**
186
     * Returns the list of properties for this table (ignoring parent tables).
187
     *
188
     * @param Table $table
189
     *
190
     * @return AbstractBeanPropertyDescriptor[]
191
     */
192
    private function getPropertiesForTable(Table $table)
193
    {
194
        $parentRelationship = $this->schemaAnalyzer->getParentRelationship($table->getName());
195
        if ($parentRelationship) {
196
            $ignoreColumns = $parentRelationship->getLocalColumns();
197
        } else {
198
            $ignoreColumns = [];
199
        }
200
201
        $beanPropertyDescriptors = [];
202
203
        foreach ($table->getColumns() as $column) {
204
            if (array_search($column->getName(), $ignoreColumns) !== false) {
205
                continue;
206
            }
207
208
            $fk = $this->isPartOfForeignKey($table, $column);
209
            if ($fk !== null) {
210
                // Check that previously added descriptors are not added on same FK (can happen with multi key FK).
211
                foreach ($beanPropertyDescriptors as $beanDescriptor) {
212
                    if ($beanDescriptor instanceof ObjectBeanPropertyDescriptor && $beanDescriptor->getForeignKey() === $fk) {
213
                        continue 2;
214
                    }
215
                }
216
                // Check that this property is not an inheritance relationship
217
                $parentRelationship = $this->schemaAnalyzer->getParentRelationship($table->getName());
218
                if ($parentRelationship === $fk) {
219
                    continue;
220
                }
221
222
                $beanPropertyDescriptors[] = new ObjectBeanPropertyDescriptor($table, $fk, $this->schemaAnalyzer, $this->namingStrategy);
223
            } else {
224
                $beanPropertyDescriptors[] = new ScalarBeanPropertyDescriptor($table, $column, $this->namingStrategy);
225
            }
226
        }
227
228
        // Now, let's get the name of all properties and let's check there is no duplicate.
229
        /** @var $names AbstractBeanPropertyDescriptor[] */
230
        $names = [];
231
        foreach ($beanPropertyDescriptors as $beanDescriptor) {
232
            $name = $beanDescriptor->getGetterName();
233
            if (isset($names[$name])) {
234
                $names[$name]->useAlternativeName();
235
                $beanDescriptor->useAlternativeName();
236
            } else {
237
                $names[$name] = $beanDescriptor;
238
            }
239
        }
240
241
        // Final check (throw exceptions if problem arises)
242
        $names = [];
243
        foreach ($beanPropertyDescriptors as $beanDescriptor) {
244
            $name = $beanDescriptor->getGetterName();
245
            if (isset($names[$name])) {
246
                throw new TDBMException('Unsolvable name conflict while generating method name');
247
            } else {
248
                $names[$name] = $beanDescriptor;
249
            }
250
        }
251
252
        // Last step, let's rebuild the list with a map:
253
        $beanPropertyDescriptorsMap = [];
254
        foreach ($beanPropertyDescriptors as $beanDescriptor) {
255
            $beanPropertyDescriptorsMap[$beanDescriptor->getVariableName()] = $beanDescriptor;
256
        }
257
258
        return $beanPropertyDescriptorsMap;
259
    }
260
261
    private function generateBeanConstructor() : string
262
    {
263
        $constructorProperties = $this->getConstructorProperties();
264
265
        $constructorCode = '    /**
266
     * The constructor takes all compulsory arguments.
267
     *
268
%s
269
     */
270
    public function __construct(%s)
271
    {
272
%s%s    }
273
    ';
274
275
        $paramAnnotations = [];
276
        $arguments = [];
277
        $assigns = [];
278
        $parentConstructorArguments = [];
279
280
        foreach ($constructorProperties as $property) {
281
            $className = $property->getClassName();
282
            if ($className) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $className 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...
283
                $arguments[] = $className.' '.$property->getVariableName();
284
            } else {
285
                $arguments[] = $property->getVariableName();
286
            }
287
            $paramAnnotations[] = $property->getParamAnnotation();
288
            if ($property->getTable()->getName() === $this->table->getName()) {
289
                $assigns[] = $property->getConstructorAssignCode()."\n";
290
            } else {
291
                $parentConstructorArguments[] = $property->getVariableName();
292
            }
293
        }
294
295
        $parentConstructorCode = sprintf("        parent::__construct(%s);\n", implode(', ', $parentConstructorArguments));
296
297
        foreach ($this->getPropertiesWithDefault() as $property) {
298
            $assigns[] = $property->assignToDefaultCode()."\n";
299
        }
300
301
        return sprintf($constructorCode, implode("\n", $paramAnnotations), implode(', ', $arguments), $parentConstructorCode, implode('', $assigns));
302
    }
303
304
    /**
305
     * Returns the descriptors of one-to-many relationships (the foreign keys pointing on this beans)
306
     *
307
     * @return DirectForeignKeyMethodDescriptor[]
308
     */
309
    private function getDirectForeignKeysDescriptors(): array
310
    {
311
        $fks = $this->tdbmSchemaAnalyzer->getIncomingForeignKeys($this->table->getName());
312
313
        $descriptors = [];
314
315
        foreach ($fks as $fk) {
316
            $descriptors[] = new DirectForeignKeyMethodDescriptor($fk, $this->table, $this->namingStrategy);
317
        }
318
319
        return $descriptors;
320
    }
321
322
    /**
323
     * @return PivotTableMethodsDescriptor[]
324
     */
325
    private function getPivotTableDescriptors(): array
326
    {
327
        $descs = [];
328
        foreach ($this->schemaAnalyzer->detectJunctionTables(true) as $table) {
329
            // There are exactly 2 FKs since this is a pivot table.
330
            $fks = array_values($table->getForeignKeys());
331
332
            if ($fks[0]->getForeignTableName() === $this->table->getName()) {
333
                list($localFk, $remoteFk) = $fks;
334
            } elseif ($fks[1]->getForeignTableName() === $this->table->getName()) {
335
                list($remoteFk, $localFk) = $fks;
336
            } else {
337
                continue;
338
            }
339
340
            $descs[] = new PivotTableMethodsDescriptor($table, $localFk, $remoteFk, $this->namingStrategy);
341
        }
342
343
        return $descs;
344
    }
345
346
    /**
347
     * Returns the list of method descriptors (and applies the alternative name if needed).
348
     *
349
     * @return MethodDescriptorInterface[]
350
     */
351
    public function getMethodDescriptors(): array
352
    {
353
        $directForeignKeyDescriptors = $this->getDirectForeignKeysDescriptors();
354
        $pivotTableDescriptors = $this->getPivotTableDescriptors();
355
356
        $descriptors = array_merge($directForeignKeyDescriptors, $pivotTableDescriptors);
357
358
        // Descriptors by method names
359
        $descriptorsByMethodName = [];
360
361
        foreach ($descriptors as $descriptor) {
362
            $descriptorsByMethodName[$descriptor->getName()][] = $descriptor;
363
        }
364
365
        foreach ($descriptorsByMethodName as $descriptorsForMethodName) {
366
            if (count($descriptorsForMethodName) > 1) {
367
                foreach ($descriptorsForMethodName as $descriptor) {
368
                    $descriptor->useAlternativeName();
369
                }
370
            }
371
        }
372
373
        return $descriptors;
374
    }
375
376
    public function generateJsonSerialize(): string
377
    {
378
        $tableName = $this->table->getName();
379
        $parentFk = $this->schemaAnalyzer->getParentRelationship($tableName);
380
        if ($parentFk !== null) {
381
            $initializer = '$array = parent::jsonSerialize($stopRecursion);';
382
        } else {
383
            $initializer = '$array = [];';
384
        }
385
386
        $str = '
387
    /**
388
     * Serializes the object for JSON encoding.
389
     *
390
     * @param bool $stopRecursion Parameter used internally by TDBM to stop embedded objects from embedding other objects.
391
     * @return array
392
     */
393
    public function jsonSerialize($stopRecursion = false)
394
    {
395
        %s
396
%s
397
%s
398
        return $array;
399
    }
400
';
401
402
        $propertiesCode = '';
403
        foreach ($this->beanPropertyDescriptors as $beanPropertyDescriptor) {
404
            $propertiesCode .= $beanPropertyDescriptor->getJsonSerializeCode();
405
        }
406
407
        // Many2many relationships
408
        $methodsCode = '';
409
        foreach ($this->getMethodDescriptors() as $methodDescriptor) {
410
            $methodsCode .= $methodDescriptor->getJsonSerializeCode();
411
        }
412
413
        return sprintf($str, $initializer, $propertiesCode, $methodsCode);
414
    }
415
416
    /**
417
     * Returns as an array the class we need to extend from and the list of use statements.
418
     *
419
     * @param ForeignKeyConstraint|null $parentFk
420
     * @return array
421
     */
422
    private function generateExtendsAndUseStatements(ForeignKeyConstraint $parentFk = null): array
423
    {
424
        $classes = [];
425
        if ($parentFk !== null) {
426
            $extends = $this->namingStrategy->getBeanClassName($parentFk->getForeignTableName());
427
            $classes[] = $extends;
428
        }
429
430
        foreach ($this->getBeanPropertyDescriptors() as $beanPropertyDescriptor) {
431
            $className = $beanPropertyDescriptor->getClassName();
432
            if (null !== $className) {
433
                $classes[] = $beanPropertyDescriptor->getClassName();
434
            }
435
        }
436
437
        foreach ($this->getMethodDescriptors() as $descriptor) {
438
            $classes = array_merge($classes, $descriptor->getUsedClasses());
439
        }
440
441
        $classes = array_unique($classes);
442
443
        return $classes;
444
    }
445
446
    /**
447
     * Writes the PHP bean file with all getters and setters from the table passed in parameter.
448
     *
449
     * @return string
450
     */
451
    public function generatePhpCode(): string
452
    {
453
        $tableName = $this->table->getName();
454
        $baseClassName = $this->namingStrategy->getBaseBeanClassName($tableName);
455
        $className = $this->namingStrategy->getBeanClassName($tableName);
456
        $parentFk = $this->schemaAnalyzer->getParentRelationship($this->table->getName());
457
458
        $classes = $this->generateExtendsAndUseStatements($parentFk);
459
460
        $uses = array_map(function ($className) {
461
            return 'use '.$this->beanNamespace.'\\'.$className.";\n";
462
        }, $classes);
463
        $use = implode('', $uses);
464
465
        $extends = $this->getExtendedBeanClassName();
466
        if ($extends === null) {
467
            $extends = 'AbstractTDBMObject';
468
            $use .= "use TheCodingMachine\\TDBM\\AbstractTDBMObject;\n";
469
        }
470
471
        $str = "<?php
472
namespace {$this->generatedBeanNamespace};
473
474
use TheCodingMachine\\TDBM\\ResultIterator;
475
use TheCodingMachine\\TDBM\\ResultArray;
476
use TheCodingMachine\\TDBM\\AlterableResultIterator;
477
use Ramsey\\Uuid\\Uuid;
478
$use
479
/*
480
 * This file has been automatically generated by TDBM.
481
 * DO NOT edit this file, as it might be overwritten.
482
 * If you need to perform changes, edit the $className class instead!
483
 */
484
485
/**
486
 * The $baseClassName class maps the '$tableName' table in database.
487
 */
488
abstract class $baseClassName extends $extends implements \\JsonSerializable
489
{
490
";
491
492
        $str .= $this->generateBeanConstructor();
493
494
        foreach ($this->getExposedProperties() as $property) {
495
            $str .= $property->getGetterSetterCode();
496
        }
497
498
        foreach ($this->getMethodDescriptors() as $methodDescriptor) {
499
            $str .= $methodDescriptor->getCode();
500
        }
501
        $str .= $this->generateJsonSerialize();
502
503
        $str .= $this->generateGetUsedTablesCode();
504
505
        $str .= $this->generateOnDeleteCode();
506
507
        $str .= '}
508
';
509
510
        return $str;
511
    }
512
513
    /**
514
     * @param string $beanNamespace
515
     * @param string $beanClassName
516
     *
517
     * @return array first element: list of used beans, second item: PHP code as a string
518
     */
519
    public function generateFindByDaoCode($beanNamespace, $beanClassName)
520
    {
521
        $code = '';
522
        $usedBeans = [];
523
        foreach ($this->removeDuplicateIndexes($this->table->getIndexes()) as $index) {
524
            if (!$index->isPrimary()) {
525
                list($usedBeansForIndex, $codeForIndex) = $this->generateFindByDaoCodeForIndex($index, $beanNamespace, $beanClassName);
526
                $code .= $codeForIndex;
527
                $usedBeans = array_merge($usedBeans, $usedBeansForIndex);
528
            }
529
        }
530
531
        return [$usedBeans, $code];
532
    }
533
534
    /**
535
     * Remove identical indexes (indexes on same columns)
536
     *
537
     * @param Index[] $indexes
538
     * @return Index[]
539
     */
540
    private function removeDuplicateIndexes(array $indexes): array
541
    {
542
        $indexesByKey = [];
543
        foreach ($indexes as $index) {
544
            $indexesByKey[implode('__`__', $index->getColumns())] = $index;
545
        }
546
547
        return array_values($indexesByKey);
548
    }
549
550
    /**
551
     * @param Index  $index
552
     * @param string $beanNamespace
553
     * @param string $beanClassName
554
     *
555
     * @return array first element: list of used beans, second item: PHP code as a string
556
     */
557
    private function generateFindByDaoCodeForIndex(Index $index, $beanNamespace, $beanClassName)
558
    {
559
        $columns = $index->getColumns();
560
        $usedBeans = [];
561
562
        /*
563
         * The list of elements building this index (expressed as columns or foreign keys)
564
         * @var AbstractBeanPropertyDescriptor[]
565
         */
566
        $elements = [];
567
568
        foreach ($columns as $column) {
569
            $fk = $this->isPartOfForeignKey($this->table, $this->table->getColumn($column));
570
            if ($fk !== null) {
571
                if (!in_array($fk, $elements)) {
572
                    $elements[] = new ObjectBeanPropertyDescriptor($this->table, $fk, $this->schemaAnalyzer, $this->namingStrategy);
573
                }
574
            } else {
575
                $elements[] = new ScalarBeanPropertyDescriptor($this->table, $this->table->getColumn($column), $this->namingStrategy);
576
            }
577
        }
578
579
        // If the index is actually only a foreign key, let's bypass it entirely.
580
        if (count($elements) === 1 && $elements[0] instanceof ObjectBeanPropertyDescriptor) {
581
            return [[], ''];
582
        }
583
584
        $functionParameters = [];
585
        $first = true;
586
        foreach ($elements as $element) {
587
            $functionParameter = $element->getClassName();
588
            if ($functionParameter) {
589
                $usedBeans[] = $beanNamespace.'\\'.$functionParameter;
590
                $functionParameter .= ' ';
591
            }
592
            $functionParameter .= $element->getVariableName();
593
            if ($first) {
594
                $first = false;
595
            } else {
596
                $functionParameter .= ' = null';
597
            }
598
            $functionParameters[] = $functionParameter;
599
        }
600
601
        $functionParametersString = implode(', ', $functionParameters);
602
603
        $count = 0;
604
605
        $params = [];
606
        $filterArrayCode = '';
607
        $commentArguments = [];
608
        foreach ($elements as $element) {
609
            $params[] = $element->getParamAnnotation();
610
            if ($element instanceof ScalarBeanPropertyDescriptor) {
611
                $filterArrayCode .= '            '.var_export($element->getColumnName(), true).' => '.$element->getVariableName().",\n";
612
            } else {
613
                ++$count;
614
                $filterArrayCode .= '            '.$count.' => '.$element->getVariableName().",\n";
615
            }
616
            $commentArguments[] = substr($element->getVariableName(), 1);
617
        }
618
        $paramsString = implode("\n", $params);
619
620
        $methodName = $this->namingStrategy->getFindByIndexMethodName($index, $elements);
621
622
        if ($index->isUnique()) {
623
            $returnType = "{$beanClassName}";
624
625
            $code = "
626
    /**
627
     * Get a $beanClassName filtered by ".implode(', ', $commentArguments).".
628
     *
629
$paramsString
630
     * @param array \$additionalTablesFetch A list of additional tables to fetch (for performance improvement)
631
     * @return $returnType
632
     */
633
    public function $methodName($functionParametersString, array \$additionalTablesFetch = array()) : $returnType
634
    {
635
        \$filter = [
636
".$filterArrayCode."        ];
637
        return \$this->findOne(\$filter, [], \$additionalTablesFetch);
638
    }
639
";
640
        } else {
641
            $returnType = "{$beanClassName}[]|ResultIterator|ResultArray";
642
643
            $code = "
644
    /**
645
     * Get a list of $beanClassName filtered by ".implode(', ', $commentArguments).".
646
     *
647
$paramsString
648
     * @param mixed \$orderBy The order string
649
     * @param array \$additionalTablesFetch A list of additional tables to fetch (for performance improvement)
650
     * @param string \$mode Either TDBMService::MODE_ARRAY or TDBMService::MODE_CURSOR (for large datasets). Defaults to TDBMService::MODE_ARRAY.
651
     * @return $returnType
652
     */
653
    public function $methodName($functionParametersString, \$orderBy = null, array \$additionalTablesFetch = array(), \$mode = null) : iterable
654
    {
655
        \$filter = [
656
".$filterArrayCode."        ];
657
        return \$this->find(\$filter, [], \$orderBy, \$additionalTablesFetch, \$mode);
658
    }
659
";
660
        }
661
662
        return [$usedBeans, $code];
663
    }
664
665
    /**
666
     * Generates the code for the getUsedTable protected method.
667
     *
668
     * @return string
669
     */
670
    private function generateGetUsedTablesCode()
671
    {
672
        $hasParentRelationship = $this->schemaAnalyzer->getParentRelationship($this->table->getName()) !== null;
673
        if ($hasParentRelationship) {
674
            $code = sprintf('        $tables = parent::getUsedTables();
675
        $tables[] = %s;
676
677
        return $tables;', var_export($this->table->getName(), true));
678
        } else {
679
            $code = sprintf('        return [ %s ];', var_export($this->table->getName(), true));
680
        }
681
682
        return sprintf('
683
    /**
684
     * Returns an array of used tables by this bean (from parent to child relationship).
685
     *
686
     * @return string[]
687
     */
688
    protected function getUsedTables() : array
689
    {
690
%s
691
    }
692
', $code);
693
    }
694
695
    private function generateOnDeleteCode()
696
    {
697
        $code = '';
698
        $relationships = $this->getPropertiesForTable($this->table);
699
        foreach ($relationships as $relationship) {
700
            if ($relationship instanceof ObjectBeanPropertyDescriptor) {
701
                $code .= sprintf('        $this->setRef('.var_export($relationship->getForeignKey()->getName(), true).', null, '.var_export($this->table->getName(), true).");\n");
702
            }
703
        }
704
705
        if ($code) {
706
            return sprintf('
707
    /**
708
     * Method called when the bean is removed from database.
709
     *
710
     */
711
    protected function onDelete() : void
712
    {
713
        parent::onDelete();
714
%s    }
715
', $code);
716
        }
717
718
        return '';
719
    }
720
721
    /**
722
     * Returns the bean class name (without the namespace).
723
     *
724
     * @return string
725
     */
726
    public function getBeanClassName() : string
727
    {
728
        return $this->namingStrategy->getBeanClassName($this->table->getName());
729
    }
730
731
    /**
732
     * Returns the base bean class name (without the namespace).
733
     *
734
     * @return string
735
     */
736
    public function getBaseBeanClassName() : string
737
    {
738
        return $this->namingStrategy->getBaseBeanClassName($this->table->getName());
739
    }
740
741
    /**
742
     * Returns the DAO class name (without the namespace).
743
     *
744
     * @return string
745
     */
746
    public function getDaoClassName() : string
747
    {
748
        return $this->namingStrategy->getDaoClassName($this->table->getName());
749
    }
750
751
    /**
752
     * Returns the base DAO class name (without the namespace).
753
     *
754
     * @return string
755
     */
756
    public function getBaseDaoClassName() : string
757
    {
758
        return $this->namingStrategy->getBaseDaoClassName($this->table->getName());
759
    }
760
761
    /**
762
     * Returns the table used to build this bean.
763
     *
764
     * @return Table
765
     */
766
    public function getTable(): Table
767
    {
768
        return $this->table;
769
    }
770
771
    /**
772
     * Returns the extended bean class name (without the namespace), or null if the bean is not extended.
773
     *
774
     * @return string
775
     */
776
    public function getExtendedBeanClassName(): ?string
777
    {
778
        $parentFk = $this->schemaAnalyzer->getParentRelationship($this->table->getName());
779
        if ($parentFk !== null) {
780
            return $this->namingStrategy->getBeanClassName($parentFk->getForeignTableName());
781
        } else {
782
            return null;
783
        }
784
    }
785
786
    /**
787
     * @return string
788
     */
789
    public function getBeanNamespace(): string
790
    {
791
        return $this->beanNamespace;
792
    }
793
794
    /**
795
     * @return string
796
     */
797
    public function getGeneratedBeanNamespace(): string
798
    {
799
        return $this->generatedBeanNamespace;
800
    }
801
}
802