Completed
Push — master ( 555240...fa2155 )
by Alexander
115:41 queued 90:43
created

ReflectionClass::__debugInfo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 1
cts 1
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
/**
5
 * Parser Reflection API
6
 *
7
 * @copyright Copyright 2015, Lisachenko Alexander <[email protected]>
8
 *
9
 * This source file is subject to the license that is bundled
10
 * with this source code in the file LICENSE.
11
 */
12
13
namespace Go\ParserReflection;
14
15
use Go\ParserReflection\Traits\InternalPropertiesEmulationTrait;
16
use Go\ParserReflection\Traits\ReflectionClassLikeTrait;
17
use PhpParser\Node\Name\FullyQualified;
18
use PhpParser\Node\Stmt\ClassLike;
19
use PhpParser\Node\Stmt\Interface_;
20
use PhpParser\Node\Stmt\TraitUse;
21
use ReflectionClass as InternalReflectionClass;
22
23
/**
24
 * AST-based reflection class
25
 */
26
class ReflectionClass extends InternalReflectionClass
27
{
28
    use InternalPropertiesEmulationTrait;
29
    use ReflectionClassLikeTrait;
30
31
    /**
32
     * Initializes reflection instance
33
     *
34 3007
     * @param string|object $argument      Class name or instance of object
35
     * @param ?ClassLike    $classLikeNode AST node for class
0 ignored issues
show
Documentation introduced by
The doc-type ?ClassLike could not be parsed: Unknown type name "?ClassLike" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
36 3007
     */
37 3007
    public function __construct($argument, ClassLike $classLikeNode = null)
38 3007
    {
39
        $fullClassName   = is_object($argument) ? get_class($argument) : ltrim($argument, '\\');
40 3007
        $namespaceParts  = explode('\\', $fullClassName);
41
        $this->className = array_pop($namespaceParts);
42 3007
        // Let's unset original read-only property to have a control over it via __get
43
        unset($this->name);
44 3007
45 3007
        $this->namespaceName = implode('\\', $namespaceParts);
46
47
        $this->classLikeNode = $classLikeNode ?: ReflectionEngine::parseClass($fullClassName);
48
    }
49
50
    /**
51
     * Parses interfaces from the concrete class node
52
     *
53
     * @return InternalReflectionClass[] List of reflections of interfaces
54 172
     */
55
    public static function collectInterfacesFromClassNode(ClassLike $classLikeNode): array
56 172
    {
57
        $interfaces = [];
58 172
59 172
        $isInterface    = $classLikeNode instanceof Interface_;
60 172
        $interfaceField = $isInterface ? 'extends' : 'implements';
61 172
        $hasInterfaces  = in_array($interfaceField, $classLikeNode->getSubNodeNames(), true);
62 172
        $implementsList = $hasInterfaces ? $classLikeNode->$interfaceField : [];
63 7
        if ($implementsList) {
64 7
            foreach ($implementsList as $implementNode) {
65 7
                if ($implementNode instanceof FullyQualified) {
66 7
                    $implementName = $implementNode->toString();
67 7
                    $interface     = interface_exists($implementName, false)
68 7
                        ? new parent($implementName)
69 7
                        : new static($implementName);
70
71
                    $interfaces[$implementName] = $interface;
72
                }
73
            }
74 172
        }
75
76
        return $interfaces;
77
    }
78
79
    /**
80
     * Parses traits from the concrete class node
81
     *
82
     * @param array $traitAdaptations List of method adaptations
83
     *
84
     * @return InternalReflectionClass[] List of reflections of traits
85 94
     */
86
    public static function collectTraitsFromClassNode(ClassLike $classLikeNode, array &$traitAdaptations): array
87 94
    {
88
        $traits = [];
89 94
90 89
        if (!empty($classLikeNode->stmts)) {
91 89
            foreach ($classLikeNode->stmts as $classLevelNode) {
92 5
                if ($classLevelNode instanceof TraitUse) {
93 5
                    foreach ($classLevelNode->traits as $classTraitName) {
94 5
                        if ($classTraitName instanceof FullyQualified) {
95 5
                            $traitName          = $classTraitName->toString();
96 5
                            $trait              = trait_exists($traitName, false)
97 5
                                ? new parent($traitName)
98 5
                                : new static($traitName);
99
                            $traits[$traitName] = $trait;
100
                        }
101 5
                    }
102
                    $traitAdaptations = $classLevelNode->adaptations;
103
                }
104
            }
105
        }
106 94
107
        return $traits;
108
    }
109
110
    /**
111
     * Emulating original behaviour of reflection
112 50
     */
113
    public function __debugInfo(): array
114
    {
115 50
        return [
116
            'name' => $this->getName()
117
        ];
118
    }
119
120
    /**
121
     * Returns an AST-node for class
122
     */
123
    public function getNode(): ?ClassLike
124
    {
125
        return $this->classLikeNode;
126
    }
127
128
    /**
129
     * Implementation of internal reflection initialization
130
     *
131
     * @return void
132
     */
133
    protected function __initialize(): void
134 4
    {
135
        parent::__construct($this->getName());
136 4
    }
137 4
138
    /**
139
     * Create a ReflectionClass for a given class name.
140
     *
141
     * @param string $className
142
     *     The name of the class to create a reflection for.
143
     *
144
     * @return InternalReflectionClass The appropriate reflection object.
145
     */
146
    protected function createReflectionForClass(string $className)
147
    {
148 24
        return class_exists($className, false) ? new parent($className) : new static($className);
149
    }
150
}
151