Completed
Push — master ( 6c5557...d84e1e )
by Alexander
03:46
created

ReflectionClass   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 103
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 6

Test Coverage

Coverage 94%

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 19
c 2
b 0
f 1
lcom 0
cbo 6
dl 0
loc 103
ccs 47
cts 50
cp 0.94
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 3
C collectInterfacesFromClassNode() 0 22 7
C collectTraitsFromClassNode() 0 22 7
A __debugInfo() 0 6 1
A __initialize() 0 4 1
1
<?php
2
/**
3
 * Parser Reflection API
4
 *
5
 * @copyright Copyright 2015, Lisachenko Alexander <[email protected]>
6
 *
7
 * This source file is subject to the license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
11
namespace Go\ParserReflection;
12
13
use Go\ParserReflection\Traits\InternalPropertiesEmulationTrait;
14
use Go\ParserReflection\Traits\ReflectionClassLikeTrait;
15
use PhpParser\Node\Name;
16
use PhpParser\Node\Name\FullyQualified;
17
use PhpParser\Node\Stmt\ClassLike;
18
use PhpParser\Node\Stmt\Interface_;
19
use PhpParser\Node\Stmt\TraitUse;
20
use ReflectionClass as InternalReflectionClass;
21
22
/**
23
 * AST-based reflection class
24
 */
25
class ReflectionClass extends InternalReflectionClass
26
{
27
    use ReflectionClassLikeTrait, InternalPropertiesEmulationTrait;
28
29
    /**
30
     * Initializes reflection instance
31
     *
32
     * @param string|object $argument Class name or instance of object
33
     * @param ClassLike $classLikeNode AST node for class
34
     */
35 17
    public function __construct($argument, ClassLike $classLikeNode = null)
36
    {
37 17
        $fullClassName       = is_object($argument) ? get_class($argument) : $argument;
38 17
        $namespaceParts      = explode('\\', $fullClassName);
39 17
        $this->className     = array_pop($namespaceParts);
40
        // Let's unset original read-only property to have a control over it via __get
41 17
        unset($this->name);
42
43 17
        $this->namespaceName = join('\\', $namespaceParts);
44
45 17
        $this->classLikeNode = $classLikeNode ?: ReflectionEngine::parseClass($fullClassName);
46 17
    }
47
48
    /**
49
     * Parses interfaces from the concrete class node
50
     *
51
     * @param ClassLike $classLikeNode Class-like node
52
     *
53
     * @return array|\ReflectionClass[] List of reflections of interfaces
54
     */
55 9
    public static function collectInterfacesFromClassNode(ClassLike $classLikeNode)
56
    {
57 9
        $interfaces = [];
58
59 9
        $isInterface    = $classLikeNode instanceof Interface_;
60 9
        $interfaceField = $isInterface ? 'extends' : 'implements';
61 9
        $hasInterfaces  = in_array($interfaceField, $classLikeNode->getSubNodeNames());
62 9
        $implementsList = $hasInterfaces ? $classLikeNode->$interfaceField : array();
63 9
        if ($implementsList) {
64 1
            foreach ($implementsList as $implementNode) {
65 1
                if ($implementNode instanceof FullyQualified) {
66 1
                    $implementName  = $implementNode->toString();
67 1
                    $interface      = interface_exists($implementName, false)
68 1
                        ? new parent($implementName)
69 1
                        : new static($implementName);
70 1
                    $interfaces[$implementName] = $interface;
71 1
                }
72 1
            }
73 1
        }
74
75 9
        return $interfaces;
76
    }
77
78
    /**
79
     * Parses traits from the concrete class node
80
     *
81
     * @param ClassLike $classLikeNode Class-like node
82
     *
83
     * @return array|\ReflectionClass[] List of reflections of traits
84
     */
85 2
    public static function collectTraitsFromClassNode(ClassLike $classLikeNode)
86
    {
87 2
        $traits = [];
88
89 2
        if (!empty($classLikeNode->stmts)) {
90 2
            foreach ($classLikeNode->stmts as $classLevelNode) {
91 2
                if ($classLevelNode instanceof TraitUse) {
92 1
                    foreach ($classLevelNode->traits as $classTraitName) {
93 1
                        if ($classTraitName instanceof FullyQualified) {
94 1
                            $traitName          = $classTraitName->toString();
95 1
                            $trait              = trait_exists($traitName, false)
96 1
                                ? new parent($traitName)
97 1
                                : new static($traitName);
98 1
                            $traits[$traitName] = $trait;
99 1
                        }
100 1
                    }
101 1
                }
102 2
            }
103 2
        }
104
105 2
        return $traits;
106
    }
107
108
    /**
109
     * Emulating original behaviour of reflection
110
     */
111
    public function __debugInfo()
112
    {
113
        return array(
114
            'name' => $this->getName()
115
        );
116
    }
117
118
    /**
119
     * Implementation of internal reflection initialization
120
     *
121
     * @return void
122
     */
123 4
    protected function __initialize()
124
    {
125 4
        parent::__construct($this->getName());
126 4
    }
127
}
128