Passed
Push — master ( 69397d...433084 )
by Chris
07:38
created

PropertyResolver::resolveProperty()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 31
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 6.0702

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 17
c 2
b 0
f 0
dl 0
loc 31
ccs 14
cts 16
cp 0.875
rs 9.0777
cc 6
nc 6
nop 2
crap 6.0702
1
<?php
2
3
namespace WebTheory\Collection\Resolution;
4
5
use LogicException;
6
use ReflectionMethod;
7
use ReflectionProperty;
8
use WebTheory\Collection\Contracts\PropertyResolverInterface;
9
10
class PropertyResolver implements PropertyResolverInterface
11
{
12
    protected array $defined = [];
13
14
    protected array $methods = [];
15
16
    protected array $members = [];
17
18 309
    public function __construct(array $defined = [])
19
    {
20 309
        $this->defined = $defined;
21
    }
22
23 309
    public function resolveProperty(object $object, string $property)
24
    {
25 309
        if ($definedMethod = $this->getDefinedMethod($property)) {
26 21
            return $object->{$definedMethod}();
27
        }
28
29 309
        if ($this->isAccessibleProperty($object, $property)) {
30 309
            return $object->{$property};
31
        }
32
33 6
        $inferredMethod = $this->getInferredMethod($property);
34
35 6
        if (is_callable([$object, $inferredMethod])) {
36 3
            return $object->{$inferredMethod}();
37
        }
38
39 3
        $inferredMember = $this->getInferredMember($property);
40
41 3
        if ($this->isAccessibleProperty($object, $inferredMember)) {
42
            return $object->{$inferredMember};
43
        }
44
45 3
        if (is_callable([$object, $property])) {
46
            return $object->{$property}();
47
        }
48
49 3
        throw new LogicException(
50 3
            sprintf(
51
                'No method of access has been defined or can be resolved for value "%s" in instances of class %s.',
52
                $property,
53 3
                get_class($object)
54
            )
55
        );
56
    }
57
58 309
    protected function isAccessibleProperty(object $object, string $property): bool
59
    {
60 309
        return property_exists($object, $property)
61 309
            && (new ReflectionProperty($object, $property))->isPublic();
62
    }
63
64 309
    protected function getDefinedMethod(string $property): ?string
65
    {
66 309
        return $this->defined[$property] ?? null;
67
    }
68
69 6
    protected function getInferredMethod(string $property): string
70
    {
71 6
        return $this->methods[$property]
72 6
            ??= $this->getPropertyAsMethod($property);
73
    }
74
75 3
    protected function getInferredMember(string $property): string
76
    {
77 3
        return $this->members[$property]
78 3
            ??= $this->getPropertyAsMember($property);
79
    }
80
81 6
    protected function getPropertyAsMethod(string $property): string
82
    {
83 6
        return 'get' . $this->convertToStudlyCaps($property);
84
    }
85
86 3
    protected function getPropertyAsMember(string $property): string
87
    {
88 3
        return lcfirst($this->convertToStudlyCaps($property));
89
    }
90
91 6
    protected function convertToStudlyCaps(string $string): string
92
    {
93 6
        return str_replace(' ', '', ucwords(str_replace('_', ' ', $string)));
94
    }
95
}
96