Passed
Pull Request — master (#68)
by David
03:59 queued 44s
created

BeanDescriptor::generateGetUsedTablesCode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
cc 2
eloc 8
nc 2
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 .= $this->generateCloneCode();
507
508
        $str .= '}
509
';
510
511
        return $str;
512
    }
513
514
    /**
515
     * @param string $beanNamespace
516
     * @param string $beanClassName
517
     *
518
     * @return array first element: list of used beans, second item: PHP code as a string
519
     */
520
    public function generateFindByDaoCode($beanNamespace, $beanClassName)
521
    {
522
        $code = '';
523
        $usedBeans = [];
524
        foreach ($this->removeDuplicateIndexes($this->table->getIndexes()) as $index) {
525
            if (!$index->isPrimary()) {
526
                list($usedBeansForIndex, $codeForIndex) = $this->generateFindByDaoCodeForIndex($index, $beanNamespace, $beanClassName);
527
                $code .= $codeForIndex;
528
                $usedBeans = array_merge($usedBeans, $usedBeansForIndex);
529
            }
530
        }
531
532
        return [$usedBeans, $code];
533
    }
534
535
    /**
536
     * Remove identical indexes (indexes on same columns)
537
     *
538
     * @param Index[] $indexes
539
     * @return Index[]
540
     */
541
    private function removeDuplicateIndexes(array $indexes): array
542
    {
543
        $indexesByKey = [];
544
        foreach ($indexes as $index) {
545
            $indexesByKey[implode('__`__', $index->getUnquotedColumns())] = $index;
546
        }
547
548
        return array_values($indexesByKey);
549
    }
550
551
    /**
552
     * @param Index  $index
553
     * @param string $beanNamespace
554
     * @param string $beanClassName
555
     *
556
     * @return array first element: list of used beans, second item: PHP code as a string
557
     */
558
    private function generateFindByDaoCodeForIndex(Index $index, $beanNamespace, $beanClassName)
559
    {
560
        $columns = $index->getColumns();
561
        $usedBeans = [];
562
563
        /*
564
         * The list of elements building this index (expressed as columns or foreign keys)
565
         * @var AbstractBeanPropertyDescriptor[]
566
         */
567
        $elements = [];
568
569
        foreach ($columns as $column) {
570
            $fk = $this->isPartOfForeignKey($this->table, $this->table->getColumn($column));
571
            if ($fk !== null) {
572
                if (!in_array($fk, $elements)) {
573
                    $elements[] = new ObjectBeanPropertyDescriptor($this->table, $fk, $this->schemaAnalyzer, $this->namingStrategy);
574
                }
575
            } else {
576
                $elements[] = new ScalarBeanPropertyDescriptor($this->table, $this->table->getColumn($column), $this->namingStrategy);
577
            }
578
        }
579
580
        // If the index is actually only a foreign key, let's bypass it entirely.
581
        if (count($elements) === 1 && $elements[0] instanceof ObjectBeanPropertyDescriptor) {
582
            return [[], ''];
583
        }
584
585
        $functionParameters = [];
586
        $first = true;
587
        foreach ($elements as $element) {
588
            $functionParameter = $element->getClassName();
589
            if ($functionParameter) {
590
                $usedBeans[] = $beanNamespace.'\\'.$functionParameter;
591
                $functionParameter .= ' ';
592
            }
593
            $functionParameter .= $element->getVariableName();
594
            if ($first) {
595
                $first = false;
596
            } else {
597
                $functionParameter .= ' = null';
598
            }
599
            $functionParameters[] = $functionParameter;
600
        }
601
602
        $functionParametersString = implode(', ', $functionParameters);
603
604
        $count = 0;
605
606
        $params = [];
607
        $filterArrayCode = '';
608
        $commentArguments = [];
609
        foreach ($elements as $element) {
610
            $params[] = $element->getParamAnnotation();
611
            if ($element instanceof ScalarBeanPropertyDescriptor) {
612
                $filterArrayCode .= '            '.var_export($element->getColumnName(), true).' => '.$element->getVariableName().",\n";
613
            } else {
614
                ++$count;
615
                $filterArrayCode .= '            '.$count.' => '.$element->getVariableName().",\n";
616
            }
617
            $commentArguments[] = substr($element->getVariableName(), 1);
618
        }
619
        $paramsString = implode("\n", $params);
620
621
        $methodName = $this->namingStrategy->getFindByIndexMethodName($index, $elements);
622
623
        if ($index->isUnique()) {
624
            $returnType = $beanClassName;
625
626
            $code = "
627
    /**
628
     * Get a $beanClassName filtered by ".implode(', ', $commentArguments).".
629
     *
630
$paramsString
631
     * @param array \$additionalTablesFetch A list of additional tables to fetch (for performance improvement)
632
     * @return $returnType|null
633
     */
634
    public function $methodName($functionParametersString, array \$additionalTablesFetch = array()) : ?$returnType
635
    {
636
        \$filter = [
637
".$filterArrayCode."        ];
638
        return \$this->findOne(\$filter, [], \$additionalTablesFetch);
639
    }
640
";
641
        } else {
642
            $returnType = "{$beanClassName}[]|ResultIterator";
643
644
            $code = "
645
    /**
646
     * Get a list of $beanClassName filtered by ".implode(', ', $commentArguments).".
647
     *
648
$paramsString
649
     * @param mixed \$orderBy The order string
650
     * @param array \$additionalTablesFetch A list of additional tables to fetch (for performance improvement)
651
     * @param int \$mode Either TDBMService::MODE_ARRAY or TDBMService::MODE_CURSOR (for large datasets). Defaults to TDBMService::MODE_ARRAY.
652
     * @return $returnType
653
     */
654
    public function $methodName($functionParametersString, \$orderBy = null, array \$additionalTablesFetch = array(), ?int \$mode = null) : iterable
655
    {
656
        \$filter = [
657
".$filterArrayCode."        ];
658
        return \$this->find(\$filter, [], \$orderBy, \$additionalTablesFetch, \$mode);
659
    }
660
";
661
        }
662
663
        return [$usedBeans, $code];
664
    }
665
666
    /**
667
     * Generates the code for the getUsedTable protected method.
668
     *
669
     * @return string
670
     */
671
    private function generateGetUsedTablesCode()
672
    {
673
        $hasParentRelationship = $this->schemaAnalyzer->getParentRelationship($this->table->getName()) !== null;
674
        if ($hasParentRelationship) {
675
            $code = sprintf('        $tables = parent::getUsedTables();
676
        $tables[] = %s;
677
678
        return $tables;', var_export($this->table->getName(), true));
679
        } else {
680
            $code = sprintf('        return [ %s ];', var_export($this->table->getName(), true));
681
        }
682
683
        return sprintf('
684
    /**
685
     * Returns an array of used tables by this bean (from parent to child relationship).
686
     *
687
     * @return string[]
688
     */
689
    protected function getUsedTables() : array
690
    {
691
%s
692
    }
693
', $code);
694
    }
695
696
    private function generateOnDeleteCode()
697
    {
698
        $code = '';
699
        $relationships = $this->getPropertiesForTable($this->table);
700
        foreach ($relationships as $relationship) {
701
            if ($relationship instanceof ObjectBeanPropertyDescriptor) {
702
                $code .= sprintf('        $this->setRef('.var_export($relationship->getForeignKey()->getName(), true).', null, '.var_export($this->table->getName(), true).");\n");
703
            }
704
        }
705
706
        if ($code) {
707
            return sprintf('
708
    /**
709
     * Method called when the bean is removed from database.
710
     *
711
     */
712
    protected function onDelete() : void
713
    {
714
        parent::onDelete();
715
%s    }
716
', $code);
717
        }
718
719
        return '';
720
    }
721
722
    private function generateCloneCode(): string
723
    {
724
        $code = '';
725
726
        foreach ($this->beanPropertyDescriptors as $beanPropertyDescriptor) {
727
            $code .= $beanPropertyDescriptor->getCloneRule();
728
        }
729
730
        if (!empty($code)) {
0 ignored issues
show
introduced by
The condition ! empty($code) can never be true.
Loading history...
731
            $code = '
732
    public function __clone()
733
    {
734
        parent::__clone();
735
'.$code.'    }
736
';
737
        }
738
739
        return $code;
740
    }
741
742
    /**
743
     * Returns the bean class name (without the namespace).
744
     *
745
     * @return string
746
     */
747
    public function getBeanClassName() : string
748
    {
749
        return $this->namingStrategy->getBeanClassName($this->table->getName());
750
    }
751
752
    /**
753
     * Returns the base bean class name (without the namespace).
754
     *
755
     * @return string
756
     */
757
    public function getBaseBeanClassName() : string
758
    {
759
        return $this->namingStrategy->getBaseBeanClassName($this->table->getName());
760
    }
761
762
    /**
763
     * Returns the DAO class name (without the namespace).
764
     *
765
     * @return string
766
     */
767
    public function getDaoClassName() : string
768
    {
769
        return $this->namingStrategy->getDaoClassName($this->table->getName());
770
    }
771
772
    /**
773
     * Returns the base DAO class name (without the namespace).
774
     *
775
     * @return string
776
     */
777
    public function getBaseDaoClassName() : string
778
    {
779
        return $this->namingStrategy->getBaseDaoClassName($this->table->getName());
780
    }
781
782
    /**
783
     * Returns the table used to build this bean.
784
     *
785
     * @return Table
786
     */
787
    public function getTable(): Table
788
    {
789
        return $this->table;
790
    }
791
792
    /**
793
     * Returns the extended bean class name (without the namespace), or null if the bean is not extended.
794
     *
795
     * @return string
796
     */
797
    public function getExtendedBeanClassName(): ?string
798
    {
799
        $parentFk = $this->schemaAnalyzer->getParentRelationship($this->table->getName());
800
        if ($parentFk !== null) {
801
            return $this->namingStrategy->getBeanClassName($parentFk->getForeignTableName());
802
        } else {
803
            return null;
804
        }
805
    }
806
807
    /**
808
     * @return string
809
     */
810
    public function getBeanNamespace(): string
811
    {
812
        return $this->beanNamespace;
813
    }
814
815
    /**
816
     * @return string
817
     */
818
    public function getGeneratedBeanNamespace(): string
819
    {
820
        return $this->generatedBeanNamespace;
821
    }
822
}
823