Completed
Pull Request — master (#25)
by Alexander
02:46
created

ReflectionClass   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 6

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 2
Metric Value
wmc 19
c 3
b 0
f 2
lcom 0
cbo 6
dl 0
loc 105
ccs 42
cts 42
cp 1
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 3
C collectInterfacesFromClassNode() 0 22 7
C collectTraitsFromClassNode() 0 23 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 108
    public function __construct($argument, ClassLike $classLikeNode = null)
36
    {
37 108
        $fullClassName       = is_object($argument) ? get_class($argument) : $argument;
38 108
        $namespaceParts      = explode('\\', $fullClassName);
39 108
        $this->className     = array_pop($namespaceParts);
40
        // Let's unset original read-only property to have a control over it via __get
41 108
        unset($this->name);
42
43 108
        $this->namespaceName = join('\\', $namespaceParts);
44
45 108
        $this->classLikeNode = $classLikeNode ?: ReflectionEngine::parseClass($fullClassName);
46 108
    }
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 96
    public static function collectInterfacesFromClassNode(ClassLike $classLikeNode)
56
    {
57 96
        $interfaces = [];
58
59 96
        $isInterface    = $classLikeNode instanceof Interface_;
60 96
        $interfaceField = $isInterface ? 'extends' : 'implements';
61 96
        $hasInterfaces  = in_array($interfaceField, $classLikeNode->getSubNodeNames());
62 96
        $implementsList = $hasInterfaces ? $classLikeNode->$interfaceField : array();
63 96
        if ($implementsList) {
64 8
            foreach ($implementsList as $implementNode) {
65 8
                if ($implementNode instanceof FullyQualified) {
66 8
                    $implementName  = $implementNode->toString();
67 8
                    $interface      = interface_exists($implementName, false)
68 8
                        ? new parent($implementName)
69 8
                        : new static($implementName);
70 8
                    $interfaces[$implementName] = $interface;
71
                }
72
            }
73
        }
74
75 96
        return $interfaces;
76
    }
77
78
    /**
79
     * Parses traits from the concrete class node
80
     *
81
     * @param ClassLike $classLikeNode Class-like node
82
     * @param array     $traitAdaptations List of method adaptations
83
     *
84
     * @return array|\ReflectionClass[] List of reflections of traits
85
     */
86 96
    public static function collectTraitsFromClassNode(ClassLike $classLikeNode, array &$traitAdaptations)
87
    {
88 96
        $traits = [];
89
90 96
        if (!empty($classLikeNode->stmts)) {
91 80
            foreach ($classLikeNode->stmts as $classLevelNode) {
92 80
                if ($classLevelNode instanceof TraitUse) {
93 14
                    foreach ($classLevelNode->traits as $classTraitName) {
94 14
                        if ($classTraitName instanceof FullyQualified) {
95 14
                            $traitName          = $classTraitName->toString();
96 14
                            $trait              = trait_exists($traitName, false)
97 14
                                ? new parent($traitName)
98 14
                                : new static($traitName);
99 14
                            $traits[$traitName] = $trait;
100
                        }
101
                    }
102 80
                    $traitAdaptations = $classLevelNode->adaptations;
103
                }
104
            }
105
        }
106
107 96
        return $traits;
108
    }
109
110
    /**
111
     * Emulating original behaviour of reflection
112
     */
113 31
    public function ___debugInfo()
114
    {
115
        return array(
116 31
            'name' => $this->getName()
117
        );
118
    }
119
120
    /**
121
     * Implementation of internal reflection initialization
122
     *
123
     * @return void
124
     */
125 4
    protected function __initialize()
126
    {
127 4
        parent::__construct($this->getName());
128 4
    }
129
}
130