ReflectionClass   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 129
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 95.65%

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 5
dl 0
loc 129
ccs 44
cts 46
cp 0.9565
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 3
B collectInterfacesFromClassNode() 0 22 7
B collectTraitsFromClassNode() 0 23 7
A ___debugInfo() 0 6 1
A getNode() 0 4 1
A __initialize() 0 4 1
A createReflectionForClass() 0 4 2
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\FullyQualified;
16
use PhpParser\Node\Stmt\ClassLike;
17
use PhpParser\Node\Stmt\Interface_;
18
use PhpParser\Node\Stmt\TraitUse;
19
use ReflectionClass as InternalReflectionClass;
20
21
/**
22
 * AST-based reflection class
23
 */
24
class ReflectionClass extends InternalReflectionClass
25
{
26
    use ReflectionClassLikeTrait, InternalPropertiesEmulationTrait;
27
28
    /**
29
     * Initializes reflection instance
30
     *
31
     * @param string|object $argument Class name or instance of object
32
     * @param ClassLike $classLikeNode AST node for class
33
     */
34 3004
    public function __construct($argument, ClassLike $classLikeNode = null)
35
    {
36 3004
        $fullClassName       = is_object($argument) ? get_class($argument) : ltrim($argument, '\\');
37 3004
        $namespaceParts      = explode('\\', $fullClassName);
38 3004
        $this->className     = array_pop($namespaceParts);
39
        // Let's unset original read-only property to have a control over it via __get
40 3004
        unset($this->name);
41
42 3004
        $this->namespaceName = join('\\', $namespaceParts);
43
44 3004
        $this->classLikeNode = $classLikeNode ?: ReflectionEngine::parseClass($fullClassName);
45 3004
    }
46
47
    /**
48
     * Parses interfaces from the concrete class node
49
     *
50
     * @param ClassLike $classLikeNode Class-like node
51
     *
52
     * @return array|\ReflectionClass[] List of reflections of interfaces
53
     */
54 168
    public static function collectInterfacesFromClassNode(ClassLike $classLikeNode)
55
    {
56 168
        $interfaces = [];
57
58 168
        $isInterface    = $classLikeNode instanceof Interface_;
59 168
        $interfaceField = $isInterface ? 'extends' : 'implements';
60 168
        $hasInterfaces  = in_array($interfaceField, $classLikeNode->getSubNodeNames());
61 168
        $implementsList = $hasInterfaces ? $classLikeNode->$interfaceField : array();
62 168
        if ($implementsList) {
63 7
            foreach ($implementsList as $implementNode) {
64 7
                if ($implementNode instanceof FullyQualified) {
65 7
                    $implementName  = $implementNode->toString();
66 7
                    $interface      = interface_exists($implementName, false)
67 7
                        ? new parent($implementName)
68 7
                        : new static($implementName);
69 7
                    $interfaces[$implementName] = $interface;
70
                }
71
            }
72
        }
73
74 168
        return $interfaces;
75
    }
76
77
    /**
78
     * Parses traits from the concrete class node
79
     *
80
     * @param ClassLike $classLikeNode Class-like node
81
     * @param array     $traitAdaptations List of method adaptations
82
     *
83
     * @return array|\ReflectionClass[] List of reflections of traits
84
     */
85 90
    public static function collectTraitsFromClassNode(ClassLike $classLikeNode, array &$traitAdaptations)
86
    {
87 90
        $traits = [];
88
89 90
        if (!empty($classLikeNode->stmts)) {
90 85
            foreach ($classLikeNode->stmts as $classLevelNode) {
91 85
                if ($classLevelNode instanceof TraitUse) {
92 5
                    foreach ($classLevelNode->traits as $classTraitName) {
93 5
                        if ($classTraitName instanceof FullyQualified) {
94 5
                            $traitName          = $classTraitName->toString();
95 5
                            $trait              = trait_exists($traitName, false)
96 5
                                ? new parent($traitName)
97 5
                                : new static($traitName);
98 5
                            $traits[$traitName] = $trait;
99
                        }
100
                    }
101 85
                    $traitAdaptations = $classLevelNode->adaptations;
102
                }
103
            }
104
        }
105
106 90
        return $traits;
107
    }
108
109
    /**
110
     * Emulating original behaviour of reflection
111
     */
112 53
    public function ___debugInfo()
113
    {
114
        return array(
115 53
            'name' => $this->getName()
116
        );
117
    }
118
119
    /**
120
     * Returns an AST-node for class
121
     *
122
     * @return ClassLike
123
     */
124
    public function getNode()
125
    {
126
        return $this->classLikeNode;
127
    }
128
129
    /**
130
     * Implementation of internal reflection initialization
131
     *
132
     * @return void
133
     */
134 4
    protected function __initialize()
135
    {
136 4
        parent::__construct($this->getName());
137 4
    }
138
139
    /**
140
     * Create a ReflectionClass for a given class name.
141
     *
142
     * @param string $className
143
     *     The name of the class to create a reflection for.
144
     *
145
     * @return ReflectionClass
146
     *     The apropriate reflection object.
147
     */
148 24
    protected function createReflectionForClass($className)
149
    {
150 24
        return class_exists($className, false) ? new parent($className) : new static($className);
151
    }
152
}
153