Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
FunctionReflection
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
1 / 1
17
100.00% covered (success)
100.00%
1 / 1
 parse
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
1 / 1
17
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\FunctionGenerator;
17
18/**
19 * Function 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 FunctionReflection extends AbstractReflection
29{
30
31    /**
32     * Method to parse a function or closure
33     *
34     * @param  mixed  $code
35     * @param  string $name
36     * @throws \ReflectionException
37     * @return FunctionGenerator
38     */
39    public static function parse($code, $name = null)
40    {
41        $reflection       = new \ReflectionFunction($code);
42        $reflectionName   = $reflection->getName();
43        $reflectionParams = $reflection->getParameters();
44        $isClosure        = ($reflectionName == '{closure}');
45
46        if ((null === $name) && !($isClosure)) {
47            $name = $reflectionName;
48        }
49
50        $function = new FunctionGenerator($name, $isClosure);
51
52        foreach ($reflectionParams as $key => $reflectionParam) {
53            $paramName  = $reflectionParam->getName();
54            $paramType  = $reflectionParam->getType();
55            $paramType  = (!empty($paramType) && ($paramType instanceof \ReflectionType)) ? $paramType->getName() : null;
56
57            try {
58                $paramValue = $reflectionParam->getDefaultValue();
59            } catch (\ReflectionException $e) {
60                $paramValue = null;
61            }
62
63            $function->addArgument($paramName, $paramValue, $paramType);
64        }
65
66        // Parse the body if available
67        $file = $reflection->getFileName();
68
69        if (!empty($file) && file_exists($file)) {
70            $lines     = file($file);
71            $startLine = $reflection->getStartLine() - 1;
72            $endLine   = $reflection->getEndLine() - 1;
73            $length    = $endLine - $startLine;
74            $body      = null;
75
76            if (($length > 0) && isset($lines[$startLine]) && isset($lines[$endLine])) {
77                $lines = array_slice($lines, ($startLine + 1), ($length - 1));
78                if (isset($lines[0]) && (substr($lines[0], 0, 1) == ' ')) {
79                    $spaces = strlen($lines[0]) - strlen(ltrim($lines[0]));
80                    if ($spaces > 0) {
81                        $lines = array_map(function($value) use ($spaces) {
82                            if (substr($value, 0, $spaces) == str_repeat(' ', $spaces)) {
83                                $value = substr($value, $spaces);
84                            }
85                            return $value;
86                        }, $lines);
87                    }
88                }
89                $body = implode('', $lines);
90            }
91
92            if (!empty($body)) {
93                $function->setBody($body, false);
94            }
95        }
96
97        return $function;
98    }
99
100}