Completed
Push — master ( 79f24a...4b5497 )
by Emily
02:16
created

ReflectionMethodFactory::addParamAnnotation()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 31
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3.1406

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 12
cts 16
cp 0.75
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 17
nc 3
nop 2
crap 3.1406
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\ListCollection\FixedList;
23
use Spaark\CompositeUtils\Model\Collection\Map\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 29
    public function __construct(PHPNativeReflector $reflector)
73
    {
74 29
        parent::__construct($reflector);
75
76 29
        $this->parameters = new HashMap();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Spaark\CompositeUti...ollection\Map\HashMap() of type object<Spaark\CompositeU...Collection\Map\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 29
    }
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 29
    public function build(?ReflectionComposite $parent = null)
88
    {
89 29
        $this->typeParser = new TypeParser($parent);
90 29
        $this->accessor->setRawValue('owner', $parent);
91 29
        $this->accessor->setRawValue
92
        (
93 29
            'name',
94 29
            $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 29
        $this->initParams();
98
99 29
        $this->accessor->setRawValue('visibility',
100 29
              ($this->reflector->isPublic() ? 'public'
101 4
            : ($this->reflector->isProtected() ? 'protected'
102 1
            : ($this->reflector->isPrivate() ? 'private'
103 29
            : (''))))
104
        );
105 29
        $this->accessor->setRawValue('scope',
106 29
            ($this->reflector->isStatic() ? 'static' : 'dynamic')
107
        );
108 29
        $this->accessor->setRawValue('final',
109 29
            $this->reflector->isFinal()
110
        );
111
112 29
        foreach ($this->reflector->getParameters() as $parameter)
113
        {
114 29
            $this->addParameter($parameter);
115
        }
116
117 29
        $this->parseDocComment(['param' => 'addParamAnnotation']);
118
119 29
        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 29
    protected function initParams()
127
    {
128 29
        $this->accessor->setRawValue
129
        (
130 29
            'parameters',
131 29
            new FixedList(count($this->reflector->getParameters()))
132
        );
133 29
        $this->accessor->setRawValue
134
        (
135 29
            'nativeParameters',
136 29
            new FixedList(count($this->reflector->getParameters()))
137
        );
138 29
    }
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 29
    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 29
        $items = explode(' ', $value);
150 29
        $type = $items[0];
151 29
        $param = $items[1];
152
153 29
        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 29
        $comparator = new TypeComparator();
163 29
        $type = $this->typeParser->parse($type);
164 29
        $param = $this->parameters[$param];
165 29
        $nativeType = $param->getRawValue('type');
166
167 29
        if (!$comparator->compatible($nativeType, $type))
168
        {
169
            throw new \Exception
170
            (
171
                  'Types are incompatible for: '
172
                . $this->reflector->getName() . '::' . $items[1]
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...
173
            );
174
        }
175
176 29
        $param->setRawValue('type', $type);
177 29
    }
178
179
    /**
180
     * Adds a parameter to the method, based on it's native
181
     * ReflectionParameter
182
     *
183
     * @param PHPNativeReflectionParameter $reflect
184
     */
185 29
    protected function addParameter
186
    (
187
        PHPNativeReflectionParameter $reflect
188
    )
189
    : void
190
    {
191 29
        $parameter = new ReflectionParameter();
192 29
        $accessor = new RawPropertyAccessor($parameter);
193 29
        $type = (new TypeParser())->parse((string)$reflect->getType());
194
195 29
        $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...
196 29
        $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...
197 29
        $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...
198 29
            (string)$reflect->getType()
199
        );
200
201 29
        $accessor->setRawValue('owner', $this->object);
202 29
        $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...
203 29
        $accessor->setRawValue('type', $type);
204 29
    }
205
}
206
207