Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.16% covered (success)
95.16%
59 / 62
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
ClassReflection
95.16% covered (success)
95.16%
59 / 62
0.00% covered (danger)
0.00%
0 / 1
31
0.00% covered (danger)
0.00%
0 / 1
 parse
95.16% covered (success)
95.16%
59 / 62
0.00% covered (danger)
0.00%
0 / 1
31
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Code\Reflection;
15
16use Pop\Code\Generator;
17
18/**
19 * Class reflection code class
20 *
21 * @category   Pop
22 * @package    Pop\Code
23 * @author     Nick Sagona, III <dev@nolainteractive.com>
24 * @copyright  Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com)
25 * @license    http://www.popphp.org/license     New BSD License
26 * @version    4.1.0
27 */
28class ClassReflection extends AbstractReflection
29{
30
31    /**
32     * Method to parse a class
33     *
34     * @param  mixed  $code
35     * @param  string $name
36     * @throws Exception
37     * @return Generator\ClassGenerator
38     */
39    public static function parse($code, $name = null)
40    {
41        $reflection     = new \ReflectionClass($code);
42        $reflectionName = $reflection->getShortName();
43        $reflectionFile = $reflection->getFileName();
44        $fileContents   = null;
45
46        if (!empty($reflectionFile) && file_exists($reflectionFile)) {
47            $fileContents = file_get_contents($reflectionFile);
48        }
49
50        if ((null === $name) && !empty($reflectionName)) {
51            $name = $reflectionName;
52        }
53
54        if (($reflection->isInterface()) || ($reflection->isTrait())) {
55            throw new Exception('Error: The code must be a class, not an interface or trait.');
56        }
57
58        $class = new Generator\ClassGenerator($name);
59
60        // Detect and set namespace
61        if (($reflection->inNamespace()) && (null !== $fileContents)) {
62            $class->setNamespace(NamespaceReflection::parse($fileContents, $reflection->getNamespaceName()));
63        }
64
65        // Detect and set the class doc block
66        $classDocBlock = $reflection->getDocComment();
67        if (!empty($classDocBlock) && (strpos($classDocBlock, '/*') !== false)) {
68            $class->setDocblock(DocblockReflection::parse($classDocBlock));
69        }
70
71        if ($reflection->isAbstract()) {
72            $class->setAsAbstract(true);
73        } else if ($reflection->isFinal()) {
74            $class->setAsFinal(true);
75        }
76
77        // Detect parent class
78        $parent = $reflection->getParentClass();
79        if ($parent !== false) {
80            if ($parent->inNamespace()) {
81                if (!$class->hasNamespace()) {
82                    $class->setNamespace(new Generator\NamespaceGenerator());
83                }
84                $class->getNamespace()->addUse($parent->getNamespaceName() . '\\' . $parent->getShortName());
85            }
86            $class->setParent($parent->getShortName());
87        }
88
89        // Detect implemented interfaces
90        $interfaces = $reflection->getInterfaces();
91        if ($interfaces !== false) {
92            $interfacesAry = [];
93            foreach ($interfaces as $interface) {
94                if ($interface->inNamespace()) {
95                    if (!$class->hasNamespace()) {
96                        $class->setNamespace(new Generator\NamespaceGenerator());
97                    }
98                    $class->getNamespace()->addUse($interface->getNamespaceName() . '\\' . $interface->getShortName());
99                }
100                $interfacesAry[] = $interface->getShortName();
101            }
102            $class->addInterfaces($interfacesAry);
103        }
104
105        // Detect used traits
106        if (null !== $fileContents) {
107            $uses = [];
108            preg_match_all('/[ ]+use(.*);$/m', $fileContents, $uses);
109
110            if (isset($uses[1])) {
111                foreach ($uses[1] as $u) {
112                    $useAry = array_map('trim', explode(',', trim($u)));
113                    foreach ($useAry as $useValue) {
114                        if (strpos($useValue, ' as ') !== false) {
115                            [$use, $as] = explode(' as ', $useValue);
116                        } else {
117                            $use = $useValue;
118                            $as  = null;
119                        }
120                        $class->addUse($use, $as);
121                    }
122                }
123            }
124        }
125
126        // Detect constants
127        $constants = $reflection->getConstants();
128        if (count($constants) > 0) {
129            foreach ($constants as $key => $value) {
130                $class->addConstant(new Generator\ConstantGenerator($key, gettype($value), $value));
131            }
132        }
133
134        // Detect properties
135        $properties = $reflection->getDefaultProperties();
136        if (count($properties) > 0) {
137            foreach ($properties as $name => $value) {
138                $class->addProperty(PropertyReflection::parse($reflection->getProperty($name), $name, $value));
139            }
140        }
141
142        // Detect methods
143        $methods = $reflection->getMethods();
144        if (count($methods) > 0) {
145            foreach ($methods as $method) {
146                $class->addMethod(MethodReflection::parse($method, $method->name));
147            }
148        }
149
150        return $class;
151    }
152
153}