Passed
Push — master ( 36d135...97e9b8 )
by Sébastien
08:13
created

EntityGenerator::generateEntityConstructor()   F

Complexity

Conditions 19
Paths 576

Size

Total Lines 58
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 19

Importance

Changes 0
Metric Value
eloc 34
dl 0
loc 58
ccs 34
cts 34
cp 1
rs 0.9388
c 0
b 0
f 0
cc 19
nc 576
nop 0
crap 19

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
0 ignored issues
show
introduced by
The PHP open tag must be followed by exactly one blank line
Loading history...
2
/*
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
introduced by
Namespaced classes, interfaces and traits should not begin with a file doc comment
Loading history...
Coding Style introduced by
Empty line required before block comment
Loading history...
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Bdf\Prime\Entity;
21
22
use Bdf\Prime\Mapper\Info\InfoInterface;
23
use Bdf\Prime\Mapper\Info\ObjectPropertyInfo;
24
use Bdf\Prime\Mapper\Info\PropertyInfo;
25
use Bdf\Prime\Mapper\Mapper;
26
use Bdf\Prime\Mapper\Info\MapperInfo;
27
use Bdf\Prime\ServiceLocator;
28
use Bdf\Prime\Types\PhpTypeInterface;
29
use Bdf\Prime\Types\TypeInterface;
30
use Doctrine\Common\Inflector\Inflector;
31
use Doctrine\Inflector\Inflector as InflectorObject;
32
use Doctrine\Inflector\InflectorFactory;
33
34
/**
35
 * Generic class used to generate PHP5 entity classes from Mapper.
36
 *
37
 *     [php]
38
 *     $mapper = $service->mappers()->build('Entity);
39
 *
40
 *     $generator = new EntityGenerator();
41
 *     $generator->setGenerateStubMethods(true);
42
 *     $generator->setRegenerateEntityIfExists(false);
43
 *     $generator->setUpdateEntityIfExists(true);
44
 *     $generator->generate($mapper, '/path/to/generate/entities');
45
 *
46
 *
47
 * @link    www.doctrine-project.org
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @author tag
Loading history...
introduced by
Tag value indented incorrectly; expected 1 space but found 4
Loading history...
Coding Style introduced by
There must be exactly one blank line before the tags in a doc comment
Loading history...
48
 * @since   2.0
0 ignored issues
show
introduced by
Tag value indented incorrectly; expected 1 space but found 3
Loading history...
Coding Style introduced by
The tag in position 2 should be the @link tag
Loading history...
49
 * @author  Benjamin Eberlei <[email protected]>
0 ignored issues
show
introduced by
Tag value indented incorrectly; expected 1 space but found 2
Loading history...
Coding Style introduced by
The tag in position 3 should be the @since tag
Loading history...
50
 * @author  Guilherme Blanco <[email protected]>
0 ignored issues
show
introduced by
Tag value indented incorrectly; expected 1 space but found 2
Loading history...
51
 * @author  Jonathan Wage <[email protected]>
0 ignored issues
show
introduced by
Tag value indented incorrectly; expected 1 space but found 2
Loading history...
52
 * @author  Roman Borschel <[email protected]>
0 ignored issues
show
introduced by
Tag value indented incorrectly; expected 1 space but found 2
Loading history...
53
 */
54
class EntityGenerator
55
{
56
    // @todo should not be there : should be on PhpTypeInterface
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
57
    /**
58
     * Map prime types to php 7.4 property type
59
     */
60
    const PROPERTY_TYPE_MAP = [
61
        PhpTypeInterface::BOOLEAN => 'bool',
62
        PhpTypeInterface::DOUBLE => 'float',
63
        PhpTypeInterface::INTEGER => 'int',
64
    ];
65
66
    /**
67
     * Specifies class fields should be protected.
68
     */
69
    const FIELD_VISIBLE_PROTECTED = 'protected';
70
71
    /**
72
     * Specifies class fields should be private.
73
     */
74
    const FIELD_VISIBLE_PRIVATE = 'private';
75
76
    /**
77
     * The prime service locator
78
     *
79
     * @var ServiceLocator
80
     */
81
    private $prime;
82
83
    /**
84
     * The inflector instance
85
     *
86
     * @var InflectorObject
87
     */
88
    private $inflector;
89
90
    /**
91
     * The mapper info
92
     *
93
     * @var MapperInfo
94
     */
95
    private $mapperInfo;
96
97
    /**
98
     * The extension to use for written php files.
99
     *
100
     * @var string
101
     */
102
    private $extension = '.php';
103
104
    /**
105
     * Whether or not the current Mapper instance is new or old.
106
     *
107
     * @var boolean
0 ignored issues
show
introduced by
Expected "bool" but found "boolean" for @var tag in member variable comment
Loading history...
108
     */
109
    private $isNew = true;
110
111
    /**
112
     * @var array
113
     */
114
    private $staticReflection = [];
115
116
    /**
117
     * Number of spaces to use for indention in generated code.
118
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @var tag in member variable comment
Loading history...
119
    private $numSpaces = 4;
120
121
    /**
122
     * The actual spaces to use for indention.
123
     *
124
     * @var string
125
     */
126
    private $spaces = '    ';
127
128
    /**
129
     * The class all generated entities should extend.
130
     *
131
     * @var string
132
     */
133
    private $classToExtend;
134
135
    /**
136
     * The interfaces all generated entities should implement.
137
     *
138
     * @var array
139
     */
140
    private $interfaces = [];
141
142
    /**
143
     * The traits
144
     *
145
     * @var array
146
     */
147
    private $traits = [];
148
149
    /**
150
     * Whether or not to generate sub methods.
151
     *
152
     * @var boolean
0 ignored issues
show
introduced by
Expected "bool" but found "boolean" for @var tag in member variable comment
Loading history...
153
     */
154
    private $generateEntityStubMethods = true;
155
156
    /**
157
     * Whether or not to update the entity class if it exists already.
158
     *
159
     * @var boolean
0 ignored issues
show
introduced by
Expected "bool" but found "boolean" for @var tag in member variable comment
Loading history...
160
     */
161
    private $updateEntityIfExists = false;
162
163
    /**
164
     * Whether or not to re-generate entity class if it exists already.
165
     *
166
     * @var boolean
0 ignored issues
show
introduced by
Expected "bool" but found "boolean" for @var tag in member variable comment
Loading history...
167
     */
168
    private $regenerateEntityIfExists = false;
169
170
    /**
171
     * The name of get methods will not contains the 'get' prefix
172
     *
173
     * @var boolean
0 ignored issues
show
introduced by
Expected "bool" but found "boolean" for @var tag in member variable comment
Loading history...
174
     */
175
    private $useGetShortcutMethod = true;
176
177
    /**
178
     * Visibility of the field
179
     *
180
     * @var string
181
     */
182
    private $fieldVisibility = self::FIELD_VISIBLE_PROTECTED;
183
184
    /**
185
     * Use type on generated properties
186
     * Note: only compatible with PHP >= 7.4
187
     *
188
     * @var bool
0 ignored issues
show
Bug introduced by
Expected "boolean" but found "bool" for @var tag in member variable comment
Loading history...
189
     */
190
    private $useTypedProperties = false;
191
192
    /**
193
     * @var string
194
     */
195
    private static $classTemplate =
0 ignored issues
show
Coding Style introduced by
Multi-line assignments must have the equal sign on the second line
Loading history...
196
'<?php
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 4 spaces, found 0
Loading history...
197
198
<namespace><useStatement><entityAnnotation>
199
<entityClassName>
200
{
201
<entityTraits><entityBody>
202
}
203
';
204
205
    /**
206
     * @var string
207
     */
208
    private static $getMethodTemplate =
0 ignored issues
show
Coding Style introduced by
Multi-line assignments must have the equal sign on the second line
Loading history...
209
'/**
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 4 spaces, found 0
Loading history...
210
 * <description>
211
 *
212
 * @return <variableType>
213
 */
214
public function <methodName>()
215
{
216
<spaces>return $this-><fieldName>;
217
}
218
';
219
220
    /**
221
     * @var string
222
     */
223
    private static $setMethodTemplate =
0 ignored issues
show
Coding Style introduced by
Multi-line assignments must have the equal sign on the second line
Loading history...
224
'/**
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 4 spaces, found 0
Loading history...
225
 * <description>
226
 *
227
 * @param <variableType> $<variableName>
228
 *
229
 * @return $this
230
 */
231
public function <methodName>(<methodTypeHint>$<variableName><variableDefault>)
232
{
233
<spaces>$this-><fieldName> = $<variableName>;
234
235
<spaces>return $this;
236
}
237
';
238
239
    /**
240
     * @var string
241
     */
242
    private static $addMethodTemplate =
0 ignored issues
show
Coding Style introduced by
Multi-line assignments must have the equal sign on the second line
Loading history...
243
'/**
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 4 spaces, found 0
Loading history...
244
 * <description>
245
 *
246
 * @param <variableType> $<variableName>
247
 *
248
 * @return $this
249
 */
250
public function <methodName>(<methodTypeHint>$<variableName>)
251
{
252
<spaces>$this-><fieldName>[] = $<variableName>;
253
254
<spaces>return $this;
255
}
256
';
257
258
    /**
259
     * @var string
260
     */
261
    private static $methodTemplate =
0 ignored issues
show
Coding Style introduced by
Multi-line assignments must have the equal sign on the second line
Loading history...
262
'/**
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 4 spaces, found 0
Loading history...
263
 * <description>
264
 */
265
public function <methodName>()
266
{
267
<spaces><content>
268
}
269
';
270
271
    /**
272
     * @var string
273
     */
274
    private static $constructorMethodTemplate =
0 ignored issues
show
Coding Style introduced by
Multi-line assignments must have the equal sign on the second line
Loading history...
275
'/**
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 4 spaces, found 0
Loading history...
276
 * Constructor
277
 */
278
public function __construct()
279
{
280
<spaces><collections>
281
}
282
';
283
284
    /**
285
     * @var string
286
     */
287
    private static $importableConstructorMethodTemplate =
0 ignored issues
show
Coding Style introduced by
Multi-line assignments must have the equal sign on the second line
Loading history...
288
'/**
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 4 spaces, found 0
Loading history...
289
 * Constructor
290
 *
291
 * @param array $data
292
 */
293
public function __construct(array $data = [])
294
{
295
<spaces><initialize>$this->import($data);
296
}
297
';
298
299
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $prime should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $inflector should have a doc-comment as per coding-style.
Loading history...
300
     * Set prime service locator
301
     */
302 29
    public function __construct(ServiceLocator $prime, ?InflectorObject $inflector = null)
303
    {
304 29
        $this->prime = $prime;
305 29
        $this->inflector = $inflector ?? InflectorFactory::create()->build();
0 ignored issues
show
Coding Style introduced by
Operation must be bracketed
Loading history...
306 29
    }
307
308
    /**
309
     * Generates and writes entity classes
310
     *
311
     * @param Mapper $mapper
312
     * @param string $file    Entity file name
313
     *
314
     * @return string|false If no generation
315
     * 
316
     * @api
317
     */
318 28
    public function generate($mapper, $file = null)
0 ignored issues
show
introduced by
Type hint "Mapper" missing for $mapper
Loading history...
319
    {
320 28
        $this->isNew = !$file || !file_exists($file) || $this->regenerateEntityIfExists;
0 ignored issues
show
Coding Style introduced by
The value of a boolean operation must not be assigned to a variable
Loading history...
Coding Style introduced by
Boolean operators are not allowed outside of control structure conditions
Loading history...
321
322
        // If entity doesn't exist or we're re-generating the entities entirely
323 28
        if ($this->isNew || !$file) {
324 28
            return $this->generateEntityClass($mapper);
325
        // If entity exists and we're allowed to update the entity class
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 12 spaces, found 8
Loading history...
326
        } elseif ($this->updateEntityIfExists && $file) {
0 ignored issues
show
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
327
            return $this->generateUpdatedEntityClass($mapper, $file);
328
        }
329
        
330
        return false;
331
    }
332
    
333
    /**
334
     * Generates a PHP5 Doctrine 2 entity class from the given Mapper instance.
335
     *
336
     * @param Mapper $mapper
337
     *
338
     * @return string
339
     */
340 28
    public function generateEntityClass(Mapper $mapper)
341
    {
342 28
        $this->mapperInfo = $mapper->info();
343
        
344 28
        $this->staticReflection[$this->mapperInfo->className()] = ['properties' => [], 'methods' => []];
345
        
346
        $placeHolders = array(
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
347 28
            '<namespace>',
348
            '<useStatement>',
349
            '<entityAnnotation>',
350
            '<entityClassName>',
351
            '<entityTraits>',
352
            '<entityBody>'
0 ignored issues
show
introduced by
A comma should follow the last multiline array item. Found: '<entityBody>'
Loading history...
353
        );
354
355
        $replacements = array(
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
356 28
            $this->generateEntityNamespace(),
357 28
            $this->generateEntityUse(),
358 28
            $this->generateEntityDocBlock(),
359 28
            $this->generateEntityClassName(),
360 28
            $this->generateEntityTraits(),
361 28
            $this->generateEntityBody()
0 ignored issues
show
introduced by
A comma should follow the last multiline array item. Found: )
Loading history...
362
        );
363
364 28
        $code = str_replace($placeHolders, $replacements, static::$classTemplate);
0 ignored issues
show
Bug introduced by
Since $classTemplate is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $classTemplate to at least protected.
Loading history...
365
366 28
        return str_replace('<spaces>', $this->spaces, $code);
367
    }
368
369
    /**
370
     * Generates the updated code for the given Mapper and entity at path.
371
     *
372
     * @param Mapper $mapper
373
     * @param string $file
374
     *
375
     * @return string
376
     */
377
    public function generateUpdatedEntityClass(Mapper $mapper, $file)
378
    {
379
        $this->mapperInfo = $mapper->info();
380
        
381
        $currentCode = file_get_contents($file);
382
383
        $this->parseTokensInEntityFile($currentCode);
384
        
385
        $body = $this->generateEntityBody();
386
        $body = str_replace('<spaces>', $this->spaces, $body);
387
        $last = strrpos($currentCode, '}');
388
389
        return substr($currentCode, 0, $last) . $body . (strlen($body) > 0 ? "\n" : '') . "}\n";
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
390
    }
391
392
    /**
393
     * @return string
394
     */
395 28
    protected function generateEntityNamespace()
396
    {
397 28
        if ($this->hasNamespace($this->mapperInfo->className())) {
398 28
            return 'namespace ' . $this->getNamespace($this->mapperInfo->className()) .';' . "\n\n";
399
        }
400
    }
401
402
    /**
403
     * Generate use part
404
     * 
405
     * @return string
406
     */
407 28
    protected function generateEntityUse()
408
    {
409 28
        $use = [];
410
        
411 28
        if ($this->hasNamespace($this->getClassToExtend())) {
412 2
            $use[$this->getClassToExtend()] = 'use ' . $this->getClassToExtend() . ';';
413
        }
414
        
415 28
        foreach ($this->interfaces as $interface) {
416 3
            if ($this->hasNamespace($interface)) {
417 3
                $use[$interface] = 'use ' . $interface . ';';
418
            }
419
        }
420
        
421 28
        foreach ($this->traits as $trait) {
422 2
            if ($this->hasNamespace($trait)) {
423 2
                $use[$trait] = 'use ' . $trait . ';';
424
            }
425
        }
426
        
427 28
        foreach ($this->mapperInfo->objects() as $info) {
428 25
            $className = $info->className();
429 25
            if (!$info->belongsToRoot()) {
430 4
                continue;
431
            }
432
433 25
            if ($this->hasNamespace($className)) {
434 25
                $use[$className] = 'use '.$className.';';
435
            }
436
437 25
            if ($info->wrapper() !== null) {
438 1
                $repository = $this->prime->repository($className);
439 1
                $wrapperClass = $repository->collectionFactory()->wrapperClass($info->wrapper());
0 ignored issues
show
Bug introduced by
It seems like $info->wrapper() can also be of type callable; however, parameter $wrapper of Bdf\Prime\Collection\Col...Factory::wrapperClass() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

439
                $wrapperClass = $repository->collectionFactory()->wrapperClass(/** @scrutinizer ignore-type */ $info->wrapper());
Loading history...
440
441 1
                if ($this->hasNamespace($wrapperClass)) {
442 25
                    $use[$wrapperClass] = 'use '.$wrapperClass.';';
443
                }
444
            }
445
        }
446
        
447 28
        if (!$use) {
448 4
            return '';
449
        }
450
        
451 25
        sort($use);
452
        
453 25
        return implode("\n", $use) . "\n\n";
454
    }
455
    
456
    /**
457
     * @return string
458
     */
459 28
    protected function generateEntityClassName()
460
    {
461 28
        return 'class ' . $this->getClassName($this->mapperInfo->className()) .
462 28
            ($this->classToExtend ? ' extends ' . $this->getClassToExtendName() : null) .
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
463 28
            ($this->interfaces ? ' implements ' . $this->getInterfacesToImplement() : null);
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
464
    }
465
466
    /**
467
     * @return string
468
     */
469 28
    protected function generateEntityTraits()
470
    {
471 28
        if (!$this->traits) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->traits of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
472 26
            return '';
473
        }
474
        
475 2
        $traits = '';
476
        
477 2
        foreach ($this->traits as $trait) {
478 2
            $traits .= $this->spaces . 'use ' . $this->getRelativeClassName($trait) . ';' . "\n";
479
        }
480
        
481 2
        return $traits . "\n";
482
    }
483
484
    /**
485
     * @param Mapper $mapper
0 ignored issues
show
Coding Style introduced by
Superfluous parameter comment
Loading history...
introduced by
Doc comment for parameter $mapper does not match actual variable name <undefined>
Loading history...
486
     *
487
     * @return string
488
     */
489 28
    protected function generateEntityBody()
490
    {
491 28
        $fieldMappingProperties = $this->generateEntityFieldMappingProperties();
492 28
        $embeddedProperties = $this->generateEntityEmbeddedProperties();
493 28
        $stubMethods = $this->generateEntityStubMethods ? $this->generateEntityStubMethods() : null;
0 ignored issues
show
Coding Style introduced by
The value of a comparison must not be assigned to a variable
Loading history...
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
494
495 28
        $code = array();
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
496
497 28
        if ($fieldMappingProperties) {
498 28
            $code[] = $fieldMappingProperties;
499
        }
500
501 28
        if ($embeddedProperties) {
502 25
            $code[] = $embeddedProperties;
503
        }
504
505 28
        $code[] = $this->generateEntityConstructor();
506
507 28
        if ($stubMethods) {
508 27
            $code[] = $stubMethods;
509
        }
510
511 28
        return implode("\n", $code);
512
    }
513
514
    /**
515
     * @return string
516
     */
517 28
    protected function generateEntityConstructor()
518
    {
519 28
        $initializable = in_array(InitializableInterface::class, $this->interfaces);
520 28
        $isImportable  = in_array(ImportableInterface::class, $this->interfaces)
521 28
                    || is_subclass_of($this->classToExtend, ImportableInterface::class);
0 ignored issues
show
Coding Style introduced by
Boolean operators are not allowed outside of control structure conditions
Loading history...
522
523 28
        $collections = [];
524
525 28
        foreach ($this->mapperInfo->objects() as $property) {
526 25
            if (!$property->belongsToRoot()) {
527 4
                continue;
528
            }
529
530 25
            if ($property->isRelation()) {
531 24
                if (!$property->isArray()) {
532 24
                    $collections[$property->name()] = '$this->'.$property->name().' = new '.$this->getRelativeClassName($property->className()).'();';
533 21
                } elseif ($property->wrapper() === 'collection') { // @todo handle other wrapper types
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
introduced by
There should be no white space after an opening "{"
Loading history...
Coding Style introduced by
Comments may not appear after statements
Loading history...
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
534 24
                    $collections[$property->name()] = '$this->'.$property->name().' = '.$this->getRelativeClassName($property->className()).'::collection();';
535
                }
536
            } else {
537 25
                $collections[$property->name()] = '$this->'.$property->name().' = new '.$this->getRelativeClassName($property->className()).'();';
538
            }
539
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
540 28
        foreach ($this->mapperInfo->properties() as $property) {
541 28
            if ($property->isDateTime() && $property->hasDefault()) {
542 3
                $constructorArgs = '';
543
                // Add the default timezone from the property type.
544 3
                if ($timezone = $property->getTimezone()) {
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
Coding Style introduced by
Assignments must be the first block of code on a line
Loading history...
545 3
                    $constructorArgs = "'now', new \DateTimeZone('$timezone')";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $timezone instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
546
                }
547
548 28
                $collections[$property->name()] = '$this->'.$property->name().' = new '.$property->phpType().'('.$constructorArgs.');';
549
            }
550
        }
551
        
552 28
        $methods = [];
553
        
554 28
        if (!$this->hasMethod('__construct')) {
555 26
            if ($isImportable) {
556 2
                $buffer = '';
557
558 2
                if ($initializable) {
559 1
                    $buffer = '$this->initialize();'."\n".$this->spaces;
560 1
                } elseif ($collections) {
0 ignored issues
show
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
561 1
                    $buffer = implode("\n".$this->spaces, $collections)."\n".$this->spaces;
562
                }
563
564 2
                $methods[] = $this->prefixCodeWithSpaces(str_replace("<initialize>", $buffer, static::$importableConstructorMethodTemplate));
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal <initialize> does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Bug introduced by
Since $importableConstructorMethodTemplate is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $importableConstructorMethodTemplate to at least protected.
Loading history...
565 24
            } elseif ($collections && !$initializable) {
0 ignored issues
show
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
566 23
                $methods[] = $this->prefixCodeWithSpaces(str_replace("<collections>", implode("\n".$this->spaces, $collections), static::$constructorMethodTemplate));
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal <collections> does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Bug introduced by
Since $constructorMethodTemplate is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $constructorMethodTemplate to at least protected.
Loading history...
567
            }
568
        }
569
        
570 28
        if (!$this->hasMethod('initialize') && $initializable) {
571 1
            $methods[] = $this->generateMethod('{@inheritdoc}', 'initialize', implode("\n".$this->spaces, $collections));
572
        }
573
574 28
        return implode("\n", $methods);
575
    }
576
577
    /**
578
     * @param Mapper $mapper
0 ignored issues
show
Coding Style introduced by
Superfluous parameter comment
Loading history...
introduced by
Doc comment for parameter $mapper does not match actual variable name <undefined>
Loading history...
579
     *
580
     * @return string
581
     */
582 28
    protected function generateEntityDocBlock()
583
    {
584 28
        $lines = array();
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
585 28
        $lines[] = '/**';
586 28
        $lines[] = ' * ' . $this->getClassName($this->mapperInfo->className());
587 28
        $lines[] = ' */';
588
        
589 28
        return implode("\n", $lines);
590
    }
591
    
592
    /**
593
     * @return string
594
     */
595 27
    protected function generateEntityStubMethods()
596
    {
597 27
        $methods = [];
598
        
599 27
        foreach ($this->mapperInfo->properties() as $property) {
600 27
            if ($code = $this->generateEntityStubMethod('set', $property)) {
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
Coding Style introduced by
Assignments must be the first block of code on a line
Loading history...
601 27
                $methods[] = $code;
602
            }
603
604 27
            if ($code = $this->generateEntityStubMethod('get', $property)) {
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
Coding Style introduced by
Assignments must be the first block of code on a line
Loading history...
605 27
                $methods[] = $code;
606
            }
607
        }
608
609 27
        foreach ($this->mapperInfo->objects() as $property) {
610 24
            if (!$property->belongsToRoot()) {
611 4
                continue;
612
            }
613
614 24
            if (!$property->isArray() || $property->wrapper() !== null) {
615 24
                if ($code = $this->generateEntityStubMethod('set', $property)) {
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
Coding Style introduced by
Assignments must be the first block of code on a line
Loading history...
616 24
                    $methods[] = $code;
617
                }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
618 24
                if ($code = $this->generateEntityStubMethod('get', $property)) {
0 ignored issues
show
Coding Style introduced by
Assignments must be the first block of code on a line
Loading history...
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
619 24
                    $methods[] = $code;
620
                }
621
            } else {
622 19
                if ($code = $this->generateEntityStubMethod('add', $property)) {
0 ignored issues
show
Coding Style introduced by
Assignments must be the first block of code on a line
Loading history...
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
623 19
                    $methods[] = $code;
624
                }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
625 19
                if ($code = $this->generateEntityStubMethod('set', $property)) {
0 ignored issues
show
Coding Style introduced by
Assignments must be the first block of code on a line
Loading history...
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
626 19
                    $methods[] = $code;
627
                }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
628 19
                if ($code = $this->generateEntityStubMethod('get', $property)) {
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
Coding Style introduced by
Assignments must be the first block of code on a line
Loading history...
629 24
                    $methods[] = $code;
630
                }
631
            }
632
        }
0 ignored issues
show
Coding Style introduced by
End comment for long condition not found; expected "//end foreach"
Loading history...
633
634 27
        return implode("\n", $methods);
635
    }
636
637
    /**
638
     * @return string
639
     */
640 28
    protected function generateEntityFieldMappingProperties()
641
    {
642 28
        $lines = [];
643
644 28
        foreach ($this->mapperInfo->properties() as  $property) {
0 ignored issues
show
Coding Style introduced by
There should be 1 space after "as" as per the coding-style, but found 2.
Loading history...
645 28
            if ($this->hasProperty($property->name())) {
646 2
                continue;
647
            }
648
            
649 28
            $default = '';
650
651 28
            if ($property->hasDefault() && !$property->isDateTime()) {
652 4
                $default = ' = '.$this->stringfyValue(
653 4
                    $property->convert($property->getDefault())
654
                );
655 28
            } elseif ($property->isArray()) {
0 ignored issues
show
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
656 17
                $default = ' = []';
657
            }
658
659
            // A nullable property should be defined as null by default
660
            // A property is considered as nullable if it's explicitly defined on mapper or if the field is auto-generated
661 28
            if ($this->useTypedProperties && !$default && $property->isNullable()) {
662 6
                $default = ' = null';
663
            }
664
665 28
            $lines[] = $this->generateFieldMappingPropertyDocBlock($property);
666 28
            $lines[] = $this->spaces.$this->fieldVisibility.$this->getPropertyTypeHintForSimpleProperty($property).' $'.$property->name().$default.";\n";
667
        }
0 ignored issues
show
Coding Style introduced by
End comment for long condition not found; expected "//end foreach"
Loading history...
668
669 28
        return implode("\n", $lines);
670
    }
671
672
    /**
673
     * @return string
674
     */
675 28
    protected function generateEntityEmbeddedProperties()
676
    {
677 28
        $lines = array();
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
678
679 28
        foreach ($this->mapperInfo->objects() as $property) {
680 25
            if (!$property->belongsToRoot() || $this->hasProperty($property->name())) {
681 6
                continue;
682
            }
683
            
684 25
            if (!$property->isRelation()) {
685 4
                $lines[] = $this->generateEmbeddedPropertyDocBlock($property);
686 4
                $lines[] = $this->spaces . $this->fieldVisibility . $this->getPropertyTypeHintForObject($property) . ' $'.$property->name().";\n";
687
            } else {
688 24
                $name = $property->name();
689 24
                $default = '';
690
691
                // Do not initialize the property if it's a wrapper
692 24
                if ($property->isArray() && $property->wrapper() === null) {
693 18
                    $default = ' = []';
694
                }
695
696
                // If property is typed, always define a default value
697 24
                if ($this->useTypedProperties && !$default) {
698 7
                    $default = ' = null';
699
                }
700
701 24
                $lines[] = $this->generateEmbeddedPropertyDocBlock($property);
702 25
                $lines[] = $this->spaces . $this->fieldVisibility . $this->getPropertyTypeHintForObject($property) . ' $' . $name . $default .";\n";
703
            }
704
        }
0 ignored issues
show
Coding Style introduced by
End comment for long condition not found; expected "//end foreach"
Loading history...
705
706 28
        return implode("\n", $lines);
707
    }
708
709
    /**
710
     * @param string            $type
711
     * @param InfoInterface     $propertyInfo
712
     * @param string|null       $defaultValue
713
     *
714
     * @return string
715
     */
716 27
    protected function generateEntityStubMethod($type, InfoInterface $propertyInfo, $defaultValue = null)
717
    {
718 27
        $fieldName = $propertyInfo->name();
719
720
        // The hint flag help algorythm to determine the hint info for object parameter.
721
        // It should be 'array' for collection but the add method need the object hint.
722
        // setItems(array $items)
723
        // addItem(Item $item)
724 27
        $hintOne = false;
725
726 27
        if ($type === 'get' && $this->useGetShortcutMethod === true) {
727 26
            $variableName = $this->inflector->camelize($fieldName);
728 26
            $methodName = $variableName;
729
        } else {
730 27
            $methodName = $type . $this->inflector->classify($fieldName);
731 27
            $variableName = $this->inflector->camelize($fieldName);
732
        }
733
        
734 27
        if ($type === 'add') {
735 19
            $methodName = $this->inflector->singularize($methodName);
736 19
            $variableName = $this->inflector->singularize($variableName);
737 19
            $hintOne = true;
738
        }
739
740 27
        if ($this->hasMethod($methodName)) {
741
            return '';
742
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
743 27
        $this->staticReflection[$this->mapperInfo->className()]['methods'][] = strtolower($methodName);
744
745 27
        if ($propertyInfo->isObject()) {
746 24
            $variableType = $this->getRelativeClassName($propertyInfo->className());
0 ignored issues
show
Bug introduced by
The method className() does not exist on Bdf\Prime\Mapper\Info\InfoInterface. It seems like you code against a sub-type of Bdf\Prime\Mapper\Info\InfoInterface such as Bdf\Prime\Mapper\Info\ObjectPropertyInfo. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

746
            $variableType = $this->getRelativeClassName($propertyInfo->/** @scrutinizer ignore-call */ className());
Loading history...
747 24
            $methodTypeHint =  $variableType.' ';
0 ignored issues
show
Coding Style introduced by
Expected 1 space after "="; 2 found
Loading history...
748
        } else {
749 27
            $variableType = $propertyInfo->phpType();
0 ignored issues
show
Bug introduced by
The method phpType() does not exist on Bdf\Prime\Mapper\Info\InfoInterface. It seems like you code against a sub-type of Bdf\Prime\Mapper\Info\InfoInterface such as Bdf\Prime\Mapper\Info\PropertyInfo. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

749
            /** @scrutinizer ignore-call */ 
750
            $variableType = $propertyInfo->phpType();
Loading history...
750 27
            $methodTypeHint = null;
751
        }
752
753 27
        if ($propertyInfo->isArray() && $hintOne === false) {
754 20
            if ($propertyInfo->isObject() && $propertyInfo->wrapper() !== null) {
0 ignored issues
show
Bug introduced by
The method wrapper() does not exist on Bdf\Prime\Mapper\Info\InfoInterface. It seems like you code against a sub-type of Bdf\Prime\Mapper\Info\InfoInterface such as Bdf\Prime\Mapper\Info\ObjectPropertyInfo. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

754
            if ($propertyInfo->isObject() && $propertyInfo->/** @scrutinizer ignore-call */ wrapper() !== null) {
Loading history...
755 1
                $repository = $this->prime->repository($propertyInfo->className());
756 1
                $wrapperClass = $this->getRelativeClassName($repository->collectionFactory()->wrapperClass($propertyInfo->wrapper()));
757
758 1
                $methodTypeHint = $wrapperClass.' ';
759 1
                $variableType .= '[]|'.$wrapperClass;
760
            } else {
761 19
                $methodTypeHint = 'array ';
762
763 19
                if ($variableType !== 'array') {
764 19
                    $variableType .= '[]';
765
                }
766
            }
767
        }
768
769
        $replacements = array(
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
770 27
          '<description>'       => ucfirst($type).' '.$variableName,
0 ignored issues
show
Coding Style introduced by
Array key not indented correctly; expected 12 spaces but found 10
Loading history...
771 27
          '<methodTypeHint>'    => $methodTypeHint,
0 ignored issues
show
Coding Style introduced by
Array key not indented correctly; expected 12 spaces but found 10
Loading history...
772 27
          '<variableType>'      => $variableType,
0 ignored issues
show
Coding Style introduced by
Array key not indented correctly; expected 12 spaces but found 10
Loading history...
773 27
          '<variableName>'      => $variableName,
0 ignored issues
show
Coding Style introduced by
Array key not indented correctly; expected 12 spaces but found 10
Loading history...
774 27
          '<methodName>'        => $methodName,
0 ignored issues
show
Coding Style introduced by
Array key not indented correctly; expected 12 spaces but found 10
Loading history...
775 27
          '<fieldName>'         => $fieldName,
0 ignored issues
show
Coding Style introduced by
Array key not indented correctly; expected 12 spaces but found 10
Loading history...
776 27
          '<variableDefault>'   => ($defaultValue !== null ) ? (' = '.$defaultValue) : ''
0 ignored issues
show
introduced by
A comma should follow the last multiline array item. Found: ''
Loading history...
Coding Style introduced by
Array key not indented correctly; expected 12 spaces but found 10
Loading history...
introduced by
There should be no white space before a closing ")"
Loading history...
777
        );
778
779 27
        $method = str_replace(
780 27
            array_keys($replacements),
781 27
            array_values($replacements),
782 27
            $this->getMethodTemplate($type)
783
        );
784
785 27
        return $this->prefixCodeWithSpaces($method);
786
    }
787
788
    /**
789
     * Get the template of the method
790
     *
791
     * @param string $prefix
792
     *
793
     * @return string
794
     *
795
     * @throws \LogicException
796
     */
797 27
    private function getMethodTemplate($prefix)
0 ignored issues
show
Coding Style introduced by
Private method name "EntityGenerator::getMethodTemplate" must be prefixed with an underscore
Loading history...
798
    {
799
        switch ($prefix) {
800 27
            case 'get':
801 27
                return static::$getMethodTemplate;
0 ignored issues
show
Bug introduced by
Since $getMethodTemplate is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $getMethodTemplate to at least protected.
Loading history...
introduced by
Case breaking statement indented incorrectly; expected 14 spaces, found 16
Loading history...
802
803 27
            case 'add':
804 19
                return static::$addMethodTemplate;
0 ignored issues
show
introduced by
Case breaking statement indented incorrectly; expected 14 spaces, found 16
Loading history...
Bug introduced by
Since $addMethodTemplate is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $addMethodTemplate to at least protected.
Loading history...
805
806 27
            case 'set':
807 27
                return static::$setMethodTemplate;
0 ignored issues
show
Bug introduced by
Since $setMethodTemplate is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $setMethodTemplate to at least protected.
Loading history...
introduced by
Case breaking statement indented incorrectly; expected 14 spaces, found 16
Loading history...
808
        }
809
810
        throw new \LogicException('No template found for method "'.$prefix.'"');
811
    }
812
813
    /**
814
     * @param string $description
815
     * @param string $methodName
816
     * @param string $content
817
     *
818
     * @return string
819
     */
820 1
    protected function generateMethod($description, $methodName, $content = null)
821
    {
822 1
        if ($this->hasMethod($methodName)) {
823
            return '';
824
        }
825
        
826 1
        $this->staticReflection[$this->mapperInfo->className()]['methods'][] = $methodName;
827
828
        $replacements = array(
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
829 1
            '<description>' => $description,
830 1
            '<methodName>'  => $methodName,
831 1
            '<content>'     => $content,
832
        );
833
834 1
        $method = str_replace(
835 1
            array_keys($replacements),
836 1
            array_values($replacements),
837 1
            static::$methodTemplate
0 ignored issues
show
Bug introduced by
Since $methodTemplate is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $methodTemplate to at least protected.
Loading history...
838
        );
839
840 1
        return $this->prefixCodeWithSpaces($method);
841
    }
842
843
    /**
844
     * @param PropertyInfo $property
845
     *
846
     * @return string
847
     */
848 28
    protected function generateFieldMappingPropertyDocBlock($property)
0 ignored issues
show
introduced by
Type hint "PropertyInfo" missing for $property
Loading history...
849
    {
850 28
        $lines = array();
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
851 28
        $lines[] = $this->spaces . '/**';
852 28
        $lines[] = $this->spaces . ' * @var '.$property->phpType();
853 28
        $lines[] = $this->spaces . ' */';
854
855 28
        return implode("\n", $lines);
856
    }
857
858
    /**
859
     * @param ObjectPropertyInfo $property
860
     *
861
     * @return string
862
     */
863 25
    protected function generateEmbeddedPropertyDocBlock($property)
0 ignored issues
show
introduced by
Type hint "ObjectPropertyInfo" missing for $property
Loading history...
864
    {
865 25
        $className = $property->className();
866 25
        if ($className) {
867 25
            $className = $this->getRelativeClassName($className);
868
869 25
            if ($property->isArray()) {
870 19
                if ($property->wrapper() !== null) {
0 ignored issues
show
introduced by
The condition $property->wrapper() !== null is always true.
Loading history...
871 1
                    $repository = $this->prime->repository($property->className());
872 1
                    $className = $this->getRelativeClassName($repository->collectionFactory()->wrapperClass($property->wrapper())).'|'.$className.'[]';
0 ignored issues
show
Bug introduced by
It seems like $property->wrapper() can also be of type callable; however, parameter $wrapper of Bdf\Prime\Collection\Col...Factory::wrapperClass() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

872
                    $className = $this->getRelativeClassName($repository->collectionFactory()->wrapperClass(/** @scrutinizer ignore-type */ $property->wrapper())).'|'.$className.'[]';
Loading history...
873
                } else {
874 25
                    $className .= '[]';
875
                }
876
            }
877
        } else {
878
            $className = '{type}';
879
        }
880
        
881 25
        $lines = array();
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
882 25
        $lines[] = $this->spaces . '/**';
883 25
        $lines[] = $this->spaces . ' * @var '.$className;
884 25
        $lines[] = $this->spaces . ' */';
885
886 25
        return implode("\n", $lines);
887
    }
888
    
889
    //
890
    //---------- tools methods
0 ignored issues
show
Coding Style introduced by
No space found before comment text; expected "// ---------- tools methods" but found "//---------- tools methods"
Loading history...
891
    //
892
893
    /**
894
     * @todo this won't work if there is a namespace in brackets and a class outside of it.
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
895
     *
896
     * @param string $src
0 ignored issues
show
Coding Style introduced by
Parameter tags must be defined first in a doc comment
Loading history...
897
     *
898
     * @return void
0 ignored issues
show
introduced by
If there is no return value for a function, there must not be a @return tag.
Loading history...
899
     */
900
    protected function parseTokensInEntityFile($src)
901
    {
902
        $tokens = token_get_all($src);
903
        $lastSeenNamespace = "";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
904
        $lastSeenClass = false;
905
906
        $inNamespace = false;
907
        $inClass = false;
908
909
        for ($i = 0; $i < count($tokens); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
Performance Best Practice introduced by
Consider avoiding function calls on each iteration of the for loop.

If you have a function call in the test part of a for loop, this function is executed on each iteration. Often such a function, can be moved to the initialization part and be cached.

// count() is called on each iteration
for ($i=0; $i < count($collection); $i++) { }

// count() is only called once
for ($i=0, $c=count($collection); $i<$c; $i++) { }
Loading history...
Coding Style Performance introduced by
The use of count() inside a loop condition is not allowed; assign the return value to a variable and use the variable in the loop condition instead
Loading history...
910
            $token = $tokens[$i];
911
            if (in_array($token[0], array(T_WHITESPACE, T_COMMENT, T_DOC_COMMENT))) {
0 ignored issues
show
introduced by
If the line declaring an array spans longer than 80 characters, each element should be broken into its own line
Loading history...
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
912
                continue;
913
            }
914
915
            if ($inNamespace) {
916
                if ($token[0] == T_NS_SEPARATOR || $token[0] == T_STRING) {
917
                    $lastSeenNamespace .= $token[1];
918
                } elseif (is_string($token) && in_array($token, array(';', '{'))) {
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
919
                    $inNamespace = false;
920
                }
921
            }
922
923
            if ($inClass) {
924
                $inClass = false;
925
                $lastSeenClass = $lastSeenNamespace . ($lastSeenNamespace ? '\\' : '') . $token[1];
0 ignored issues
show
Coding Style introduced by
The value of a comparison must not be assigned to a variable
Loading history...
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
926
                $this->staticReflection[$lastSeenClass]['properties'] = array();
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
927
                $this->staticReflection[$lastSeenClass]['methods'] = array();
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
928
            }
929
930
            if ($token[0] == T_NAMESPACE) {
931
                $lastSeenNamespace = "";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
932
                $inNamespace = true;
933
            } elseif ($token[0] == T_CLASS && $tokens[$i-1][0] != T_DOUBLE_COLON) {
0 ignored issues
show
Coding Style introduced by
Operation must be bracketed
Loading history...
Coding Style introduced by
Expected 1 space after "-"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space before "-"; 0 found
Loading history...
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
934
                $inClass = true;
935
            } elseif ($token[0] == T_FUNCTION) {
0 ignored issues
show
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
936
                if ($tokens[$i+2][0] == T_STRING) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "+"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "+"; 0 found
Loading history...
Coding Style introduced by
Operation must be bracketed
Loading history...
937
                    $this->staticReflection[$lastSeenClass]['methods'][] = strtolower($tokens[$i+2][1]);
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "+"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "+"; 0 found
Loading history...
Coding Style introduced by
Operation must be bracketed
Loading history...
938
                } elseif ($tokens[$i+2] == "&" && $tokens[$i+3][0] == T_STRING) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after "+"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space before "+"; 0 found
Loading history...
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
Coding Style introduced by
Operation must be bracketed
Loading history...
Coding Style Comprehensibility introduced by
The string literal & does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
939
                    $this->staticReflection[$lastSeenClass]['methods'][] = strtolower($tokens[$i+3][1]);
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "+"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "+"; 0 found
Loading history...
Coding Style introduced by
Operation must be bracketed
Loading history...
940
                }
941
            } elseif (in_array($token[0], array(T_VAR, T_PUBLIC, T_PRIVATE, T_PROTECTED)) && $tokens[$i+2][0] != T_FUNCTION) {
0 ignored issues
show
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
introduced by
If the line declaring an array spans longer than 80 characters, each element should be broken into its own line
Loading history...
Coding Style introduced by
Expected 1 space before "+"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "+"; 0 found
Loading history...
Coding Style introduced by
Operation must be bracketed
Loading history...
942
                $this->staticReflection[$lastSeenClass]['properties'][] = substr($tokens[$i+2][1], 1);
0 ignored issues
show
Coding Style introduced by
Expected 1 space after "+"; 0 found
Loading history...
Coding Style introduced by
Operation must be bracketed
Loading history...
Coding Style introduced by
Expected 1 space before "+"; 0 found
Loading history...
943
            }
944
        }
0 ignored issues
show
Coding Style introduced by
End comment for long condition not found; expected "//end for"
Loading history...
945
    }
946
947
    /**
948
     * @param string $property
949
     *
950
     * @return bool
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for function return type
Loading history...
951
     */
952 28
    protected function hasProperty($property)
953
    {
954 28
        if ($this->classToExtend || (!$this->isNew && class_exists($this->mapperInfo->className()))) {
955
            // don't generate property if its already on the base class.
0 ignored issues
show
Coding Style Documentation introduced by
Inline comments must start with a capital letter
Loading history...
956 2
            $reflClass = new \ReflectionClass($this->getClassToExtend() ?: $this->mapperInfo->className());
0 ignored issues
show
Coding Style introduced by
The value of a comparison must not be assigned to a variable
Loading history...
957 2
            if ($reflClass->hasProperty($property)) {
958 2
                return true;
959
            }
960
        }
961
962
        // check traits for existing property
0 ignored issues
show
Coding Style Documentation introduced by
Inline comments must start with a capital letter
Loading history...
963 28
        foreach ($this->getTraitsReflections() as $trait) {
964
            if ($trait->hasProperty($property)) {
965
                return true;
966
            }
967
        }
968
969
        return (
970 28
            isset($this->staticReflection[$this->mapperInfo->className()]) &&
0 ignored issues
show
Coding Style introduced by
Boolean operators are not allowed outside of control structure conditions
Loading history...
971 28
            in_array($property, $this->staticReflection[$this->mapperInfo->className()]['properties'])
972
        );
973
    }
974
975
    /**
976
     * @param string $method
977
     *
978
     * @return bool
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for function return type
Loading history...
979
     */
980 28
    protected function hasMethod($method)
981
    {
982 28
        if ($this->classToExtend || (!$this->isNew && class_exists($this->mapperInfo->className()))) {
983
            // don't generate method if its already on the base class.
0 ignored issues
show
Coding Style Documentation introduced by
Inline comments must start with a capital letter
Loading history...
984 2
            $reflClass = new \ReflectionClass($this->getClassToExtend() ?: $this->mapperInfo->className());
0 ignored issues
show
Coding Style introduced by
The value of a comparison must not be assigned to a variable
Loading history...
985
986 2
            if ($reflClass->hasMethod($method)) {
987 2
                return true;
988
            }
989
        }
990
991
        // check traits for existing method
0 ignored issues
show
Coding Style Documentation introduced by
Inline comments must start with a capital letter
Loading history...
992 28
        foreach ($this->getTraitsReflections() as $trait) {
993
            if ($trait->hasMethod($method)) {
994
                return true;
995
            }
996
        }
997
998
        return (
999 28
            isset($this->staticReflection[$this->mapperInfo->className()]) &&
0 ignored issues
show
Coding Style introduced by
Boolean operators are not allowed outside of control structure conditions
Loading history...
1000 28
            in_array(strtolower($method), $this->staticReflection[$this->mapperInfo->className()]['methods'])
1001
        );
1002
    }
1003
1004
    /**
1005
     * Get class name relative to use
1006
     * 
1007
     * @param string $className
1008
     * @return string
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
1009
     */
1010 25
    protected function getRelativeClassName($className)
1011
    {
1012 25
        $className = ltrim($className, '\\');
1013
        
1014 25
        if ($this->hasNamespace($className)) {
1015 25
            return $this->getClassName($className);
1016
        } else {
1017 3
            return '\\' . $className;
1018
        }
1019
    }
1020
    
1021
    /**
1022
     * Get the class short name
1023
     * 
1024
     * @param string $className
1025
     *
1026
     * @return string
1027
     */
1028 28
    protected function getClassName($className)
1029
    {
1030 28
        $parts = explode('\\', $className);
1031 28
        return array_pop($parts);
1032
    }
1033
1034
    /**
1035
     * @param string $className
1036
     *
1037
     * @return string
1038
     */
1039 28
    protected function getNamespace($className)
1040
    {
1041 28
        $parts = explode('\\', $className);
1042 28
        array_pop($parts);
1043
        
1044 28
        return implode('\\', $parts);
1045
    }
1046
    
1047
    /**
1048
     * @param string $className
1049
     *
1050
     * @return bool
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for function return type
Loading history...
1051
     */
1052 28
    protected function hasNamespace($className)
1053
    {
1054 28
        return strrpos($className, '\\') != 0;
1055
    }
1056
1057
    /**
1058
     * @return string
1059
     */
1060 2
    protected function getClassToExtendName()
1061
    {
1062 2
        $refl = new \ReflectionClass($this->getClassToExtend());
1063
1064 2
        return $this->getRelativeClassName($refl->getName());
1065
    }
1066
1067
    /**
1068
     * @return string
1069
     */
1070 3
    protected function getInterfacesToImplement()
1071
    {
1072 3
        $interfaces = [];
1073
        
1074 3
        foreach ($this->interfaces as $interface) {
1075 3
            $refl = new \ReflectionClass($interface);
1076
1077 3
            $interfaces[] = $this->getRelativeClassName($refl->getName());
1078
        }
1079
        
1080 3
        return implode(', ', $interfaces);
1081
    }
1082
    
1083
    /**
1084
     * @param Mapper $mapper
0 ignored issues
show
Coding Style introduced by
Superfluous parameter comment
Loading history...
introduced by
Doc comment for parameter $mapper does not match actual variable name <undefined>
Loading history...
1085
     *
1086
     * @return \ReflectionClass[]
1087
     */
1088 28
    protected function getTraitsReflections()
1089
    {
1090 28
        if ($this->isNew) {
1091 28
            return [];
1092
        }
1093
        
1094
        $reflClass = new \ReflectionClass($this->mapperInfo->className());
1095
1096
        $traits = array();
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
1097
1098
        while ($reflClass !== false) {
1099
            $traits = array_merge($traits, $reflClass->getTraits());
0 ignored issues
show
Bug introduced by
It seems like $reflClass->getTraits() can also be of type null; however, parameter $arrays of array_merge() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1099
            $traits = array_merge($traits, /** @scrutinizer ignore-type */ $reflClass->getTraits());
Loading history...
1100
1101
            $reflClass = $reflClass->getParentClass();
1102
        }
1103
1104
        return $traits;
1105
    }
1106
    
1107
    /**
1108
     * @param string $code
1109
     * @param int    $num
0 ignored issues
show
Coding Style introduced by
Expected "integer" but found "int" for parameter type
Loading history...
1110
     *
1111
     * @return string
1112
     */
1113 28
    protected function prefixCodeWithSpaces($code, $num = 1)
1114
    {
1115 28
        $lines = explode("\n", $code);
1116
1117 28
        foreach ($lines as $key => $value) {
1118 28
            if ( ! empty($value)) {
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces after opening bracket; 1 found
Loading history...
Coding Style introduced by
First condition of a multi-line IF statement must directly follow the opening parenthesis
Loading history...
introduced by
There should be no white space after an opening "("
Loading history...
introduced by
A unary operator statement must not be followed by a space
Loading history...
1119 28
                $lines[$key] = str_repeat($this->spaces, $num) . $lines[$key];
1120
            }
1121
        }
1122
1123 28
        return implode("\n", $lines);
1124
    }
1125
    
1126
    /**
1127
     * Get string representation of a value
1128
     * 
1129
     * @param mixed $value
1130
     *
1131
     * @return string
1132
     */
1133 4
    protected function stringfyValue($value)
1134
    {
1135 4
        if (is_array($value)) {
1136
            if (empty($value)) {
1137
                return '[]';
1138
            }
1139
            
1140
            return var_export($value, true);
1141
        }
1142
        
1143 4
        if (null === $value) {
1144
            return 'null';
1145
        }
1146
        
1147 4
        if (is_string($value)) {
1148 3
            return "'" . $value . "'";
1149
        }
1150
        
1151 2
        if (is_bool($value)) {
1152 2
            return $value ? 'true' : 'false';
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
1153
        }
1154
1155
        return $value;
1156
    }
1157
1158
    /**
1159
     * Get the php 7.4 property type hint
1160
     *
1161
     * This method will map invalid type hint to value one (ex: double -> float)
1162
     * It will also resolve the relative class name if the type is a class
0 ignored issues
show
introduced by
Doc comment long description must end with a full stop
Loading history...
1163
     *
1164
     * @param string $type The property type declared by field phpType()
1165
     * @param bool $nullable Does the property should be nullable
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for parameter type
Loading history...
1166
     *
1167
     * @return string
1168
     *
1169
     * @see TypeInterface::phpType()
1170
     *
1171
     * @todo use directly the property info object ?
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
1172
     */
1173 7
    protected function getPropertyTypeHint(string $type, bool $nullable): string
1174
    {
1175 7
        if (class_exists($type)) {
1176 7
            $type = $this->getRelativeClassName($type);
1177
        } else {
1178 7
            $type = self::PROPERTY_TYPE_MAP[$type] ?? $type;
0 ignored issues
show
Coding Style introduced by
Operation must be bracketed
Loading history...
1179
        }
1180
1181 7
        return ($nullable ? '?' : '') . $type;
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
1182
    }
1183
1184
    /**
1185
     * Get the php 7.4 property type hint for a simple property
1186
     *
1187
     * If typed properties are disabled, this method will return an empty string
1188
     * The returned type hint will be prefixed by a single space
0 ignored issues
show
introduced by
Doc comment long description must end with a full stop
Loading history...
1189
     *
1190
     * @param PropertyInfo $property
1191
     *
1192
     * @return string
1193
     */
1194 28
    protected function getPropertyTypeHintForSimpleProperty(PropertyInfo $property): string
1195
    {
1196 28
        if (!$this->useTypedProperties) {
1197 26
            return '';
1198
        }
1199
1200 7
        return ' ' . $this->getPropertyTypeHint($property->phpType(), $property->isNullable());
1201
    }
1202
1203
    /**
1204
     * Get the php 7.4 property type hint for a object property (i.e. relation or embedded)
1205
     *
1206
     * If typed properties are disabled, this method will return an empty string
1207
     * The returned type hint will be prefixed by a single space
0 ignored issues
show
introduced by
Doc comment long description must end with a full stop
Loading history...
1208
     *
1209
     * - Embedded properties will not be marked as nullable
1210
     * - Relations will always be nullable
1211
     * - This method will also resolve collection relations and the wrapper class if provided
1212
     *
1213
     * @param ObjectPropertyInfo $property
1214
     *
1215
     * @return string
1216
     */
1217 25
    protected function getPropertyTypeHintForObject(ObjectPropertyInfo $property): string
1218
    {
1219 25
        if (!$this->useTypedProperties) {
1220 23
            return '';
1221
        }
1222
1223 7
        $type = $property->className();
1224
1225 7
        if ($property->isArray()) {
1226 5
            if ($property->wrapper() === null) {
0 ignored issues
show
introduced by
The condition $property->wrapper() === null is always false.
Loading history...
1227 4
                $type = 'array';
1228
            } else {
1229 1
                $repository = $this->prime->repository($type);
1230 1
                $type = $repository->collectionFactory()->wrapperClass($property->wrapper());
0 ignored issues
show
Bug introduced by
It seems like $property->wrapper() can also be of type callable; however, parameter $wrapper of Bdf\Prime\Collection\Col...Factory::wrapperClass() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1230
                $type = $repository->collectionFactory()->wrapperClass(/** @scrutinizer ignore-type */ $property->wrapper());
Loading history...
1231
            }
1232
        }
1233
1234 7
        return ' ' . $this->getPropertyTypeHint($type, $property->isRelation());
0 ignored issues
show
Bug introduced by
It seems like $type can also be of type null; however, parameter $type of Bdf\Prime\Entity\EntityG...::getPropertyTypeHint() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1234
        return ' ' . $this->getPropertyTypeHint(/** @scrutinizer ignore-type */ $type, $property->isRelation());
Loading history...
1235
    }
1236
1237
    //---------------------- mutators
0 ignored issues
show
Coding Style introduced by
No space found before comment text; expected "// ---------------------- mutators" but found "//---------------------- mutators"
Loading history...
1238
1239
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $numSpaces should have a doc-comment as per coding-style.
Loading history...
1240
     * Sets the number of spaces the exported class should have.
1241
     *
1242
     * @api
1243
     */
1244 1
    public function setNumSpaces(int $numSpaces): void
1245
    {
1246 1
        $this->spaces = str_repeat(' ', $numSpaces);
1247 1
        $this->numSpaces = $numSpaces;
1248 1
    }
1249
1250
    /**
1251
     * Gets the indentation spaces
1252
     */
1253 1
    public function getNumSpaces(): int
1254
    {
1255 1
        return $this->numSpaces;
1256
    }
1257
1258
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $extension should have a doc-comment as per coding-style.
Loading history...
1259
     * Sets the extension to use when writing php files to disk.
1260
     *
1261
     * @api
1262
     */
1263 1
    public function setExtension(string $extension): void
1264
    {
1265 1
        $this->extension = $extension;
1266 1
    }
1267
1268
    /**
1269
     * Get the file extension
1270
     */
1271 1
    public function getExtension(): string
1272
    {
1273 1
        return $this->extension;
1274
    }
1275
1276
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $classToExtend should have a doc-comment as per coding-style.
Loading history...
1277
     * Sets the name of the class the generated classes should extend from.
1278
     *
1279
     * @api
1280
     */
1281 3
    public function setClassToExtend(string $classToExtend): void
1282
    {
1283 3
        $this->classToExtend = $classToExtend;
1284 3
    }
1285
1286
    /**
1287
     * Get the class to extend
1288
     */
1289 29
    public function getClassToExtend(): ?string
1290
    {
1291 29
        return $this->classToExtend;
1292
    }
1293
1294
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $interface should have a doc-comment as per coding-style.
Loading history...
1295
     * Add interface to implement
1296
     *
1297
     * @api
1298
     */
1299 2
    public function addInterface(string $interface)
1300
    {
1301 2
        $this->interfaces[$interface] = $interface;
1302 2
    }
1303
1304
    /**
1305
     * Sets the interfaces
1306
     *
1307
     * @param string[] $interfaces
1308
     *
1309
     * @api
1310
     */
1311 2
    public function setInterfaces(array $interfaces): void
1312
    {
1313 2
        $this->interfaces = $interfaces;
1314 2
    }
1315
1316
    /**
1317
     * Get the registered interfaces
1318
     */
1319 1
    public function getInterfaces(): array
1320
    {
1321 1
        return $this->interfaces;
1322
    }
1323
1324
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $trait should have a doc-comment as per coding-style.
Loading history...
1325
     * Add trait
1326
     *
1327
     * @api
1328
     */
1329 2
    public function addTrait(string $trait)
1330
    {
1331 2
        $this->traits[$trait] = $trait;
1332 2
    }
1333
1334
    /**
1335
     * Sets the traits
1336
     *
1337
     * @param string[] $traits
1338
     *
1339
     * @api
1340
     */
1341 1
    public function setTraits(array $traits): void
1342
    {
1343 1
        $this->traits = $traits;
1344 1
    }
1345
1346
    /**
1347
     * Get the registered traits
1348
     */
1349 1
    public function getTraits(): array
1350
    {
1351 1
        return $this->traits;
1352
    }
1353
1354
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $visibility should have a doc-comment as per coding-style.
Loading history...
1355
     * Sets the class fields visibility for the entity (can either be private or protected).
1356
     *
1357
     * @throws \InvalidArgumentException
1358
     *
1359
     * @api
1360
     */
1361 2
    public function setFieldVisibility(string $visibility): void
1362
    {
1363 2
        if ($visibility !== static::FIELD_VISIBLE_PRIVATE && $visibility !== static::FIELD_VISIBLE_PROTECTED) {
1364
            throw new \InvalidArgumentException('Invalid provided visibility (only private and protected are allowed): ' . $visibility);
1365
        }
1366
1367 2
        $this->fieldVisibility = $visibility;
1368 2
    }
1369
1370
    /**
1371
     * Get the field visibility
1372
     */
1373 1
    public function getFieldVisibility(): string
1374
    {
1375 1
        return $this->fieldVisibility;
1376
    }
1377
1378
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $bool should have a doc-comment as per coding-style.
Loading history...
1379
     * Sets whether or not to try and update the entity if it already exists.
1380
     *
1381
     * @api
1382
     */
1383 1
    public function setUpdateEntityIfExists(bool $bool): void
1384
    {
1385 1
        $this->updateEntityIfExists = $bool;
1386 1
    }
1387
1388
    /**
1389
     * Get the flag for updating the entity
1390
     */
1391 1
    public function getUpdateEntityIfExists(): bool
1392
    {
1393 1
        return $this->updateEntityIfExists;
1394
    }
1395
1396
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $bool should have a doc-comment as per coding-style.
Loading history...
1397
     * Sets whether or not to regenerate the entity if it exists.
1398
     *
1399
     * @api
1400
     */
1401 1
    public function setRegenerateEntityIfExists(bool $bool): void
1402
    {
1403 1
        $this->regenerateEntityIfExists = $bool;
1404 1
    }
1405
1406
    /**
1407
     * Get the flag for regenerating entity
1408
     */
1409 1
    public function getRegenerateEntityIfExists(): bool
1410
    {
1411 1
        return $this->regenerateEntityIfExists;
1412
    }
1413
1414
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $bool should have a doc-comment as per coding-style.
Loading history...
1415
     * Sets whether or not to generate stub methods for the entity.
1416
     *
1417
     * @api
1418
     */
1419 2
    public function setGenerateStubMethods(bool $bool): void
1420
    {
1421 2
        $this->generateEntityStubMethods = $bool;
1422 2
    }
1423
1424
    /**
1425
     * Get the flag for generating stub methods
1426
     */
1427 1
    public function getGenerateStubMethods(): bool
1428
    {
1429 1
        return $this->generateEntityStubMethods;
1430
    }
1431
1432
    /**
1433
     * Sets whether or not the get mehtod will be suffixed by 'get'.
1434
     *
1435
     * @param bool $bool
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for parameter type
Loading history...
1436
     *
1437
     * @return void
0 ignored issues
show
introduced by
If there is no return value for a function, there must not be a @return tag.
Loading history...
1438
     *
1439
     * @api
1440
     */
1441 2
    public function useGetShortcutMethod($bool = true)
1442
    {
1443 2
        $this->useGetShortcutMethod = $bool;
1444 2
    }
1445
1446
    /**
1447
     * Get the flag for get mehtod name.
1448
     */
1449 1
    public function getUseGetShortcutMethod(): bool
1450
    {
1451 1
        return $this->useGetShortcutMethod;
1452
    }
1453
1454
    /**
1455
     * @return bool
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for function return type
Loading history...
1456
     */
1457
    public function getUseTypedProperties(): bool
1458
    {
1459
        return $this->useTypedProperties;
1460
    }
1461
1462
    /**
1463
     * Enable usage of php 7.4 type properties
1464
     *
1465
     * @param bool $useTypedProperties
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for parameter type
Loading history...
1466
     */
1467 7
    public function useTypedProperties(bool $useTypedProperties = true): void
1468
    {
1469 7
        $this->useTypedProperties = $useTypedProperties;
1470 7
    }
1471
}
1472