Passed
Push — master ( a14817...61baa6 )
by Mike
03:16
created

DataProviderGenerator::getDefaultValue()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5

Importance

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