PhpClass::getConstantCollection()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the ClassGeneration package.
5
 *
6
 * (c) Antonio Spinelli <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ClassGeneration;
13
14
use ClassGeneration\Composition\MethodInterface as CompositionMethodInterface;
15
use ClassGeneration\Element\ElementAbstract;
16
17
/**
18
 * Class to create a PhpClass Object
19
 * @author Antonio Spinelli <[email protected]>
20
 */
21
class PhpClass extends ElementAbstract implements PhpClassInterface
22
{
23
24
    /**
25
     * Sets like a trait.
26
     * @var boolean
27
     */
28
    protected $isTrait = false;
29
30
    /**
31
     * Sets like an interface.
32
     * @var boolean
33
     */
34
    protected $isInterface = false;
35
36
    /**
37
     * Set like a final.
38
     * @var bool
39
     */
40
    protected $isFinal = false;
41
42
    /**
43
     * Set like an abstract.
44
     * @var bool
45
     */
46
    protected $isAbstract = false;
47
48
    /**
49
     * Documentation Block
50
     * @var DocBlockInterface
51
     */
52
    protected $docBlock;
53
54
    /**
55
     * Class name
56
     * @var string
57
     */
58
    protected $name;
59
60
    /**
61
     * Class namespace
62
     * @var NamespaceInterface
63
     */
64
    protected $namespace;
65
66
    /**
67
     * Class Use Collection
68
     * @var UseCollection
69
     */
70
    protected $useCollection;
71
72
    /**
73
     * Class constants
74
     * @var ConstantCollection
75
     */
76
    protected $constants;
77
78
    /**
79
     * Class properties
80
     * @var PropertyCollection
81
     */
82
    protected $properties;
83
84
    /**
85
     * Class methods
86
     * @var MethodCollection
87
     */
88
    protected $methods;
89
90
    /**
91
     * Extends from.
92
     * @var string
93
     */
94
    protected $extends;
95
96
    /**
97
     * Implements the interfaces.
98
     * @var InterfaceCollection
99
     */
100
    protected $interfaces;
101
102
    /**
103
     * @var CompositionCollection
104
     */
105
    protected $compositionCollection;
106
107
    /**
108
     * Force on add method on class docblock.
109
     * @var boolean
110
     */
111
    public $forceMethodInDocBlock = false;
112
113
    /**
114
     * Force on add property on class docblock.
115
     * @var boolean
116
     */
117
    public $forcePropertyInDocBlock = false;
118
119
    /**
120
     * {@inheritdoc}
121
     */
122 36
    public function init()
123
    {
124 36
        $this->setTabulation(0);
125 36
        $this->setDocBlock(new DocBlock());
126 36
        $this->setMethodCollection(new MethodCollection());
127 36
        $this->setPropertyCollection(new PropertyCollection());
128 36
        $this->setConstantCollection(new ConstantCollection());
129 36
        $this->setInterfaceCollection(new InterfaceCollection());
130 36
        $this->setNamespace(new NamespaceClass());
131 36
        $this->setUseCollection(new UseCollection());
132 36
        $this->setCompositionCollection(new CompositionCollection());
133 36
    }
134
135
    /**
136
     * {@inheritdoc}
137
     */
138 12
    public function getDocBlock()
139
    {
140 12
        return $this->docBlock;
141
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146 36
    public function setDocBlock(DocBlockInterface $docBlock)
147
    {
148 36
        $this->docBlock = $docBlock;
149
150 36
        return $this;
151
    }
152
153
    /**
154
     * @inheritdoc
155
     */
156 2
    public function getFullName()
157
    {
158 2
        return $this->getNamespace()->getPath() . '\\' . $this->getName();
159
    }
160
161
    /**
162
     * @inheritdoc
163
     */
164 11
    public function getName()
165
    {
166 11
        return $this->name;
167
    }
168
169
    /**
170
     * @inheritdoc
171
     */
172 11
    public function setName($name)
173
    {
174 11
        $replaceTo = strpos($name, '_') !== false ? '_' : '';
175 11
        $this->name = str_replace(' ', $replaceTo, ucwords(strtr($name, '_-', '  ')));
176
177 11
        return $this;
178
    }
179
180
    /**
181
     * @inheritdoc
182
     */
183 11
    public function getNamespace()
184
    {
185 11
        return $this->namespace;
186
    }
187
188
    /**
189
     * @inheritdoc
190
     */
191 36
    public function setNamespace(NamespaceInterface $namespace)
192
    {
193 36
        $namespace->setParent($this);
194 36
        $this->namespace = $namespace;
195
196 36
        return $this;
197
    }
198
199
    /**
200
     * @inheritdoc
201
     */
202 10
    public function getConstantCollection()
203
    {
204 10
        return $this->constants;
205
    }
206
207
    /**
208
     * @inheritdoc
209
     */
210 36
    public function setConstantCollection(ConstantCollection $constants)
211
    {
212 36
        $this->constants = $constants;
213
214 36
        return $this;
215
    }
216
217
    /**
218
     * @inheritdoc
219
     */
220 1
    public function addConstant(ConstantInterface $const)
221
    {
222 1
        $const->setParent($this);
223 1
        $this->getConstantCollection()->add($const);
224
225 1
        return $this;
226
    }
227
228
    /**
229
     * @inheritdoc
230
     */
231 11
    public function getPropertyCollection()
232
    {
233 11
        return $this->properties;
234
    }
235
236
    /**
237
     * @inheritdoc
238
     */
239 1
    public function getProperty($propertyName)
240
    {
241 1
        return $this->properties->getByName($propertyName);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->properties...tByName($propertyName); (ClassGeneration\PropertyCollection) is incompatible with the return type declared by the interface ClassGeneration\PhpClassInterface::getProperty of type ClassGeneration\Property.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
242
    }
243
244
    /**
245
     * @inheritdoc
246
     */
247 36
    public function setPropertyCollection(PropertyCollection $properties)
248
    {
249 36
        $this->properties = $properties;
250
251 36
        return $this;
252
    }
253
254
    /**
255
     * @inheritdoc
256
     */
257 6
    public function addProperty(PropertyInterface $property)
258
    {
259 6
        $property->setParent($this);
260 6
        $this->getPropertyCollection()->add($property);
261
262 6
        return $this;
263
    }
264
265
    /**
266
     * @inheritdoc
267
     */
268 13
    public function getMethodCollection()
269
    {
270 13
        return $this->methods;
271
    }
272
273
    /**
274
     * @inheritdoc
275
     */
276 12
    public function addMethod(MethodInterface $method)
277
    {
278 12
        $method->setParent($this);
279 12
        $this->getMethodCollection()->add($method);
280
281 12
        return $this;
282
    }
283
284
    /**
285
     * @inheritdoc
286
     */
287 36
    public function setMethodCollection(MethodCollection $methods)
288
    {
289 36
        $this->methods = $methods;
290
291 36
        return $this;
292
    }
293
294
    /**
295
     * @inheritdoc
296
     */
297 10
    public function getExtends()
298
    {
299 10
        return $this->extends;
300
    }
301
302
    /**
303
     * @inheritdoc
304
     */
305 5
    public function setExtends($extends)
306
    {
307 5
        $this->extends = $extends;
308
309 5
        $this->createMethodsFromAbstractClass($extends);
310
311 5
        return $this;
312
    }
313
314
    /**
315
     * @inheritdoc
316
     */
317 10
    public function getInterfaceCollection()
318
    {
319 10
        return $this->interfaces;
320
    }
321
322
    /**
323
     * @inheritdoc
324
     */
325 4
    public function addInterface($interfaceName)
326
    {
327 4
        $this->interfaces->add($interfaceName);
328 4
        $this->createMethodsFromInterface($interfaceName);
329
330 4
        return $this;
331
    }
332
333
    /**
334
     * @inheritdoc
335
     */
336 36
    public function setInterfaceCollection(InterfaceCollection $interfacesNames)
337
    {
338 36
        $this->interfaces = $interfacesNames;
339
340 36
        return $this;
341
    }
342
343
    /**
344
     * Creates methods from Interface.
345
     *
346
     * @param string $interfaceName
347
     */
348 4
    protected function createMethodsFromInterface($interfaceName)
349
    {
350 4
        if (!interface_exists($interfaceName)) {
351 1
            return;
352
        }
353
354 3
        $refInterface = new \ReflectionClass($interfaceName);
355 3
        $methodsReflected = $refInterface->getMethods();
356 3
        foreach ($methodsReflected as $methodReflected) {
357 3
            if ($this->getMethodCollection()->exists($methodReflected->getName())) {
358 1
                continue;
359
            }
360 3
            $method = Method::createFromReflection($methodReflected);
361 3
            $this->addMethod($method);
362 3
        }
363 3
    }
364
365
366
    /**
367
     * Creates methods from Abstract.
368
     *
369
     * @param string $abstractClass
370
     *
371
     * @return void
372
     */
373 5
    protected function createMethodsFromAbstractClass($abstractClass)
374
    {
375 5
        if (!class_exists($abstractClass)) {
376 1
            return;
377
        }
378
379 4
        $refExtends = new \ReflectionClass($abstractClass);
380 4
        $methodsRef = $refExtends->getMethods();
381 4
        foreach ($methodsRef as $methodRef) {
382 4
            if (!$methodRef->isAbstract() || $this->getMethodCollection()->exists($methodRef->getName())) {
383 4
                continue;
384
            }
385
386 1
            $method = Method::createFromReflection($methodRef);
387 1
            $this->addMethod($method);
388 4
        }
389 4
    }
390
391
    /**
392
     * @inheritdoc
393
     */
394 7
    public function isTrait()
395
    {
396 7
        return $this->isTrait;
397
    }
398
399
    /**
400
     * @inheritdoc
401
     */
402 2
    public function setIsTrait($isTrait = true)
403
    {
404 2
        $this->isTrait = (bool)$isTrait;
405
406 2
        return $this;
407
    }
408
409
    /**
410
     * @inheritdoc
411
     */
412 11
    public function isInterface()
413
    {
414 11
        return $this->isInterface;
415
    }
416
417
    /**
418
     * @inheritdoc
419
     */
420 3
    public function setIsInterface($isInterface = true)
421
    {
422 3
        if ($this->isAbstract()) {
423 1
            throw new \RuntimeException('This method is an abstract and it not be an interface too.');
424
        }
425
426 2
        $this->isInterface = (bool)$isInterface;
427
428 2
        return $this;
429
    }
430
431
    /**
432
     * @inheritdoc
433
     */
434 12
    public function setDescription($description)
435
    {
436 12
        $this->docBlock->setDescription($description);
437
438 12
        return $this;
439
    }
440
441
    /**
442
     * @inheritdoc
443
     */
444 10
    public function getUseCollection()
445
    {
446 10
        return $this->useCollection;
447
    }
448
449
    /**
450
     * @inheritdoc
451
     */
452 1
    public function addUse(UseInterface $use)
453
    {
454 1
        $this->useCollection->add($use);
455
456 1
        return $this;
457
    }
458
459
    /**
460
     * @inheritdoc
461
     */
462 36
    public function setUseCollection(UseCollection $uses)
463
    {
464 36
        $this->useCollection = $uses;
465
466 36
        return $this;
467
    }
468
469
    /**
470
     * Create all getters and setters from Property Collection.
471
     * @return void
472
     */
473 1
    public function generateGettersAndSettersFromProperties()
474
    {
475 1
        $propertyIterator = $this->getPropertyCollection()->getIterator();
476 1
        foreach ($propertyIterator as $property) {
477 1
            $this->getMethodCollection()->add(Method::createGetterFromProperty($property));
478 1
            $this->getMethodCollection()->add(Method::createSetterFromProperty($property));
479 1
        }
480 1
    }
481
482
    /**
483
     * @inheritdoc
484
     */
485 9
    public function toString()
486
    {
487 9
        $extends = '';
488 9
        if ($this->getExtends()) {
489 4
            $extends = ' extends ' . $this->getExtends();
490 4
        }
491
        $string = '<?php' . PHP_EOL
492 9
            . $this->getNamespace()->toString()
493 9
            . $this->getUseCollection()->toString()
494 9
            . $this->getDocBlock()->setTabulation($this->getTabulation())->toString()
495 9
            . $this->toStringType()
496 9
            . $this->getName()
497 9
            . $extends
498 9
            . $this->getInterfaceCollection()->toString()
499 9
            . PHP_EOL
500 9
            . '{'
501 9
            . PHP_EOL
502 9
            . $this->getCompositionCollection()->toString()
503 9
            . $this->getConstantCollection()->toString()
504 9
            . $this->getPropertyCollection()->toString()
505 9
            . $this->getMethodCollection()->toString()
506 9
            . '}' . PHP_EOL;
507
508 9
        return $string;
509
    }
510
511
    /**
512
     * @inheritdoc
513
     */
514 2
    public function evaluate()
515
    {
516 2
        $classString = substr($this->toString(), 7);
517 2
        eval($classString);
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
518 2
    }
519
520
    /**
521
     * {@inheritdoc}
522
     */
523 8
    public function isFinal()
524
    {
525 8
        return $this->isFinal;
526
    }
527
528
    /**
529
     * {@inheritdoc}
530
     * @return PhpClass
531
     */
532 2
    public function setIsFinal($isFinal = true)
533
    {
534 2
        $this->isFinal = (bool)$isFinal;
535
536 2
        return $this;
537
    }
538
539
    /**
540
     * {@inheritdoc}
541
     */
542 11
    public function isAbstract()
543
    {
544 11
        return $this->isAbstract;
545
    }
546
547
    /**
548
     * {@inheritdoc}
549
     */
550 3
    public function setIsAbstract($isAbstract = true)
551
    {
552 3
        if ($this->isInterface()) {
553 1
            throw new \RuntimeException('This class is an interface and it not be an abstract too.');
554
        }
555
556 2
        $this->isAbstract = (bool)$isAbstract;
557
558 2
        return $this;
559
    }
560
561
    /**
562
     * Get string based on type set.
563
     * @return string
564
     */
565 9
    protected function toStringType()
566
    {
567 9
        $type = 'class ';
568
569 9
        switch (true) {
570 9
            case $this->isInterface():
571 1
                $type = 'interface ';
572 1
                break;
573 8
            case $this->isAbstract():
574 1
                $type = 'abstract class ';
575 1
                break;
576 7
            case $this->isFinal():
577 1
                $type = 'final class ';
578 1
                break;
579 6
            case $this->isTrait():
580 1
                $type = 'trait ';
581 1
        }
582
583 9
        return $type;
584
    }
585
586
    /**
587
     * @inheritdoc
588
     */
589 3
    public function addComposition($traitName)
590
    {
591 3
        $this->getCompositionCollection()->add($traitName);
592
593 3
        return $this;
594
    }
595
596
    /**
597
     * @inheritdoc
598
     */
599 1
    public function addCompositionMethod(CompositionMethodInterface $compositionMethod)
600
    {
601 1
        $compositionMethod->setParent($this);
602 1
        $this->getCompositionCollection()->addMethod($compositionMethod);
603 1
        return $this;
604
    }
605
606
    /**
607
     * @inheritdoc
608
     */
609 36
    public function setCompositionCollection(CompositionCollection $traits)
610
    {
611 36
        $this->compositionCollection = $traits;
612 36
        return $this;
613
    }
614
615
    /**
616
     * @inheritdoc
617
     */
618 10
    public function getCompositionCollection()
619
    {
620 10
        return $this->compositionCollection;
621
    }
622
}
623