Completed
Pull Request — 1.x (#1)
by Dorian
02:41
created

Getter   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 130
Duplicated Lines 53.08 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 26
lcom 1
cbo 0
dl 69
loc 130
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A get() 16 16 4
A getFromArray() 0 10 3
B getFromObject() 24 24 6
B findGetterMethod() 14 14 7
B findProperty() 15 15 5

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
namespace MetaHydrator\Reflection;
3
4
use ArrayAccess;
5
use ReflectionClass;
6
use ReflectionException;
7
use ReflectionMethod;
8
9
class Getter implements GetterInterface
10
{
11
    /** @var bool */
12
    protected $throwOnFail;
13
14
    /** @var bool */
15
    protected $ignoreProtected;
16
17
    /**
18
     * Getter constructor.
19
     * @param bool $throwOnFail
20
     * @param bool $ignoreProtected
21
     */
22
    public function __construct(bool $throwOnFail = true, bool $ignoreProtected = false)
23
    {
24
        $this->throwOnFail = $throwOnFail;
25
        $this->ignoreProtected = $ignoreProtected;
26
    }
27
28
    /**
29
     * @param $object
30
     * @param string $field
31
     * @return mixed
32
     */
33 View Code Duplication
    public function get($object, string $field)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
34
    {
35
        if (is_array($object)) {
36
            return $this->getFromArray($object, $field);
37
        }
38
39
        if (is_object($object)) {
40
            return $this->getFromObject($object, $field);
41
        }
42
43
        if ($this->throwOnFail) {
44
            throw new ReflectionException("cannot extract field '$field' from non-object, non-array value");
45
        } else {
46
            return null;
47
        }
48
    }
49
50
    /**
51
     * @param $object
52
     * @param string $field
53
     * @return null
54
     * @throws ReflectionException
55
     */
56
    protected function getFromArray($object, string $field)
57
    {
58
        if (array_key_exists($field, $object)) {
59
            return $object[$field];
60
        } else if ($this->throwOnFail) {
61
            throw new ReflectionException("cannot extract field '$field' from array");
62
        } else {
63
            return null;
64
        }
65
    }
66
67
    /**
68
     * @param $object
69
     * @param string $field
70
     * @return mixed|null
71
     * @throws ReflectionException
72
     */
73 View Code Duplication
    protected function getFromObject($object, string $field)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
74
    {
75
        $reflectionClass = new ReflectionClass($object);
76
77
        $getterMethod = $this->findGetterMethod($reflectionClass, $field);
78
        if ($getterMethod !== null) {
79
            return $getterMethod->invoke($object);
80
        }
81
82
        $property = $this->findProperty($reflectionClass, $field);
83
        if ($property !== null) {
84
            return $property->getValue($object);
85
        }
86
87
        if ($object instanceof ArrayAccess && $object->offsetExists($field)) {
88
            return $object->offsetGet($field);
89
        }
90
91
        if ($this->throwOnFail) {
92
            throw new ReflectionException("cannot extract field '$field' from object");
93
        } else {
94
            return null;
95
        }
96
    }
97
98
    /**
99
     * @param ReflectionClass $reflectionClass
100
     * @param string $field
101
     * @return null|ReflectionMethod
102
     */
103 View Code Duplication
    protected function findGetterMethod(ReflectionClass $reflectionClass, string $field)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
104
    {
105
        foreach ($reflectionClass->getMethods($this->ignoreProtected ? ReflectionMethod::IS_PUBLIC|ReflectionMethod::IS_PROTECTED|ReflectionMethod::IS_PRIVATE : ReflectionMethod::IS_PUBLIC) as $reflectionMethod) {
106
            if (!$reflectionMethod->isStatic()
107
                && $reflectionMethod->getNumberOfRequiredParameters() == 0
108
                && strcasecmp($reflectionMethod->getName(), "get$field") == 0) {
0 ignored issues
show
Bug introduced by
Consider using $reflectionMethod->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
109
                if (!$reflectionMethod->isPublic()) {
110
                    $reflectionMethod->setAccessible(true);
111
                }
112
                return $reflectionMethod;
113
            }
114
        }
115
        return null;
116
    }
117
118
    /**
119
     * @param ReflectionClass $reflectionClass
120
     * @param string $field
121
     * @return null|\ReflectionProperty
122
     */
123 View Code Duplication
    protected function findProperty(ReflectionClass $reflectionClass, string $field)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124
    {
125
        if ($reflectionClass->hasProperty($field)) {
126
            $property = $reflectionClass->getProperty($field);
127
            if (!$property->isStatic()) {
128
                if ($property->isPublic()) {
129
                    return $property;
130
                } else if ($this->ignoreProtected) {
131
                    $property->setAccessible(true);
132
                    return $property;
133
                }
134
            }
135
        }
136
        return null;
137
    }
138
}
139