Completed
Push — master ( b0bc39...c39dfb )
by Emily
10s
created

ReflectionMethodFactory::addParamAnnotation()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 27
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3.072

Importance

Changes 0
Metric Value
dl 0
loc 27
ccs 12
cts 15
cp 0.8
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 15
nc 3
nop 2
crap 3.072
1
<?php
2
/**
3
 * This file is part of the Composite Utils package.
4
 *
5
 * (c) Emily Shepherd <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the
8
 * LICENSE.md file that was distributed with this source code.
9
 *
10
 * @package spaark/composite-utils
11
 * @author Emily Shepherd <[email protected]>
12
 * @license MIT
13
 */
14
15
namespace Spaark\CompositeUtils\Factory\Reflection;
16
17
use Spaark\CompositeUtils\Model\Reflection\ReflectionComposite;
18
use Spaark\CompositeUtils\Model\Reflection\ReflectionMethod;
19
use Spaark\CompositeUtils\Model\Reflection\ReflectionParameter;
20
use Spaark\CompositeUtils\Service\RawPropertyAccessor;
21
use Spaark\CompositeUtils\Service\TypeComparator;
22
use Spaark\CompositeUtils\Model\Collection\FixedList;
23
use Spaark\CompositeUtils\Model\Collection\HashMap;
24
use \ReflectionMethod as PHPNativeReflectionMethod;
25
use \ReflectionParameter as PHPNativeReflectionParameter;
26
use \Reflector as PHPNativeReflector;
27
28
/**
29
 * Builds a ReflectionMethod for a given method and optionally links
30
 * this to a parent ReflectionComposite
31
 */
32
class ReflectionMethodFactory extends ReflectorFactory
33
{
34
    const REFLECTION_OBJECT = ReflectionMethod::class;
35
36
    /**
37
     * @var PHPNativeReflectionMethod
38
     */
39
    protected $reflector;
40
41
    /**
42
     * @var ReflectionMethod
43
     */
44
    protected $object;
45
46
    /**
47
     * @var Hashmap
48
     */
49
    protected $parameters;
50
51
    /**
52
     * @var TypeParser
53
     */
54
    protected $typeParser;
55
56
    /**
57
     * Returns a new ReflectionMethodFactory using the given class and
58
     * method names
59
     *
60
     * @param string $class The classname of the method
61
     * @param string $method The method to reflect
62
     * @return ReflectionMethodFactory
63
     */
64
    public static function fromName(string $class, string $method)
65
    {
66
        return new static(new PHPNativeReflectionMethod
67
        (
68
            $class, $method
69
        ));
70
    }
71
72 24
    public function __construct(PHPNativeReflector $reflector)
73
    {
74 24
        parent::__construct($reflector);
75
76 24
        $this->parameters = new HashMap();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Spaark\CompositeUti...el\Collection\HashMap() of type object<Spaark\CompositeU...del\Collection\HashMap> is incompatible with the declared type object<Spaark\CompositeU...ory\Reflection\Hashmap> of property $parameters.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
77 24
    }
78
79
    /**
80
     * Builds the ReflectionMethod from the provided parameters,
81
     * optionally linking to a parent ReflectionComposite
82
     *
83
     * @param ReflectionComposite $parent The reflector for the class
84
     *     this method belongs to
85
     * @return ReflectionMethod
86
     */
87 24
    public function build(?ReflectionComposite $parent = null)
88
    {
89 24
        $this->typeParser = new TypeParser($parent);
90 24
        $this->accessor->setRawValue('owner', $parent);
91 24
        $this->accessor->setRawValue
92
        (
93 24
            'name',
94 24
            $this->reflector->getName()
0 ignored issues
show
Bug introduced by
Consider using $this->reflector->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
95
        );
96
97 24
        $this->initParams();
98
99 24
        $this->accessor->setRawValue('visibility',
100 24
              ($this->reflector->isPublic() ? 'public'
101 3
            : ($this->reflector->isProtected() ? 'protected'
102 1
            : ($this->reflector->isPrivate() ? 'private'
103 24
            : (''))))
104
        );
105 24
        $this->accessor->setRawValue('scope',
106 24
            ($this->reflector->isStatic() ? 'static' : 'dynamic')
107
        );
108 24
        $this->accessor->setRawValue('final',
109 24
            $this->reflector->isFinal()
110
        );
111
112 24
        foreach ($this->reflector->getParameters() as $parameter)
113
        {
114 24
            $this->addParameter($parameter);
115
        }
116
117 24
        $this->parseDocComment(['param' => 'addParamAnnotation']);
118
119 24
        return $this->object;
120
    }
121
122
    /**
123
     * Creates the Method's parameter's property with a fixd list of
124
     * the appropriate size
125
     */
126 24
    protected function initParams()
127
    {
128 24
        $this->accessor->setRawValue
129
        (
130 24
            'parameters',
131 24
            new FixedList(count($this->reflector->getParameters()))
132
        );
133 24
        $this->accessor->setRawValue
134
        (
135 24
            'nativeParameters',
136 24
            new FixedList(count($this->reflector->getParameters()))
137
        );
138 24
    }
139
140
    /**
141
     * Processes a param docblock annotation and uses it to decorate
142
     * a method parameter
143
     *
144
     * @param string $name Unused. Should be 'param'
145
     * @param string $value The annotation value
146
     */
147 24
    protected function addParamAnnotation($name, $value) : void
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
148
    {
149 24
        $items = explode(' ', $value);
150 24
        $type = $items[0];
151 24
        $param = $items[1];
152
153 24
        if (!$this->parameters->containsKey($param))
154
        {
155
            throw new \Exception
156
            (
157
                  'Tried to set param annotation for non existant '
158
                . 'parameter: ' . $param
159
            );
160
        }
161
162 24
        $comparator = new TypeComparator();
163 24
        $type = $this->typeParser->parse($type);
164 24
        $param = $this->parameters[$param];
165 24
        $nativeType = $param->getRawValue('type');
166
167 24
        if (!$comparator->compatible($nativeType, $type))
168
        {
169
            throw new \Exception('Types are incompatible');
170
        }
171
172 24
        $param->setRawValue('type', $type);
173 24
    }
174
175
    /**
176
     * Adds a parameter to the method, based on it's native
177
     * ReflectionParameter
178
     *
179
     * @param PHPNativeReflectionParameter $reflect
180
     */
181 24
    protected function addParameter
182
    (
183
        PHPNativeReflectionParameter $reflect
184
    )
185
    : void
186
    {
187 24
        $parameter = new ReflectionParameter();
188 24
        $accessor = new RawPropertyAccessor($parameter);
189 24
        $type = (new TypeParser())->parse((string)$reflect->getType());
190
191 24
        $this->parameters['$' . $reflect->getName()] = $accessor;
0 ignored issues
show
Bug introduced by
Consider using $reflect->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
192 24
        $this->accessor->rawAddToValue('parameters', $parameter);
0 ignored issues
show
Deprecated Code introduced by
The method Spaark\CompositeUtils\Se...cessor::rawAddToValue() has been deprecated.

This method has been deprecated.

Loading history...
193 24
        $this->accessor->rawAddToValue('nativeParameters',
0 ignored issues
show
Deprecated Code introduced by
The method Spaark\CompositeUtils\Se...cessor::rawAddToValue() has been deprecated.

This method has been deprecated.

Loading history...
194 24
            (string)$reflect->getType()
195
        );
196
197 24
        $accessor->setRawValue('owner', $this->object);
198 24
        $accessor->setRawValue('name', $reflect->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflect->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
199 24
        $accessor->setRawValue('type', $type);
200 24
    }
201
}
202
203