Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
98.04% |
50 / 51 |
|
0.00% |
0 / 1 |
CRAP | |
0.00% |
0 / 1 |
FunctionReflection | |
98.04% |
50 / 51 |
|
0.00% |
0 / 1 |
26 | |
0.00% |
0 / 1 |
parse | |
98.04% |
50 / 51 |
|
0.00% |
0 / 1 |
26 |
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-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
8 | * @license http://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Code\Reflection; |
15 | |
16 | use Pop\Code\Generator\FunctionGenerator; |
17 | use ReflectionException; |
18 | |
19 | /** |
20 | * Function reflection code class |
21 | * |
22 | * @category Pop |
23 | * @package Pop\Code |
24 | * @author Nick Sagona, III <dev@nolainteractive.com> |
25 | * @copyright Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
26 | * @license http://www.popphp.org/license New BSD License |
27 | * @version 5.0.0 |
28 | */ |
29 | class FunctionReflection extends AbstractReflection |
30 | { |
31 | |
32 | /** |
33 | * Method to parse a function or closure |
34 | * |
35 | * @param mixed $code |
36 | * @param ?string $name |
37 | * @throws ReflectionException |
38 | * @return FunctionGenerator |
39 | */ |
40 | public static function parse(mixed $code, ?string $name = null): FunctionGenerator |
41 | { |
42 | $reflection = new \ReflectionFunction($code); |
43 | $reflectionName = $reflection->getName(); |
44 | $reflectionParams = $reflection->getParameters(); |
45 | $isClosure = ($reflectionName == '{closure}'); |
46 | |
47 | if (($name === null) && !($isClosure)) { |
48 | $name = $reflectionName; |
49 | } |
50 | |
51 | $function = new FunctionGenerator($name, $isClosure); |
52 | |
53 | foreach ($reflectionParams as $key => $reflectionParam) { |
54 | $paramName = $reflectionParam->getName(); |
55 | $paramType = $reflectionParam->getType(); |
56 | $paramType = (!empty($paramType) && ($paramType instanceof \ReflectionType)) ? $paramType->getName() : null; |
57 | |
58 | try { |
59 | $paramValue = $reflectionParam->getDefaultValue(); |
60 | } catch (\ReflectionException $e) { |
61 | $paramValue = null; |
62 | } |
63 | |
64 | $function->addArgument($paramName, $paramValue, $paramType); |
65 | } |
66 | |
67 | // Parse the body if available |
68 | $file = $reflection->getFileName(); |
69 | |
70 | if (!empty($file) && file_exists($file)) { |
71 | $lines = file($file); |
72 | $startLine = $reflection->getStartLine() - 1; |
73 | $endLine = $reflection->getEndLine() - 1; |
74 | $length = $endLine - $startLine; |
75 | $body = null; |
76 | |
77 | if (($length > 0) && isset($lines[$startLine]) && isset($lines[$endLine])) { |
78 | $lines = array_slice($lines, ($startLine + 1), ($length - 1)); |
79 | if (isset($lines[0]) && (str_starts_with($lines[0], ' '))) { |
80 | $spaces = strlen($lines[0]) - strlen(ltrim($lines[0])); |
81 | if ($spaces > 0) { |
82 | $lines = array_map(function($value) use ($spaces) { |
83 | if (substr($value, 0, $spaces) == str_repeat(' ', $spaces)) { |
84 | $value = substr($value, $spaces); |
85 | } |
86 | return $value; |
87 | }, $lines); |
88 | } |
89 | } |
90 | $body = implode('', $lines); |
91 | } |
92 | |
93 | if (!empty($body)) { |
94 | $function->setBody($body, false); |
95 | } |
96 | } |
97 | |
98 | // Get return type(s) |
99 | if ($reflection->hasReturnType()) { |
100 | $namedTypes = []; |
101 | $returnTypes = $reflection->getReturnType(); |
102 | if ($returnTypes instanceof \ReflectionUnionType) { |
103 | $types = $returnTypes->getTypes(); |
104 | foreach ($types as $type) { |
105 | $namedTypes[] = $type->getName(); |
106 | } |
107 | if (($returnTypes->allowsNull()) && !in_array('null', $namedTypes)) { |
108 | $namedTypes[] = 'null'; |
109 | } |
110 | } else if ($returnTypes instanceof \ReflectionNamedType) { |
111 | $namedTypes[] = $returnTypes->getName(); |
112 | if (($returnTypes->allowsNull()) && !in_array('null', $namedTypes)) { |
113 | $namedTypes[] = 'null'; |
114 | } |
115 | } |
116 | if (!empty($namedTypes)) { |
117 | $function->addReturnTypes($namedTypes); |
118 | } |
119 | } |
120 | |
121 | return $function; |
122 | } |
123 | |
124 | } |