Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
81.08% covered (success)
81.08%
30 / 37
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
TraitReflection
81.08% covered (success)
81.08%
30 / 37
0.00% covered (danger)
0.00%
0 / 1
22.71
0.00% covered (danger)
0.00%
0 / 1
 parse
81.08% covered (success)
81.08%
30 / 37
0.00% covered (danger)
0.00%
0 / 1
22.71
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <dev@noladev.com>
8 * @copyright  Copyright (c) 2009-2027 NOLA Interactive, LLC.
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Code\Reflection;
16
17use Pop\Code\Generator;
18use Pop\Code\Reflection\Support\UseStatementParser;
19use Pop\Code\Reflection\Support\AttributeCollector;
20use Pop\Code\Reflection\Support\NamespaceImportResolver;
21use ReflectionException;
22
23/**
24 * Property reflection code class
25 *
26 * @category   Pop
27 * @package    Pop\Code
28 * @author     Nick Sagona, III <dev@noladev.com>
29 * @copyright  Copyright (c) 2009-2027 NOLA Interactive, LLC.
30 * @license    https://www.popphp.org/license     New BSD License
31 * @version    6.0.0
32 */
33class TraitReflection extends AbstractReflection
34{
35
36    /**
37     * Method to parse a trait
38     *
39     * @param  mixed   $code
40     * @param  ?string $name
41     * @throws Exception|ReflectionException
42     * @return Generator\TraitGenerator
43     */
44    public static function parse(mixed $code, ?string $name = null): Generator\TraitGenerator
45    {
46        $reflection     = new \ReflectionClass($code);
47        $reflectionName = $reflection->getShortName();
48        $reflectionFile = $reflection->getFileName();
49        $fileContents   = null;
50
51        if (!empty($reflectionFile) && file_exists($reflectionFile)) {
52            $fileContents = file_get_contents($reflectionFile);
53        }
54
55        if (($name === null) && !empty($reflectionName)) {
56            $name = $reflectionName;
57        }
58
59        if (!$reflection->isTrait()) {
60            throw new Exception('Error: The code is not a trait.');
61        }
62
63        $trait = new Generator\TraitGenerator($name);
64
65        // Detect and set namespace
66        if (($reflection->inNamespace()) && ($fileContents !== null)) {
67            $trait->setNamespace(NamespaceReflection::parse($fileContents, $reflection->getNamespaceName()));
68        }
69
70        // Detect attributes
71        $importResolver = new NamespaceImportResolver();
72        foreach ($reflection->getAttributes() as $reflectionAttribute) {
73            [$attributeReference, $needsImport] = $importResolver->resolve($reflectionAttribute->getName(), $reflection->getNamespaceName());
74            if ($needsImport) {
75                if (!$trait->hasNamespace()) {
76                    $trait->setNamespace(new Generator\NamespaceGenerator());
77                }
78                $trait->getNamespace()->addUse($reflectionAttribute->getName());
79            }
80            $trait->addAttribute(AttributeCollector::build($reflectionAttribute, $attributeReference));
81        }
82
83        // Detect and set the class doc block
84        $traitDocBlock = $reflection->getDocComment();
85        if (!empty($traitDocBlock) && (str_contains($traitDocBlock, '/*'))) {
86            $trait->setDocblock(DocblockReflection::parse($traitDocBlock));
87        }
88
89        // Detect used traits
90        if ($fileContents !== null) {
91            foreach (UseStatementParser::parse($fileContents) as $use => $as) {
92                $trait->addUse($use, $as);
93            }
94        }
95
96        // Detect properties
97        foreach ($reflection->getProperties() as $property) {
98            if ($property->isPromoted()) {
99                continue;
100            }
101            $value = $property->hasDefaultValue() ? $property->getDefaultValue() : null;
102            $trait->addProperty(PropertyReflection::parse($property, $property->getName(), $value));
103        }
104
105        // Detect methods
106        $methods = $reflection->getMethods();
107        if (count($methods) > 0) {
108            foreach ($methods as $method) {
109                $trait->addMethod(MethodReflection::parse($method, $method->name));
110            }
111        }
112
113        return $trait;
114    }
115
116}