Passed
Pull Request — master (#125)
by David
03:21
created

DirectForeignKeyMethodDescriptor::isProtected()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace TheCodingMachine\TDBM\Utils;
6
7
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
8
use Doctrine\DBAL\Schema\Table;
9
use TheCodingMachine\TDBM\AlterableResultIterator;
10
use TheCodingMachine\TDBM\TDBMException;
11
use TheCodingMachine\TDBM\Utils\Annotation\AnnotationParser;
12
use Zend\Code\Generator\AbstractMemberGenerator;
13
use Zend\Code\Generator\DocBlock\Tag\ReturnTag;
14
use Zend\Code\Generator\MethodGenerator;
15
16
/**
17
 * Represents a method to get a list of beans from a direct foreign key pointing to our bean.
18
 */
19
class DirectForeignKeyMethodDescriptor implements MethodDescriptorInterface
20
{
21
    use ForeignKeyAnalyzerTrait;
22
23
    /**
24
     * @var ForeignKeyConstraint
25
     */
26
    private $foreignKey;
27
28
    private $useAlternateName = false;
29
    /**
30
     * @var Table
31
     */
32
    private $mainTable;
33
    /**
34
     * @var NamingStrategyInterface
35
     */
36
    private $namingStrategy;
37
    /**
38
     * @var AnnotationParser
39
     */
40
    private $annotationParser;
41
42
    /**
43
     * @param ForeignKeyConstraint $fk The foreign key pointing to our bean
44
     * @param Table $mainTable The main table that is pointed to
45
     * @param NamingStrategyInterface $namingStrategy
46
     */
47
    public function __construct(ForeignKeyConstraint $fk, Table $mainTable, NamingStrategyInterface $namingStrategy, AnnotationParser $annotationParser)
48
    {
49
        $this->foreignKey = $fk;
50
        $this->mainTable = $mainTable;
51
        $this->namingStrategy = $namingStrategy;
52
        $this->annotationParser = $annotationParser;
53
    }
54
55
    /**
56
     * Returns the name of the method to be generated.
57
     *
58
     * @return string
59
     */
60
    public function getName() : string
61
    {
62
        if (!$this->useAlternateName) {
63
            return 'get'.TDBMDaoGenerator::toCamelCase($this->foreignKey->getLocalTableName());
64
        } else {
65
            $methodName = 'get'.TDBMDaoGenerator::toCamelCase($this->foreignKey->getLocalTableName()).'By';
66
67
            $camelizedColumns = array_map([TDBMDaoGenerator::class, 'toCamelCase'], $this->foreignKey->getUnquotedLocalColumns());
68
69
            $methodName .= implode('And', $camelizedColumns);
70
71
            return $methodName;
72
        }
73
    }
74
75
    /**
76
     * Returns the name of the class that will be returned by the getter (short name).
77
     *
78
     * @return string
79
     */
80
    public function getBeanClassName(): string
81
    {
82
        return $this->namingStrategy->getBeanClassName($this->foreignKey->getLocalTableName());
83
    }
84
85
    /**
86
     * Requests the use of an alternative name for this method.
87
     */
88
    public function useAlternativeName(): void
89
    {
90
        $this->useAlternateName = true;
91
    }
92
93
    /**
94
     * Returns the code of the method.
95
     *
96
     * @return MethodGenerator[]
97
     */
98
    public function getCode() : array
99
    {
100
        $beanClass = $this->getBeanClassName();
101
102
        $getter = new MethodGenerator($this->getName());
103
        $getter->setDocBlock(sprintf('Returns the list of %s pointing to this bean via the %s column.', $beanClass, implode(', ', $this->foreignKey->getUnquotedLocalColumns())));
104
        $getter->getDocBlock()->setTag(new ReturnTag([
105
            $beanClass.'[]',
106
            '\\'.AlterableResultIterator::class
107
        ]));
108
        $getter->setReturnType(AlterableResultIterator::class);
109
110
        $code = sprintf(
111
            'return $this->retrieveManyToOneRelationshipsStorage(%s, %s, %s, %s);',
112
            var_export($this->foreignKey->getLocalTableName(), true),
113
            var_export($this->foreignKey->getName(), true),
114
            var_export($this->foreignKey->getLocalTableName(), true),
115
            $this->getFilters($this->foreignKey)
116
        );
117
118
        $getter->setBody($code);
119
120
        if ($this->isProtected()) {
121
            $getter->setVisibility(AbstractMemberGenerator::VISIBILITY_PROTECTED);
122
        }
123
124
        return [ $getter ];
125
    }
126
127
    private function getFilters(ForeignKeyConstraint $fk) : string
128
    {
129
        $counter = 0;
130
        $parameters = [];
131
132
        $fkForeignColumns = $fk->getUnquotedForeignColumns();
133
134
        foreach ($fk->getUnquotedLocalColumns() as $columnName) {
135
            $fkColumn = $fkForeignColumns[$counter];
136
            $parameters[] = sprintf('%s => $this->get(%s, %s)', var_export($fk->getLocalTableName().'.'.$columnName, true), var_export($fkColumn, true), var_export($this->foreignKey->getForeignTableName(), true));
137
            ++$counter;
138
        }
139
        $parametersCode = '['.implode(', ', $parameters).']';
140
141
        return $parametersCode;
142
    }
143
144
    /**
145
     * Returns an array of classes that needs a "use" for this method.
146
     *
147
     * @return string[]
148
     */
149
    public function getUsedClasses() : array
150
    {
151
        return [$this->getBeanClassName()];
152
    }
153
154
    /**
155
     * Returns the code to past in jsonSerialize.
156
     *
157
     * @return string
158
     */
159
    public function getJsonSerializeCode() : string
160
    {
161
        return '';
162
    }
163
164
    /**
165
     * @return ForeignKeyConstraint
166
     */
167
    public function getForeignKey(): ForeignKeyConstraint
168
    {
169
        return $this->foreignKey;
170
    }
171
172
    /**
173
     * Returns the table that is pointed to.
174
     * @return Table
175
     */
176
    public function getMainTable(): Table
177
    {
178
        return $this->mainTable;
179
    }
180
181
    private function isProtected(): bool
182
    {
183
        foreach ($this->getAnnotations() as $annotations) {
184
            if ($annotations->findAnnotation(Annotation\ProtectedOneToMany::class)) {
185
                return true;
186
            }
187
        }
188
        return false;
189
    }
190
}
191