Test Failed
Push — master ( 78e22c...a9269f )
by Vitaly
05:04 queued 02:20
created

Generator::defVar()   D

Complexity

Conditions 9
Paths 9

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 27
rs 4.9091
cc 9
eloc 20
nc 9
nop 5
1
<?php
2
//[PHPCOMPRESSOR(remove,start)]
3
namespace samsonphp\generator;
4
5
class Generator
6
{
7
    /** Single quote for string value **/
8
    const QUOTE_SINGLE = "'";
9
10
    /** Double quote for string value **/
11
    const QUOTE_DOUBLE = '"';
12
13
    /** @var string Generated code */
14
    public $code = '';
15
16
    /** @var integer Level of code line tabbing for new lines */
17
    public $tabs = 0;
18
19
    /** @var string Current class name */
20
    public $class;
21
22
    /**
23
     * Add simple text to current code position
24
     * @param string $text Text to add
25
     * @return self
26
     */
27
    public function text($text = '')
28
    {
29
        $this->code .= $text;
30
31
        return $this;
32
    }
33
34
    /**
35
     * Add current tabbing level to current line.
36
     *
37
     * @param string $endText Text to add after tabs
38
     * @param integer $tabs Amount of tabs to add
39
     * @param string $startText Text to add before tabs
40
     * @return Generator Chaining
41
     */
42
    public function tabs($endText = '', $tabs = null, $startText = '')
43
    {
44
        // Generate tabs array
45
        $tabs = isset($tabs) ? array_fill(0, $tabs, "\t") : array();
46
47
        // Add necessary amount of tabs to line and append text
48
        $this->text($startText.implode('', $tabs) . $endText);
49
50
        return $this;
51
    }
52
53
    /**
54
     * Add new line to code.
55
     *
56
     * @param string $text Code to add to new line
57
     * @param integer $tabs Tabs count
58
     * @return self
59
     */
60
    public function newLine($text = '', $tabs = null)
61
    {
62
        // If no tabs count is specified set default tabs
63
        if (!isset($tabs)) {
64
            $tabs = $this->tabs;
65
        }
66
67
        return $this->tabs($text, $tabs, "\n");
68
    }
69
70
    /**
71
     * Add single line comment to code
72
     * @param string $text Comment text
73
     * @return self Chaining
74
     */
75
    public function comment($text = '')
76
    {
77
        return isset($text{0}) ? $this->newLine("// " . $text) : $this;
78
    }
79
80
    /**
81
     * Add multi-line comment. If array with one line is passed
82
     * we create special syntax comment in one line, usually
83
     * used for class variable definition in more compact form.
84
     *
85
     * @param array $lines Array of comments lines
86
     * @return self Chaining
87
     */
88
    public function multiComment(array $lines = array())
89
    {
90
        // If array is not empty
91
        if (sizeof($lines)) {
92
            $this->newLine("/**");
93
94
            // Multi-comment with single line
95
            if (sizeof($lines) === 1) {
96
                $this->text(' '.$lines[0].' */');
97
            } else { // Iterate comments lines and if comment line is not empty
98
                foreach ($lines as $line) {
99
                    if (isset($line{0})) {
100
                        $this->newLine(" * " . $line);
101
                    }
102
                }
103
104
                return $this->newLine(" */");
105
            }
106
107
        }
108
109
        return $this;
110
    }
111
112
    /**
113
     * Add string value definition.
114
     *
115
     * @param string $value String value to add
116
     * @param string $tabs Tabs count
117
     * @param string $quote Type of quote
118
     * @return self Chaining
119
     */
120
    public function stringValue($value, $tabs = null, $quote = self::QUOTE_SINGLE)
121
    {
122
        return $this->tabs($quote . $value . $quote, $tabs);
123
    }
124
125
    /**
126
     * Add array values definition.
127
     *
128
     * @param array $items Array key-value pairs collection
129
     * @return self Chaining
130
     */
131
    public function arrayValue(array $items = array())
132
    {
133
        $this->text('array(');
134
        $this->tabs++;
135
136
        // Iterate array items
137
        foreach ($items as $key => $value) {
138
            // Start array key definition
139
            $this->newLine()->stringValue($key)->text(' => ');
140
141
            // If item value is array - recursion
142
            if (is_array($value)) {
143
                $this->arrayValue($value)->text(',');
144
            } else {
145
                $this->stringValue($value)->text(',');
146
            }
147
        }
148
149
        $this->newLine(')');
150
        $this->tabs--;
151
152
        return $this;
153
    }
154
155
    /**
156
     * Add variable definition with array merging.
157
     *
158
     * @param string $name Variable name
159
     * @param array $value Array of key-value items for merging it to other array
160
     * @param string $arrayName Name of array to merge to, if no is specified - $name is used
161
     * @return self Chaining
162
     */
163
    public function defArrayMerge($name, array $value, $arrayName = null)
164
    {
165
        // If no other array is specified - set it to current
166
        if (!isset($arrayName)) {
167
            $arrayName = $name;
168
        }
169
170
        return $this->defvar($name, $value, ' = array_merge( ' . $arrayName . ', ', '')->text(');');
0 ignored issues
show
Documentation introduced by
$value is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
171
    }
172
173
    /**
174
     * Add variable definition.
175
     *
176
     * @param string $name Variable name
177
     * @param string $value Variable default value
178
     * @param string $after String to insert after variable definition
179
     * @param string $end Closing part of variable definition
180
     * @param string $quote Type of quote
181
     * @return Generator Chaining
182
     */
183
    public function defVar($name, $value = null, $after = ' = ', $end = ';', $quote = self::QUOTE_SINGLE)
184
    {
185
        // Output variable definition
186
        $this->newLine($name);
187
188
        // Get variable type
189
        switch (gettype($value)) {
190
            case 'integer':
191
            case 'boolean':
192
            case 'double':
193
                $this->text($after)->text($value)->text($end);
194
                break;
195
            case 'string':
196
                $this->text($after)->stringValue($value, 0, $quote)->text($end);
197
                break;
198
            case 'array':
199
                $this->text($after)->arrayValue($value)->text($end);
0 ignored issues
show
Documentation introduced by
$value is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
200
                break;
201
            case 'NULL':
202
            case 'object':
203
            case 'resource':
204
            default:
205
                $this->text(';');
206
        }
207
208
        return $this;
209
    }
210
211
    /**
212
     * Add class definition.
213
     *
214
     * @param string $name Class name
215
     * @param string $extends Parent class name
216
     * @param array $implements Interfaces names collection
217
     * @return self Chaining
218
     */
219
    public function defClass($name, $extends = null, array $implements = array())
220
    {
221
        // If we define another class, and we were in other class context
222
        if (isset($this->class) && ($name !== $this->class)) {
223
            // Close old class context
224
            $this->endClass();
225
        }
226
227
        // Save new class name
228
        $this->class = $name;
229
230
        // Class definition start
231
        $this->newLine('class ' . $name);
232
233
        // Parent class definition
234
        if (isset($extends)) {
235
            $this->text(' extends ' . $extends);
236
        }
237
238
        // Interfaces
239
        if (sizeof($implements)) {
240
            $this->text(' implements ' . implode(',', $implements));
241
        }
242
243
        $this->newLine('{');
244
245
        $this->tabs++;
246
247
        return $this;
248
    }
249
250
    /**
251
     * Close current class context.
252
     *
253
     * @return self Chaining
254
     */
255
    public function endClass()
256
    {
257
        $this->tabs--;
258
259
        // Close class definition
260
        return $this->newLine('}')
261
            // Add one empty line after class definition
262
        ->newLine('');
263
    }
264
265
    /**
266
     * Add class variable definition.
267
     *
268
     * @param string $name Variable name
269
     * @param string $visibility Variable accessibility level
270
     * @param string|null $comment Variable description
271
     * @param string $value Variable default value
272
     * @return self Chaining
273
     */
274
    public function defClassVar($name, $visibility = 'public', $comment = null, $value = null)
275
    {
276
        if (isset($comment) && isset($comment{0})) {
277
            $this->multiComment(array($comment));
278
        }
279
280
        return $this->defvar($visibility . ' ' . $name, $value)->newLine();
281
    }
282
283
    /**
284
     * Add class constant definition.
285
     *
286
     * @param string $name Constant name
287
     * @param string $value Variable default value
288
     * @param string|null $comment Variable description
289
     * @return self Chaining
290
     */
291
    public function defClassConst($name, $value, $comment = null)
292
    {
293
        return $this->defClassVar(strtoupper($name), 'const', $comment, $value);
294
    }
295
296
    /**
297
     * Write file to disk
298
     * @param string $name Path to file
299
     * @param string $format Output file format
300
     */
301
    public function write($name, $format = 'php')
302
    {
303
        $code = $this->flush();
304
305
        if ($format === 'php') {
306
            $code = '<?php ' . $code;
307
        }
308
309
        file_put_contents($name, $code, 0775);
310
    }
311
312
    /**
313
     * Flush internal data and return it.
314
     *
315
     * @return string Current generated code
316
     */
317
    public function flush()
318
    {
319
        // We should use 4 spaces instead of tabs
320
        $code = str_replace("\t", '    ', $this->code);
321
322
        $this->tabs = 0;
323
        $this->code = '';
324
        $this->class = null;
325
326
        return $code;
327
    }
328
329
    /**
330
     * Add function definition.
331
     *
332
     * @param string $name Function name
333
     * @param array $parameters Collection of parameters $typeHint => $paramName
334
     * @return Generator Chaining
335
     */
336
    public function defFunction($name, $parameters = array())
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
337
    {
338
        // Convert parameters to string
339
        $parameterList = array();
340
        foreach ($parameters as $type => $name) {
341
            $parameterList[] = (is_string($type) ? $type.' ' : '') . $name;
342
        }
343
        $parameterList = implode(', ', $parameterList);
344
345
        $this->newLine('function ' . $name . '('.$parameterList.')')
346
            ->newLine('{')
347
            ->tabs('');
348
349
        $this->tabs++;
350
351
        return $this;
352
    }
353
354
    /**
355
     * Close current function context.
356
     *
357
     * @return self Chaining
358
     */
359
    public function endFunction()
360
    {
361
        $this->tabs--;
362
363
        return $this->newLine('}')->newLine('');
364
    }
365
366
    /**
367
     * Constructor
368
     * @param string $namespace Code namespace
369
     */
370
    public function __construct($namespace = null)
371
    {
372
        // If namespace is defined - set it
373
        if (isset($namespace)) {
374
            $this->defnamespace($namespace);
375
        }
376
    }
377
378
    /**
379
     * Add namespace declaration
380
     * @param string $name Namespace name
381
     * @return self
382
     */
383
    private function defnamespace($name)
384
    {
385
        return $this->newLine('namespace ' . $name . ';')->newLine();
386
    }
387
}
388
//[PHPCOMPRESSOR(remove,end)]
389