Completed
Push — master ( 5fca22...233410 )
by Emily
01:43
created

ReflectionCompositeFactory   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 246
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 97.14%

Importance

Changes 0
Metric Value
wmc 21
lcom 1
cbo 9
dl 0
loc 246
ccs 68
cts 70
cp 0.9714
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A fromClassName() 0 8 1
A __construct() 0 9 1
A initObject() 0 15 3
A resizeProperties() 0 10 3
A addInheritance() 0 14 2
A buildProperty() 0 14 1
A buildMethod() 0 5 1
B build() 0 42 4
B addItems() 0 42 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\ListCollection\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 21
    public static function fromClassName(string $classname)
66
    {
67 21
        return new static
68
        (
69 21
            new PHPNativeReflectionClass($classname),
70 21
            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 21
    public function __construct
82
    (
83
        PHPNativeReflectionClass $reflect,
84
        ReflectionCompositeProviderInterface $provider
85
    )
86
    {
87 21
        parent::__construct($reflect);
88 21
        $this->provider = $provider;
89 21
    }
90
91
    /**
92
     * Builds the ReflectionComposite from the provided parameters
93
     *
94
     * @return ReflectionComposite
95
     */
96 21
    public function build()
97
    {
98 21
        $this->initObject();
99
100 21
        foreach ($this->reflector->getTraits() as $trait)
101
        {
102 2
            $this->addInheritance('traits', $trait);
103
        }
104
105 21
        if ($parent = $this->reflector->getParentClass())
106
        {
107 1
            $this->addInheritance('parent', $parent, 'setRawValue');
108
        }
109
110 21
        foreach ($this->reflector->getInterfaces() as $interface)
111
        {
112
            $this->addInheritance('interfaces', $interface);
113
        }
114
115 21
        $fileName = $this->reflector->getFileName();
116
117 21
        $file = (new ReflectionFileFactory($fileName))->build();
118 21
        $this->accessor->setRawValue('file', $file);
119
120 21
        $this->accessor->setRawValue
121
        (
122 21
            'classname',
123 21
            $this->reflector->name
124
        );
125 21
        $this->accessor->setRawValue
126
        (
127 21
            'namespace',
128 21
            $file->namespaces[$this->reflector->getNamespaceName()]
129
        );
130
131 21
        $this->addItems('properties', false, 'Property');
132 21
        $this->addItems('methods', true, 'Method');
133
134 21
        $this->resizeProperties();
135
136 21
        return $this->object;
137
    }
138
139
    /**
140
     * Initialise the object with fixed lists
141
     */
142 21
    protected function initObject()
143
    {
144 21
        foreach (static::PROPERTIES as $name => $prefixes)
145
        {
146 21
            $size = count($this->reflector->{'get' . $name}());
147 21
            foreach ($prefixes as $prefix)
148
            {
149 21
                $this->accessor->setRawValue
150
                (
151 21
                    $prefix . $name,
152 21
                    new FixedList($size)
153
                );
154
            }
155
        }
156 21
    }
157
158
    /**
159
     * Resize the FixedList properties down to their size
160
     */
161 21
    protected function resizeProperties()
162
    {
163 21
        foreach (static::PROPERTIES as $name => $prefixes)
164
        {
165 21
            foreach ($prefixes as $prefix)
166
            {
167 21
                $this->object->{$prefix . $name}->resizeToFull();
168
            }
169
        }
170 21
    }
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 21
    protected function addItems
181
    (
182
        string $name,
183
        bool $checkFile,
184
        string $signular
185
    )
186
    {
187 21
        foreach ($this->reflector->{'get' . $name}() as $item)
188
        {
189
            // We only reflect on methods in userspace
190 21
            if ($checkFile && !$item->getFileName())
191
            {
192
                continue;
193
            }
194
            // This belongs to a super class, use that definition
195
            // instead
196 21
            elseif ($item->class !== $this->reflector->getName())
197
            {
198 1
                $item = $this->provider->get($item->class)
199 1
                    ->$name[$item->getName()];
200
            }
201
            // Parse this method
202
            else
203
            {
204
                $factory =
205
                      '\Spaark\CompositeUtils\Factory\Reflection'
206 21
                    . '\Reflection' . $signular . 'Factory';
207 21
                $item = $this->{'build' . $signular}
208
                (
209 21
                    new $factory($item),
210 21
                    $item
211
                );
212 21
                $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 21
                    'local' . ucfirst($name),
215 21
                    $item
216
                );
217
            }
218
219 21
            $this->accessor->getRawValue($name)[$item->name] = $item;
220
        }
221 21
    }
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 3
    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 3
        if ($reflect->getFileName())
239
        {
240 3
            $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 3
            $this->accessor->$method($group, $item);
242
        }
243 3
    }
244
245
    /**
246
     * Uses a ReflectionPropertyFactory to build a ReflectionProperty
247
     *
248
     * @param ReflectionPropertyFactory $factory
249
     * @return ReflectionProperty
250
     */
251 21
    protected function buildProperty
252
    (
253
        ReflectionPropertyFactory $factory,
254
        PHPNativeReflectionProperty $reflect
255
    )
256
    : ReflectionProperty
257
    {
258 21
        return $factory->build
259
        (
260 21
            $this->object,
261 21
            $this->reflector
262 21
                ->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 21
    protected function buildMethod(ReflectionMethodFactory $factory)
273
        : ReflectionMethod
274
    {
275 21
        return $factory->build($this->object);
276
    }
277
}
278
279