Completed
Push — master ( 6dc464...8b1d35 )
by Mike
03:37
created

DataProviderGenerator::getDefaultValue()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 10
nc 8
nop 1
dl 0
loc 13
ccs 11
cts 11
cp 1
crap 8
rs 8.4444
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
5
namespace Xervice\DataProvider\Business\Model\Generator;
6
7
8
use Nette\PhpGenerator\ClassType;
9
use Nette\PhpGenerator\Helpers;
10
use Nette\PhpGenerator\PhpNamespace;
11
use Xervice\DataProvider\Business\Model\DataProvider\DataProviderInterface;
12
use Xervice\DataProvider\Business\Model\Parser\DataProviderParserInterface;
13
14
class DataProviderGenerator implements DataProviderGeneratorInterface
15
{
16
    /**
17
     * @var \Xervice\DataProvider\Business\Model\Parser\DataProviderParserInterface
18
     */
19
    private $parser;
20
21
    /**
22
     * @var FileWriterInterface
23
     */
24
    private $fileWriter;
25
26
    /**
27
     * @var string
28
     */
29
    private $namespace;
30
31
    /**
32
     * @var string
33
     */
34
    private $dataProviderExtends;
35
36
    /**
37
     * DataProviderGenerator constructor.
38
     *
39
     * @param \Xervice\DataProvider\Business\Model\Parser\DataProviderParserInterface $parser
40
     * @param FileWriterInterface $fileWriter
41
     * @param string $namespace
42
     */
43 5
    public function __construct(
44
        DataProviderParserInterface $parser,
45
        FileWriterInterface $fileWriter,
46
        string $namespace,
47
        string $dataProviderExtends
48
    ) {
49 5
        $this->parser = $parser;
50 5
        $this->fileWriter = $fileWriter;
51 5
        $this->namespace = $namespace;
52 5
        $this->dataProviderExtends = $dataProviderExtends;
53 5
    }
54
55
    /**
56
     * @return array
57
     * @throws \Nette\InvalidArgumentException
58
     */
59 5
    public function generate(): array
60
    {
61 5
        $fileGenerated = [];
62
63 5
        foreach ($this->parser->getDataProvider() as $providerName => $providerElements) {
64 5
            $namespace = new PhpNamespace($this->namespace);
65 5
            $dataProvider = $this->createDataProviderClass($providerName, $providerElements, $namespace);
66 5
            $classContent = (string)$namespace;
67 5
            $classContent = str_replace('\?', '?', $classContent);
68 5
            $classContent = Helpers::tabsToSpaces($classContent, 4);
69 5
            $this->fileWriter->writeToFile($dataProvider->getName() . '.php', $classContent);
70 5
            $fileGenerated[] = $dataProvider->getName() . '.php';
71
        }
72
73 5
        return $fileGenerated;
74
    }
75
76
    /**
77
     * @param string $provider
78
     * @param \Nette\PhpGenerator\PhpNamespace $namespace
79
     *
80
     * @return ClassType
81
     * @throws \Nette\InvalidArgumentException
82
     */
83 5
    private function createNewDataProvider($provider, PhpNamespace $namespace): ClassType
84
    {
85 5
        $dataProvider = $namespace->addClass($provider . 'DataProvider');
86
        $dataProvider
87 5
            ->setFinal()
88 5
            ->setExtends($this->dataProviderExtends)
89 5
            ->setImplements(
90
                [
91 5
                    DataProviderInterface::class
92
                ]
93
            )
94 5
            ->setComment('Auto generated data provider');
95
96 5
        return $dataProvider;
97
    }
98
99
    /**
100
     * @param \Nette\PhpGenerator\ClassType $dataProvider
101
     * @param array $element
102
     */
103 5
    private function addGetter(ClassType $dataProvider, array $element): void
104
    {
105 5
        $dataProvider->addMethod('get' . $element['name'])
106 5
                     ->addComment('@return ' . $element['type'])
107 5
                     ->setVisibility('public')
108 5
                     ->setBody('return $this->' . $element['name'] . ';')
109 5
                     ->setReturnType($this->getTypeHint($element['type'], $element['allownull']));
110 5
    }
111
112
    /**
113
     * @param \Nette\PhpGenerator\ClassType $dataProvider
114
     * @param array $element
115
     */
116 5
    private function addUnsetter(ClassType $dataProvider, array $element): void
117
    {
118 5
        $dataProvider->addMethod('unset' . $element['name'])
119 5
                     ->addComment('@return ' . $dataProvider->getName())
120 5
                     ->setVisibility('public')
121 5
                     ->setBody('$this->' . $element['name'] . ' = null;' . PHP_EOL . PHP_EOL . 'return $this;');
122 5
    }
123
124
    /**
125
     * @param \Nette\PhpGenerator\ClassType $dataProvider
126
     * @param array $element
127
     */
128 5
    private function addHas(ClassType $dataProvider, array $element): void
129
    {
130 5
        $dataProvider->addMethod('has' . $element['name'])
131 5
                     ->addComment('@return bool')
132 5
                     ->setVisibility('public')
133 5
                     ->setBody(
134 5
                         'return ($this->' . $element['name'] . ' !== null && $this->' . $element['name'] . ' !== []);'
135
                     );
136 5
    }
137
138
    /**
139
     * @param \Nette\PhpGenerator\ClassType $dataProvider
140
     * @param array $element
141
     */
142 5
    private function addSetter(ClassType $dataProvider, array $element): void
143
    {
144 5
        $setter = $dataProvider->addMethod('set' . $element['name'])
145 5
                               ->addComment(
146 5
                                   '@param ' . $element['type'] . ' $'
147 5
                                   . $element['name']
148
                               )
149 5
                               ->addComment('@return ' . $dataProvider->getName())
150 5
                               ->setVisibility('public')
151 5
                               ->setBody(
152 5
                                   '$this->' . $element['name'] . ' = $' . $element['name'] . ';' . PHP_EOL . PHP_EOL
153 5
                                   . 'return $this;'
154
                               );
155
156 5
        $param = $setter->addParameter($element['name'])
157 5
                        ->setTypeHint($this->getTypeHint($element['type'], $element['allownull']));
158 5
        if ($element['default']) {
159 5
            $default = $this->getDefaultValue($element);
160 5
            $param->setDefaultValue($default);
161
        }
162 5
        elseif ($element['allownull']) {
163 5
            $param->setDefaultValue(null);
164
        }
165 5
    }
166
167
    /**
168
     * @param array $element
169
     * @param \Nette\PhpGenerator\ClassType $dataProvider
170
     */
171 5
    private function addSingleSetter(array $element, ClassType $dataProvider): void
172
    {
173 5
        if (isset($element['singleton']) && $element['singleton'] !== '') {
174
            $singleSetter = $dataProvider
175 5
                ->addMethod('add' . $element['singleton'])
176 5
                ->addComment(
177 5
                    '@param ' . $element['singleton_type'] . ' $'
178 5
                    . $element['singleton']
179
                )
180 5
                ->addComment('@return ' . $dataProvider->getName())
181 5
                ->setVisibility('public')
182 5
                ->setBody(
183 5
                    sprintf(
184 5
                        '$this->%s[] = $%s; return $this;',
185 5
                        $element['name'],
186 5
                        $element['singleton']
187
                    )
188
                );
189
190 5
            $singleSetter->addParameter($element['singleton'])
191 5
                         ->setTypeHint($element['singleton_type']);
192
        }
193 5
    }
194
195
    /**
196
     * @param \Nette\PhpGenerator\ClassType $dataProvider
197
     * @param array $element
198
     */
199 5
    private function addProperty(ClassType $dataProvider, array $element): void
200
    {
201 5
        $property = $dataProvider->addProperty($element['name'])
202 5
                                 ->setVisibility('protected')
203 5
                                 ->addComment('@var ' . $element['type']);
204
205 5
        if ($element['default']) {
206 5
            $default = $this->getDefaultValue($element);
207 5
            $property->setValue($default);
208
        }
209 5
        elseif (strpos($element['type'], '[]') !== false) {
210 5
            $property->setValue([]);
211
        }
212 5
    }
213
214
    /**
215
     * @param string $type
216
     * @param bool $allowNull
217
     *
218
     * @return string
219
     */
220 5
    private function getTypeHint(string $type, bool $allowNull = null): string
221
    {
222 5
        if (strpos($type, '[]') !== false) {
223 5
            $type = 'array';
224
        }
225
226 5
        if ($allowNull === true) {
227 5
            $type = '?' . $type;
228
        }
229
230 5
        return $type;
231
    }
232
233
    /**
234
     * @param \Nette\PhpGenerator\ClassType $dataProvider
235
     * @param array $elements
236
     */
237 5
    private function addElementsGetter(ClassType $dataProvider, array $elements): void
238
    {
239 5
        $dataProvider->addMethod('getElements')
240 5
                     ->setReturnType('array')
241 5
                     ->setVisibility('protected')
242 5
                     ->addComment('@return array')
243 5
                     ->setBody('return ' . var_export($elements, true) . ';');
244 5
    }
245
246
    /**
247
     * @param string $providerName
248
     * @param array $providerElements
249
     * @param \Nette\PhpGenerator\PhpNamespace $namespace
250
     *
251
     * @return \Nette\PhpGenerator\ClassType
252
     */
253 5
    private function createDataProviderClass(
254
        string $providerName,
255
        array $providerElements,
256
        PhpNamespace $namespace
257
    ): ClassType {
258 5
        $dataProvider = $this->createNewDataProvider($providerName, $namespace);
259
260 5
        foreach ($providerElements as $element) {
261 5
            $this->addProperty($dataProvider, $element);
262 5
            $this->addGetter($dataProvider, $element);
263 5
            $this->addSetter($dataProvider, $element);
264 5
            $this->addUnsetter($dataProvider, $element);
265 5
            $this->addHas($dataProvider, $element);
266 5
            $this->addSingleSetter($element, $dataProvider);
267
268
        }
269
270 5
        $this->addElementsGetter($dataProvider, $providerElements);
271 5
        return $dataProvider;
272
    }
273
274
    /**
275
     * @param array $element
276
     *
277
     * @return bool
278
     */
279 5
    private function getDefaultValue($element)
280
    {
281 5
        $default = $element['default'];
282 5
        if ($element['type'] === 'bool' || $element['type'] === 'boolean') {
283 5
            $default = $default === 'false' ? false : $default;
284 5
            $default = $default === 'true' ? true : $default;
285 5
        } elseif ($element['type'] === 'array') {
286 5
            $default = [];
287 5
        } elseif ($element['type'] === 'string') {
288 5
            $default = $default === '\'\'' ? '' : $default;
289
        }
290 5
        settype($default, $element['type']);
291 5
        return $default;
292
    }
293
}