Completed
Push — master ( f51a8f...5648aa )
by Emily
11s
created

ReflectionCompositeFactory::addItems()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 42
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 42
ccs 14
cts 14
cp 1
rs 8.439
c 0
b 0
f 0
cc 5
eloc 21
nc 4
nop 3
crap 5
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\Factory\BaseFactory;
18
use Spaark\CompositeUtils\Model\Reflection\ReflectionComposite;
19
use Spaark\CompositeUtils\Model\Reflection\ReflectionProperty;
20
use Spaark\CompositeUtils\Model\Reflection\ReflectionMethod;
21
use Spaark\CompositeUtils\Model\Collection\FixedList;
22
use Spaark\CompositeUtils\Service\ReflectionCompositeProviderInterface;
23
use Spaark\CompositeUtils\Service\ReflectionCompositeProvider;
24
use \ReflectionClass as PHPNativeReflectionClass;
25
use \ReflectionProperty as PHPNativeReflectionProperty;
26
use \ReflectionMethod as PHPNativeReflectionMethod;
27
use \Reflector;
28
29
/**
30
 * Builds a ReflectionComposite for a given class
31
 */
32
class ReflectionCompositeFactory extends ReflectorFactory
33
{
34
    const REFLECTION_OBJECT = ReflectionComposite::class;
35
36
    const PROPERTIES = [
37
        'traits' => [''],
38
        'interfaces' => [''],
39
        'Methods' => ['local'],
40
        'Properties' => ['local', 'required', 'optional', 'built']
41
    ];
42
43
    /**
44
     * @var PHPNativeReflector
45
     */
46
    protected $reflector;
47
48
    /**
49
     * @var ReflectionComposite
50
     */
51
    protected $object;
52
53
    /**
54
     * @var ReflectionCompositeProviderInterface
55
     */
56
    protected $provider;
57
58
    /**
59
     * Creates a new ReflectionCompositeFactory from the given
60
     * classname
61
     *
62
     * @param string $classname The class to build a reflect upon
63
     * @return ReflectionCompositeFactory
64
     */
65 20
    public static function fromClassName(string $classname)
66
    {
67 20
        return new static
68
        (
69 20
            new PHPNativeReflectionClass($classname),
70 20
            ReflectionCompositeProvider::getDefault()
71
        );
72
    }
73
74
    /**
75
     * Constructs the Factory with the given reflector and Composite
76
     * provider
77
     *
78
     * @param PHPNativeReflectionClass $reflect
79
     * @param ReflectionCompositeProviderInterface $provider
80
     */
81 20
    public function __construct
82
    (
83
        PHPNativeReflectionClass $reflect,
84
        ReflectionCompositeProviderInterface $provider
85
    )
86
    {
87 20
        parent::__construct($reflect);
88 20
        $this->provider = $provider;
89 20
    }
90
91
    /**
92
     * Builds the ReflectionComposite from the provided parameters
93
     *
94
     * @return ReflectionComposite
95
     */
96 20
    public function build()
97
    {
98 20
        $this->initObject();
99
100 20
        foreach ($this->reflector->getTraits() as $trait)
101
        {
102 3
            $this->addInheritance('traits', $trait);
103
        }
104
105 20
        if ($parent = $this->reflector->getParentClass())
106
        {
107 2
            $this->addInheritance('parent', $parent, 'setRawValue');
108
        }
109
110 20
        foreach ($this->reflector->getInterfaces() as $interface)
111
        {
112 1
            $this->addInheritance('interfaces', $interface);
113
        }
114
115 20
        $fileName = $this->reflector->getFileName();
116
117 20
        $file = (new ReflectionFileFactory($fileName))->build();
118 20
        $this->accessor->setRawValue('file', $file);
119
120 20
        $this->accessor->setRawValue
121
        (
122 20
            'classname',
123 20
            $this->reflector->name
124
        );
125 20
        $this->accessor->setRawValue
126
        (
127 20
            'namespace',
128 20
            $file->namespaces[$this->reflector->getNamespaceName()]
129
        );
130
131 20
        $this->addItems('properties', false, 'Property');
132 20
        $this->addItems('methods', true, 'Method');
133
134 20
        $this->resizeProperties();
135
136 20
        return $this->object;
137
    }
138
139
    /**
140
     * Initialise the object with fixed lists
141
     */
142 20
    protected function initObject()
143
    {
144 20
        foreach (static::PROPERTIES as $name => $prefixes)
145
        {
146 20
            $size = count($this->reflector->{'get' . $name}());
147 20
            foreach ($prefixes as $prefix)
148
            {
149 20
                $this->accessor->setRawValue
150
                (
151 20
                    $prefix . $name,
152 20
                    new FixedList($size)
153
                );
154
            }
155
        }
156 20
    }
157
158
    /**
159
     * Resize the FixedList properties down to their size
160
     */
161 20
    protected function resizeProperties()
162
    {
163 20
        foreach (static::PROPERTIES as $name => $prefixes)
164
        {
165 20
            foreach ($prefixes as $prefix)
166
            {
167 20
                $this->object->{$prefix . $name}->resizeToFull();
168
            }
169
        }
170 20
    }
171
172
    /**
173
     * Loops through the list methods or properties adding them to the
174
     * Composite
175
     *
176
     * @param string $name
177
     * @param bool $checkFile
178
     * @param string $singular
0 ignored issues
show
Bug introduced by
There is no parameter named $singular. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
179
     */
180 20
    protected function addItems
181
    (
182
        string $name,
183
        bool $checkFile,
184
        string $signular
185
    )
186
    {
187 20
        foreach ($this->reflector->{'get' . $name}() as $item)
188
        {
189
            // We only reflect on methods in userspace
190 20
            if ($checkFile && !$item->getFileName())
191
            {
192 1
                continue;
193
            }
194
            // This belongs to a super class, use that definition
195
            // instead
196 20
            elseif ($item->class !== $this->reflector->getName())
197
            {
198 2
                $item = $this->provider->get($item->class)
199 2
                    ->$name[$item->getName()];
200
            }
201
            // Parse this method
202
            else
203
            {
204
                $factory =
205
                      '\Spaark\CompositeUtils\Factory\Reflection'
206 20
                    . '\Reflection' . $signular . 'Factory';
207 20
                $item = $this->{'build' . $signular}
208
                (
209 20
                    new $factory($item),
210
                    $item
211
                );
212 20
                $this->accessor->rawAddToValue
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...
213
                (
214 20
                    'local' . ucfirst($name),
215
                    $item
216
                );
217
            }
218
219 20
            $this->accessor->getRawValue($name)[$item->name] = $item;
220
        }
221 20
    }
222
223
    /**
224
     * Adds a super class / interface / trait to this Composite
225
     *
226
     * @param string $group The type of superclass (parent, etc...)
227
     * @param PHPNativeReflectionClass $reflect
228
     * @param string $method
229
     */
230 4
    protected function addInheritance
231
    (
232
        string $group,
233
        PHPNativeReflectionClass $reflect,
234
        string $method = 'rawAddToValue'
235
    )
236
    {
237
        // We only reflect on classes within userspace
238 4
        if ($reflect->getFileName())
239
        {
240 4
            $item = $this->provider->get($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...
241 4
            $this->accessor->$method($group, $item);
242
        }
243 4
    }
244
245
    /**
246
     * Uses a ReflectionPropertyFactory to build a ReflectionProperty
247
     *
248
     * @param ReflectionPropertyFactory $factory
249
     * @return ReflectionProperty
250
     */
251 20
    protected function buildProperty
252
    (
253
        ReflectionPropertyFactory $factory,
254
        PHPNativeReflectionProperty $reflect
255
    )
256
    : ReflectionProperty
257
    {
258 20
        return $factory->build
259
        (
260 20
            $this->object,
261 20
            $this->reflector
262 20
                ->getDefaultProperties()[$reflect->getName()]
263
        );
264
    }
265
266
    /**
267
     * Uses a ReflectionMethodFactory to build a ReflectionMethod
268
     *
269
     * @param ReflectionMethodFactory $factory
270
     * @return ReflectionMethod
271
     */
272 20
    protected function buildMethod(ReflectionMethodFactory $factory)
273
        : ReflectionMethod
274
    {
275 20
        return $factory->build($this->object);
276
    }
277
}
278
279