Completed
Push — master ( 4f6e3e...f0f2c4 )
by David
16s queued 10s
created

BeanDescriptor::getMethodDescriptors()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.5125
c 0
b 0
f 0
cc 5
eloc 12
nc 8
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->getUnquotedLocalColumns() as $columnName) {
96
                if ($columnName === $localColumnName) {
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
        if ($table->getPrimaryKey() === null) {
166
            // Security check: a table MUST have a primary key
167
            throw new TDBMException(sprintf('Table "%s" does not have any primary key', $table->getName()));
168
        }
169
170
        $parentRelationship = $this->schemaAnalyzer->getParentRelationship($table->getName());
171
        if ($parentRelationship) {
172
            $parentTable = $this->schema->getTable($parentRelationship->getForeignTableName());
173
            $properties = $this->getProperties($parentTable);
174
            // we merge properties by overriding property names.
175
            $localProperties = $this->getPropertiesForTable($table);
176
            foreach ($localProperties as $name => $property) {
177
                // We do not override properties if this is a primary key!
178
                if ($property->isPrimaryKey()) {
179
                    continue;
180
                }
181
                $properties[$name] = $property;
182
            }
183
        } else {
184
            $properties = $this->getPropertiesForTable($table);
185
        }
186
187
        return $properties;
188
    }
189
190
    /**
191
     * Returns the list of properties for this table (ignoring parent tables).
192
     *
193
     * @param Table $table
194
     *
195
     * @return AbstractBeanPropertyDescriptor[]
196
     */
197
    private function getPropertiesForTable(Table $table)
198
    {
199
        $parentRelationship = $this->schemaAnalyzer->getParentRelationship($table->getName());
200
        if ($parentRelationship) {
201
            $ignoreColumns = $parentRelationship->getUnquotedLocalColumns();
202
        } else {
203
            $ignoreColumns = [];
204
        }
205
206
        $beanPropertyDescriptors = [];
207
        foreach ($table->getColumns() as $column) {
208
            if (array_search($column->getName(), $ignoreColumns) !== false) {
209
                continue;
210
            }
211
212
            $fk = $this->isPartOfForeignKey($table, $column);
213
            if ($fk !== null) {
214
                // Check that previously added descriptors are not added on same FK (can happen with multi key FK).
215
                foreach ($beanPropertyDescriptors as $beanDescriptor) {
216
                    if ($beanDescriptor instanceof ObjectBeanPropertyDescriptor && $beanDescriptor->getForeignKey() === $fk) {
217
                        continue 2;
218
                    }
219
                }
220
                // Check that this property is not an inheritance relationship
221
                $parentRelationship = $this->schemaAnalyzer->getParentRelationship($table->getName());
222
                if ($parentRelationship === $fk) {
223
                    continue;
224
                }
225
226
                $beanPropertyDescriptors[] = new ObjectBeanPropertyDescriptor($table, $fk, $this->schemaAnalyzer, $this->namingStrategy);
227
            } else {
228
                $beanPropertyDescriptors[] = new ScalarBeanPropertyDescriptor($table, $column, $this->namingStrategy);
229
            }
230
        }
231
232
        // Now, let's get the name of all properties and let's check there is no duplicate.
233
        /** @var $names AbstractBeanPropertyDescriptor[] */
234
        $names = [];
235
        foreach ($beanPropertyDescriptors as $beanDescriptor) {
236
            $name = $beanDescriptor->getGetterName();
237
            if (isset($names[$name])) {
238
                $names[$name]->useAlternativeName();
239
                $beanDescriptor->useAlternativeName();
240
            } else {
241
                $names[$name] = $beanDescriptor;
242
            }
243
        }
244
245
        // Final check (throw exceptions if problem arises)
246
        $names = [];
247
        foreach ($beanPropertyDescriptors as $beanDescriptor) {
248
            $name = $beanDescriptor->getGetterName();
249
            if (isset($names[$name])) {
250
                throw new TDBMException('Unsolvable name conflict while generating method name');
251
            } else {
252
                $names[$name] = $beanDescriptor;
253
            }
254
        }
255
256
        // Last step, let's rebuild the list with a map:
257
        $beanPropertyDescriptorsMap = [];
258
        foreach ($beanPropertyDescriptors as $beanDescriptor) {
259
            $beanPropertyDescriptorsMap[$beanDescriptor->getVariableName()] = $beanDescriptor;
260
        }
261
262
        return $beanPropertyDescriptorsMap;
263
    }
264
265
    private function generateBeanConstructor() : string
266
    {
267
        $constructorProperties = $this->getConstructorProperties();
268
269
        $constructorCode = '    /**
270
     * The constructor takes all compulsory arguments.
271
     *
272
%s
273
     */
274
    public function __construct(%s)
275
    {
276
%s%s    }
277
278
';
279
280
        $paramAnnotations = [];
281
        $arguments = [];
282
        $assigns = [];
283
        $parentConstructorArguments = [];
284
285
        foreach ($constructorProperties as $property) {
286
            $arguments[] = $property->getPhpType().' '.$property->getVariableName();
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->getExposedProperties() 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\\AlterableResultIterator;
476
use Ramsey\\Uuid\\Uuid;
477
$use
478
/*
479
 * This file has been automatically generated by TDBM.
480
 * DO NOT edit this file, as it might be overwritten.
481
 * If you need to perform changes, edit the $className class instead!
482
 */
483
484
/**
485
 * The $baseClassName class maps the '$tableName' table in database.
486
 */
487
abstract class $baseClassName extends $extends implements \\JsonSerializable
488
{
489
";
490
491
        $str .= $this->generateBeanConstructor();
492
493
        foreach ($this->getExposedProperties() as $property) {
494
            $str .= $property->getGetterSetterCode();
495
        }
496
497
        foreach ($this->getMethodDescriptors() as $methodDescriptor) {
498
            $str .= $methodDescriptor->getCode();
499
        }
500
        $str .= $this->generateJsonSerialize();
501
502
        $str .= $this->generateGetUsedTablesCode();
503
504
        $str .= $this->generateOnDeleteCode();
505
506
        $str .= '}
507
';
508
509
        return $str;
510
    }
511
512
    /**
513
     * @param string $beanNamespace
514
     * @param string $beanClassName
515
     *
516
     * @return array first element: list of used beans, second item: PHP code as a string
517
     */
518
    public function generateFindByDaoCode($beanNamespace, $beanClassName)
519
    {
520
        $code = '';
521
        $usedBeans = [];
522
        foreach ($this->removeDuplicateIndexes($this->table->getIndexes()) as $index) {
523
            if (!$index->isPrimary()) {
524
                list($usedBeansForIndex, $codeForIndex) = $this->generateFindByDaoCodeForIndex($index, $beanNamespace, $beanClassName);
525
                $code .= $codeForIndex;
526
                $usedBeans = array_merge($usedBeans, $usedBeansForIndex);
527
            }
528
        }
529
530
        return [$usedBeans, $code];
531
    }
532
533
    /**
534
     * Remove identical indexes (indexes on same columns)
535
     *
536
     * @param Index[] $indexes
537
     * @return Index[]
538
     */
539
    private function removeDuplicateIndexes(array $indexes): array
540
    {
541
        $indexesByKey = [];
542
        foreach ($indexes as $index) {
543
            $indexesByKey[implode('__`__', $index->getUnquotedColumns())] = $index;
544
        }
545
546
        return array_values($indexesByKey);
547
    }
548
549
    /**
550
     * @param Index  $index
551
     * @param string $beanNamespace
552
     * @param string $beanClassName
553
     *
554
     * @return array first element: list of used beans, second item: PHP code as a string
555
     */
556
    private function generateFindByDaoCodeForIndex(Index $index, $beanNamespace, $beanClassName)
557
    {
558
        $columns = $index->getColumns();
559
        $usedBeans = [];
560
561
        /*
562
         * The list of elements building this index (expressed as columns or foreign keys)
563
         * @var AbstractBeanPropertyDescriptor[]
564
         */
565
        $elements = [];
566
567
        foreach ($columns as $column) {
568
            $fk = $this->isPartOfForeignKey($this->table, $this->table->getColumn($column));
569
            if ($fk !== null) {
570
                if (!in_array($fk, $elements)) {
571
                    $elements[] = new ObjectBeanPropertyDescriptor($this->table, $fk, $this->schemaAnalyzer, $this->namingStrategy);
572
                }
573
            } else {
574
                $elements[] = new ScalarBeanPropertyDescriptor($this->table, $this->table->getColumn($column), $this->namingStrategy);
575
            }
576
        }
577
578
        // If the index is actually only a foreign key, let's bypass it entirely.
579
        if (count($elements) === 1 && $elements[0] instanceof ObjectBeanPropertyDescriptor) {
580
            return [[], ''];
581
        }
582
583
        $functionParameters = [];
584
        $first = true;
585
        foreach ($elements as $element) {
586
            $functionParameter = $element->getClassName();
587
            if ($functionParameter) {
588
                $usedBeans[] = $beanNamespace.'\\'.$functionParameter;
589
                $functionParameter .= ' ';
590
            }
591
            $functionParameter .= $element->getVariableName();
592
            if ($first) {
593
                $first = false;
594
            } else {
595
                $functionParameter .= ' = null';
596
            }
597
            $functionParameters[] = $functionParameter;
598
        }
599
600
        $functionParametersString = implode(', ', $functionParameters);
601
602
        $count = 0;
603
604
        $params = [];
605
        $filterArrayCode = '';
606
        $commentArguments = [];
607
        foreach ($elements as $element) {
608
            $params[] = $element->getParamAnnotation();
609
            if ($element instanceof ScalarBeanPropertyDescriptor) {
610
                $filterArrayCode .= '            '.var_export($element->getColumnName(), true).' => '.$element->getVariableName().",\n";
611
            } else {
612
                ++$count;
613
                $filterArrayCode .= '            '.$count.' => '.$element->getVariableName().",\n";
614
            }
615
            $commentArguments[] = substr($element->getVariableName(), 1);
616
        }
617
        $paramsString = implode("\n", $params);
618
619
        $methodName = $this->namingStrategy->getFindByIndexMethodName($index, $elements);
620
621
        if ($index->isUnique()) {
622
            $returnType = $beanClassName;
623
624
            $code = "
625
    /**
626
     * Get a $beanClassName filtered by ".implode(', ', $commentArguments).".
627
     *
628
$paramsString
629
     * @param array \$additionalTablesFetch A list of additional tables to fetch (for performance improvement)
630
     * @return $returnType|null
631
     */
632
    public function $methodName($functionParametersString, array \$additionalTablesFetch = array()) : ?$returnType
633
    {
634
        \$filter = [
635
".$filterArrayCode."        ];
636
        return \$this->findOne(\$filter, [], \$additionalTablesFetch);
637
    }
638
";
639
        } else {
640
            $returnType = "{$beanClassName}[]|ResultIterator";
641
642
            $code = "
643
    /**
644
     * Get a list of $beanClassName filtered by ".implode(', ', $commentArguments).".
645
     *
646
$paramsString
647
     * @param mixed \$orderBy The order string
648
     * @param array \$additionalTablesFetch A list of additional tables to fetch (for performance improvement)
649
     * @param int \$mode Either TDBMService::MODE_ARRAY or TDBMService::MODE_CURSOR (for large datasets). Defaults to TDBMService::MODE_ARRAY.
650
     * @return $returnType
651
     */
652
    public function $methodName($functionParametersString, \$orderBy = null, array \$additionalTablesFetch = array(), ?int \$mode = null) : iterable
653
    {
654
        \$filter = [
655
".$filterArrayCode."        ];
656
        return \$this->find(\$filter, [], \$orderBy, \$additionalTablesFetch, \$mode);
657
    }
658
";
659
        }
660
661
        return [$usedBeans, $code];
662
    }
663
664
    /**
665
     * Generates the code for the getUsedTable protected method.
666
     *
667
     * @return string
668
     */
669
    private function generateGetUsedTablesCode()
670
    {
671
        $hasParentRelationship = $this->schemaAnalyzer->getParentRelationship($this->table->getName()) !== null;
672
        if ($hasParentRelationship) {
673
            $code = sprintf('        $tables = parent::getUsedTables();
674
        $tables[] = %s;
675
676
        return $tables;', var_export($this->table->getName(), true));
677
        } else {
678
            $code = sprintf('        return [ %s ];', var_export($this->table->getName(), true));
679
        }
680
681
        return sprintf('
682
    /**
683
     * Returns an array of used tables by this bean (from parent to child relationship).
684
     *
685
     * @return string[]
686
     */
687
    protected function getUsedTables() : array
688
    {
689
%s
690
    }
691
', $code);
692
    }
693
694
    private function generateOnDeleteCode()
695
    {
696
        $code = '';
697
        $relationships = $this->getPropertiesForTable($this->table);
698
        foreach ($relationships as $relationship) {
699
            if ($relationship instanceof ObjectBeanPropertyDescriptor) {
700
                $code .= sprintf('        $this->setRef('.var_export($relationship->getForeignKey()->getName(), true).', null, '.var_export($this->table->getName(), true).");\n");
701
            }
702
        }
703
704
        if ($code) {
705
            return sprintf('
706
    /**
707
     * Method called when the bean is removed from database.
708
     *
709
     */
710
    protected function onDelete() : void
711
    {
712
        parent::onDelete();
713
%s    }
714
', $code);
715
        }
716
717
        return '';
718
    }
719
720
    /**
721
     * Returns the bean class name (without the namespace).
722
     *
723
     * @return string
724
     */
725
    public function getBeanClassName() : string
726
    {
727
        return $this->namingStrategy->getBeanClassName($this->table->getName());
728
    }
729
730
    /**
731
     * Returns the base bean class name (without the namespace).
732
     *
733
     * @return string
734
     */
735
    public function getBaseBeanClassName() : string
736
    {
737
        return $this->namingStrategy->getBaseBeanClassName($this->table->getName());
738
    }
739
740
    /**
741
     * Returns the DAO class name (without the namespace).
742
     *
743
     * @return string
744
     */
745
    public function getDaoClassName() : string
746
    {
747
        return $this->namingStrategy->getDaoClassName($this->table->getName());
748
    }
749
750
    /**
751
     * Returns the base DAO class name (without the namespace).
752
     *
753
     * @return string
754
     */
755
    public function getBaseDaoClassName() : string
756
    {
757
        return $this->namingStrategy->getBaseDaoClassName($this->table->getName());
758
    }
759
760
    /**
761
     * Returns the table used to build this bean.
762
     *
763
     * @return Table
764
     */
765
    public function getTable(): Table
766
    {
767
        return $this->table;
768
    }
769
770
    /**
771
     * Returns the extended bean class name (without the namespace), or null if the bean is not extended.
772
     *
773
     * @return string
774
     */
775
    public function getExtendedBeanClassName(): ?string
776
    {
777
        $parentFk = $this->schemaAnalyzer->getParentRelationship($this->table->getName());
778
        if ($parentFk !== null) {
779
            return $this->namingStrategy->getBeanClassName($parentFk->getForeignTableName());
780
        } else {
781
            return null;
782
        }
783
    }
784
785
    /**
786
     * @return string
787
     */
788
    public function getBeanNamespace(): string
789
    {
790
        return $this->beanNamespace;
791
    }
792
793
    /**
794
     * @return string
795
     */
796
    public function getGeneratedBeanNamespace(): string
797
    {
798
        return $this->generatedBeanNamespace;
799
    }
800
}
801