Completed
Push — master ( 6efea1...0e768a )
by Simonas
04:33 queued 10s
created

DocumentGenerator::generateDocumentMethods()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 8.8571
c 0
b 0
f 0
cc 6
eloc 10
nc 4
nop 1
1
<?php
2
3
/*
4
 * This file is part of the ONGR package.
5
 *
6
 * (c) NFQ Technologies UAB <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ONGR\ElasticsearchBundle\Generator;
13
14
use Doctrine\Common\Inflector\Inflector;
15
16
/**
17
 * Document Generator
18
 */
19
class DocumentGenerator
20
{
21
    /**
22
     * @var string
23
     */
24
    private $spaces = '    ';
25
26
    /**
27
     * @var string
28
     */
29
    private $getMethodTemplate =
30
        '/**
31
 * Returns <fieldName>
32
 *
33
 * @return string
34
 */
35
public function get<methodName>()
36
{
37
<spaces>return $this-><fieldName>;
38
}';
39
40
    /**
41
     * @var string
42
     */
43
    private $isMethodTemplate =
44
        '/**
45
 * Returns <fieldName>
46
 *
47
 * @return string
48
 */
49
public function is<methodName>()
50
{
51
<spaces>return $this-><fieldName>;
52
}';
53
54
    /**
55
     * @var string
56
     */
57
    private $setMethodTemplate =
58
        '/**
59
 * Sets <fieldName>
60
 *
61
 * @param string $<fieldName>
62
 *
63
 * @return self
64
 */
65
public function set<methodName>($<fieldName>)
66
{
67
<spaces>$this-><fieldName> = $<fieldName>;
68
69
<spaces>return $this;
70
}';
71
72
    /**
73
     * @var string
74
     */
75
    private $constructorTemplate =
76
        '/**
77
 * Constructor
78
 */
79
public function __construct()
80
{
81
<fields>
82
}';
83
84
    /**
85
     * @param array $metadata
86
     *
87
     * @return string
88
     */
89
    public function generateDocumentClass(array $metadata)
90
    {
91
        return implode(
92
            "\n",
93
            [
94
                "<?php\n",
95
                sprintf('namespace %s;', substr($metadata['name'], 0, strrpos($metadata['name'], '\\'))) . "\n",
96
                $this->generateDocumentUse($metadata),
97
                $this->generateDocumentDocBlock($metadata),
98
                'class ' . $this->getClassName($metadata),
99
                "{",
100
                str_replace('<spaces>', $this->spaces, $this->generateDocumentBody($metadata)),
101
                "}\n"
102
            ]
103
        );
104
    }
105
106
    /**
107
     * Generates document body
108
     *
109
     * @param array $metadata
110
     *
111
     * @return string
112
     */
113
    private function generateDocumentBody(array $metadata)
114
    {
115
        $lines = [];
116
117
        if ($properties = $this->generateDocumentProperties($metadata)) {
118
            $lines[] = $properties;
119
        }
120
121
        if ($this->hasMultipleEmbedded($metadata)) {
122
            $lines[] = $this->generateDocumentConstructor($metadata);
123
        }
124
125
        if ($methods = $this->generateDocumentMethods($metadata)) {
126
            $lines[] = $methods;
127
        }
128
129
        return rtrim(implode("\n", $lines));
130
    }
131
132
    /**
133
     * Generates document properties
134
     *
135
     * @param array $metadata
136
     *
137
     * @return string
138
     */
139
    private function generateDocumentProperties(array $metadata)
140
    {
141
        $lines = [];
142
143
        foreach ($metadata['properties'] as $property) {
144
            $lines[] = $this->generatePropertyDocBlock($property);
145
            $lines[] = $this->spaces . $property['visibility'] . ' $' . $property['field_name'] . ";\n";
146
        }
147
148
        return implode("\n", $lines);
149
    }
150
151
    /**
152
     * Generates document methods
153
     *
154
     * @param array $metadata
155
     *
156
     * @return string
157
     */
158
    private function generateDocumentMethods(array $metadata)
159
    {
160
        $lines = [];
161
162
        foreach ($metadata['properties'] as $property) {
163
            if (isset($property['visibility']) && $property['visibility'] === 'public') {
164
                continue;
165
            }
166
            $lines[] = $this->generateDocumentMethod($property, $this->setMethodTemplate) . "\n";
167
            if (isset($property['property_type']) && $property['property_type'] === 'boolean') {
168
                $lines[] = $this->generateDocumentMethod($property, $this->isMethodTemplate) . "\n";
169
            }
170
171
            $lines[] = $this->generateDocumentMethod($property, $this->getMethodTemplate) . "\n";
172
        }
173
174
        return implode("\n", $lines);
175
    }
176
177
    /**
178
     * Generates document constructor
179
     *
180
     * @param array $metadata
181
     *
182
     * @return string
183
     */
184
    private function generateDocumentConstructor(array $metadata)
185
    {
186
        $fields = [];
187
188
        foreach ($metadata['properties'] as $prop) {
189
            if ($prop['annotation'] == 'embedded' && isset($prop['property_multiple']) && $prop['property_multiple']) {
190
                $fields[] = sprintf('%s$this->%s = new Collection();', $this->spaces, $prop['field_name']);
191
            }
192
        }
193
194
        return $this->prefixWithSpaces(
195
            str_replace('<fields>', implode("\n", $fields), $this->constructorTemplate)
196
        ) . "\n";
197
    }
198
199
    /**
200
     * Generates document method
201
     *
202
     * @param array  $metadata
203
     * @param string $template
204
     *
205
     * @return string
206
     */
207
    private function generateDocumentMethod(array $metadata, $template)
208
    {
209
        return $this->prefixWithSpaces(
210
            str_replace(
211
                ['<methodName>', '<fieldName>'],
212
                [ucfirst($metadata['field_name']), $metadata['field_name']],
213
                $template
214
            )
215
        );
216
    }
217
218
    /**
219
     * Returns property doc block
220
     *
221
     * @param array $metadata
222
     *
223
     * @return string
224
     */
225
    private function generatePropertyDocBlock(array $metadata)
226
    {
227
        $lines = [
228
            $this->spaces . '/**',
229
            $this->spaces . ' * @var string',
230
            $this->spaces . ' *',
231
        ];
232
233
        $column = [];
234
        if (isset($metadata['property_name']) && $metadata['property_name'] != $metadata['field_name']) {
235
            $column[] = 'name="' . $metadata['property_name'] . '"';
236
        }
237
238
        if (isset($metadata['property_class'])) {
239
            $column[] = 'class="' . $metadata['property_class'] . '"';
240
        }
241
242
        if (isset($metadata['property_multiple']) && $metadata['property_multiple']) {
243
            $column[] = 'multiple=true';
244
        }
245
246
        if (isset($metadata['property_type']) && $metadata['annotation'] == 'property') {
247
            $column[] = 'type="' . $metadata['property_type'] . '"';
248
        }
249
250
        if (isset($metadata['property_default'])) {
251
            $column[] = 'default="' . $metadata['property_default'] . '"';
252
        }
253
254
        if (isset($metadata['property_options'])  && $metadata['property_options']) {
255
            $column[] = 'options={' . $metadata['property_options'] . '}';
256
        }
257
258
        $lines[] = $this->spaces . ' * @ES\\' . ucfirst($metadata['annotation']) . '(' . implode(', ', $column) . ')';
259
260
        $lines[] = $this->spaces . ' */';
261
262
        return implode("\n", $lines);
263
    }
264
265
    /**
266
     * Generates document doc block
267
     *
268
     * @param array $metadata
269
     *
270
     * @return string
271
     */
272
    private function generateDocumentDocBlock(array $metadata)
273
    {
274
        return str_replace(
275
            ['<className>', '<annotation>', '<options>'],
276
            [
277
                $this->getClassName($metadata),
278
                ucfirst($metadata['annotation']),
279
                $metadata['annotation'] != 'object' ? ($metadata['type'] != lcfirst($this->getClassName($metadata))
280
                    ? sprintf('type="%s"', $metadata['type']) : '') : '',
281
            ],
282
            '/**
283
 * <className>
284
 *
285
 * @ES\<annotation>(<options>)
286
 */'
287
        );
288
    }
289
290
    /**
291
     * @param string $code
292
     *
293
     * @return string
294
     */
295
    private function prefixWithSpaces($code)
296
    {
297
        $lines = explode("\n", $code);
298
299
        foreach ($lines as $key => $value) {
300
            if ($value) {
301
                $lines[$key] = $this->spaces . $lines[$key];
302
            }
303
        }
304
305
        return implode("\n", $lines);
306
    }
307
308
    /**
309
     * Returns class name
310
     *
311
     * @param array $metadata
312
     *
313
     * @return string
314
     */
315
    private function getClassName(array $metadata)
316
    {
317
        return ($pos = strrpos($metadata['name'], '\\'))
318
            ? substr($metadata['name'], $pos + 1, strlen($metadata['name'])) : $metadata['name'];
319
    }
320
321
    /**
322
     * Generates document use statements
323
     *
324
     * @param array $metadata
325
     *
326
     * @return string
327
     */
328
    private function generateDocumentUse(array $metadata)
329
    {
330
        $uses = ['use ONGR\ElasticsearchBundle\Annotation as ES;'];
331
332
        if ($this->hasMultipleEmbedded($metadata)) {
333
            $uses[] = 'use ONGR\ElasticsearchBundle\Collection\Collection;';
334
        }
335
336
        return implode("\n", $uses) . "\n";
337
    }
338
339
    /**
340
     * @param array $metadata
341
     *
342
     * @return bool
343
     */
344
    private function hasMultipleEmbedded(array $metadata)
345
    {
346
        foreach ($metadata['properties'] as $prop) {
347
            if ($prop['annotation'] == 'embedded' && isset($prop['property_multiple']) && $prop['property_multiple']) {
348
                return true;
349
            }
350
        }
351
352
        return false;
353
    }
354
}
355