Passed
Pull Request — master (#116)
by David
03:10
created

ObjectBeanPropertyDescriptor::getParamAnnotation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
declare(strict_types=1);
3
4
namespace TheCodingMachine\TDBM\Utils;
5
6
use Doctrine\DBAL\Schema\Column;
7
use Doctrine\DBAL\Schema\Table;
8
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
9
use Mouf\Database\SchemaAnalyzer\SchemaAnalyzer;
10
use TheCodingMachine\TDBM\TDBMException;
11
use Zend\Code\Generator\DocBlock\Tag\ParamTag;
12
use Zend\Code\Generator\DocBlock\Tag\ReturnTag;
13
use Zend\Code\Generator\MethodGenerator;
14
use Zend\Code\Generator\ParameterGenerator;
15
16
/**
17
 * This class represent a property in a bean that points to another table.
18
 */
19
class ObjectBeanPropertyDescriptor extends AbstractBeanPropertyDescriptor
20
{
21
    /**
22
     * @var ForeignKeyConstraint
23
     */
24
    private $foreignKey;
25
    /**
26
     * @var string
27
     */
28
    private $beanNamespace;
29
30
    /**
31
     * ObjectBeanPropertyDescriptor constructor.
32
     * @param Table $table
33
     * @param ForeignKeyConstraint $foreignKey
34
     * @param NamingStrategyInterface $namingStrategy
35
     */
36
    public function __construct(Table $table, ForeignKeyConstraint $foreignKey, NamingStrategyInterface $namingStrategy, string $beanNamespace)
37
    {
38
        parent::__construct($table, $namingStrategy);
39
        $this->foreignKey = $foreignKey;
40
        $this->beanNamespace = $beanNamespace;
41
    }
42
43
    /**
44
     * Returns the foreignkey the column is part of, if any. null otherwise.
45
     *
46
     * @return ForeignKeyConstraint
47
     */
48
    public function getForeignKey(): ForeignKeyConstraint
49
    {
50
        return $this->foreignKey;
51
    }
52
53
    /**
54
     * Returns the name of the class linked to this property or null if this is not a foreign key.
55
     *
56
     * @return string
57
     */
58
    public function getClassName(): string
59
    {
60
        return $this->namingStrategy->getBeanClassName($this->foreignKey->getForeignTableName());
61
    }
62
63
    /**
64
     * Returns the PHP type for the property (it can be a scalar like int, bool, or class names, like \DateTimeInterface, App\Bean\User....)
65
     *
66
     * @return string
67
     */
68
    public function getPhpType(): string
69
    {
70
        return '\\'.$this->beanNamespace.'\\'.$this->getClassName();
71
    }
72
73
    /**
74
     * Returns true if the property is compulsory (and therefore should be fetched in the constructor).
75
     *
76
     * @return bool
77
     */
78
    public function isCompulsory(): bool
79
    {
80
        // Are all columns nullable?
81
        $localColumnNames = $this->foreignKey->getUnquotedLocalColumns();
82
83
        foreach ($localColumnNames as $name) {
84
            $column = $this->table->getColumn($name);
85
            if ($column->getNotnull()) {
86
                return true;
87
            }
88
        }
89
90
        return false;
91
    }
92
93
    /**
94
     * Returns true if the property has a default value.
95
     *
96
     * @return bool
97
     */
98
    public function hasDefault(): bool
99
    {
100
        return false;
101
    }
102
103
    /**
104
     * Returns the code that assigns a value to its default value.
105
     *
106
     * @return string
107
     *
108
     * @throws TDBMException
109
     */
110
    public function assignToDefaultCode(): string
111
    {
112
        throw new TDBMException('Foreign key based properties cannot be assigned a default value.');
113
    }
114
115
    /**
116
     * Returns true if the property is the primary key.
117
     *
118
     * @return bool
119
     */
120
    public function isPrimaryKey(): bool
121
    {
122
        $fkColumns = $this->foreignKey->getUnquotedLocalColumns();
123
        sort($fkColumns);
124
125
        $pkColumns = TDBMDaoGenerator::getPrimaryKeyColumnsOrFail($this->table);
126
        sort($pkColumns);
127
128
        return $fkColumns == $pkColumns;
129
    }
130
131
    /**
132
     * Returns the PHP code for getters and setters.
133
     *
134
     * @return MethodGenerator[]
135
     */
136
    public function getGetterSetterCode(): array
137
    {
138
        $tableName = $this->table->getName();
139
        $getterName = $this->getGetterName();
140
        $setterName = $this->getSetterName();
141
        $isNullable = !$this->isCompulsory();
142
143
        $referencedBeanName = $this->namingStrategy->getBeanClassName($this->foreignKey->getForeignTableName());
144
145
        $getter = new MethodGenerator($getterName);
146
        $getter->setDocBlock('Returns the '.$referencedBeanName.' object bound to this object via the '.implode(' and ', $this->foreignKey->getUnquotedLocalColumns()).' column.');
147
148
        /*$types = [ $referencedBeanName ];
149
        if ($isNullable) {
150
            $types[] = 'null';
151
        }
152
        $getter->getDocBlock()->setTag(new ReturnTag($types));*/
153
154
        $getter->setReturnType(($isNullable?'?':'').$this->beanNamespace.'\\'.$referencedBeanName);
155
156
        $getter->setBody('return $this->getRef('.var_export($this->foreignKey->getName(), true).', '.var_export($tableName, true).');');
157
158
        $setter = new MethodGenerator($setterName);
159
        $setter->setDocBlock('The setter for the '.$referencedBeanName.' object bound to this object via the '.implode(' and ', $this->foreignKey->getUnquotedLocalColumns()).' column.');
160
161
        $setter->setParameter(new ParameterGenerator('object', ($isNullable?'?':'').$this->beanNamespace.'\\'.$referencedBeanName));
162
163
        $setter->setReturnType('void');
164
165
        $setter->setBody('$this->setRef('.var_export($this->foreignKey->getName(), true).', $object, '.var_export($tableName, true).');');
166
167
        return [$getter, $setter];
168
    }
169
170
    /**
171
     * Returns the part of code useful when doing json serialization.
172
     *
173
     * @return string
174
     */
175
    public function getJsonSerializeCode(): string
176
    {
177
        if (!$this->isCompulsory()) {
178
            return 'if (!$stopRecursion) {
179
    $object = $this->'.$this->getGetterName().'();
180
    $array['.var_export($this->namingStrategy->getJsonProperty($this), true).'] = $object ? $object->jsonSerialize(true) : null;
181
}
182
';
183
        } else {
184
            return 'if (!$stopRecursion) {
185
    $array['.var_export($this->namingStrategy->getJsonProperty($this), true).'] = $this->'.$this->getGetterName().'()->jsonSerialize(true);
186
}
187
';
188
        }
189
    }
190
191
    /**
192
     * The code to past in the __clone method.
193
     * @return null|string
194
     */
195
    public function getCloneRule(): ?string
196
    {
197
        return null;
198
    }
199
200
    /**
201
     * Tells if this property is a type-hintable in PHP (resource isn't for example)
202
     *
203
     * @return bool
204
     */
205
    public function isTypeHintable() : bool
206
    {
207
        return true;
208
    }
209
}
210