Completed
Push — master ( f7de6f...0705c8 )
by Mehmet
01:41
created

EqualsBuilder::append()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.2
c 0
b 0
f 0
cc 4
eloc 8
nc 4
nop 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Selami\Stdlib;
5
6
use ReflectionClass;
7
8
/**
9
 * Class EqualsBuilder
10
 *
11
 * This class provides methods to build a good equals method for any class. Intended to be use to compare Value Objects.
12
 * @package Selami\Stdlib
13
 *
14
 */
15
16
final class EqualsBuilder
17
{
18
    private $isEquals = true;
19
20
    public static function create() : EqualsBuilder
21
    {
22
        return new static();
23
    }
24
    public function append($leftHandedValue, $rightHandedValue)
25
    {
26
        if ($this->isEquals === false) {
27
            return $this;
28
        }
29
        if ($this->checkIfValuesAreAnObjectAndEqual($leftHandedValue, $rightHandedValue)) {
30
            return $this;
31
        }
32
        if ($this->checkForSameType($leftHandedValue, $rightHandedValue)) {
33
            return $this;
34
        }
35
        return $this;
36
    }
37
38
    private function checkForSameType($leftHandedValue, $rightHandedValue) :bool
39
    {
40
        if ($leftHandedValue !== $rightHandedValue) {
41
            $this->isEquals = false;
42
            return false;
43
        }
44
        return true;
45
    }
46
47
    private function checkIfValuesAreAnObjectAndEqual($leftHandedValue, $rightHandedValue) : bool
48
    {
49
        if (! $this->checkIfValuesAreAnObject($leftHandedValue, $rightHandedValue)) {
50
            return false;
51
        }
52
        if (get_class($leftHandedValue) !== get_class($rightHandedValue)) {
53
            $this->isEquals = false;
54
            return false;
55
        }
56
        if (! $this->compareObjectProperties($leftHandedValue, $rightHandedValue)) {
57
            $this->isEquals = false;
58
            return false;
59
        }
60
        return true;
61
    }
62
    private function checkIfValuesAreAnObject($leftHandedValue, $rightHandedValue) : bool
63
    {
64
        return (is_object($leftHandedValue) && is_object($rightHandedValue));
65
    }
66
67
    private function compareObjectProperties($leftHandedObject, $rightHandedObject) : bool
68
    {
69
        $reflectionOfLeftHandedObject = new ReflectionClass($leftHandedObject);
70
        $propertiesOfLeftHandedObject = $this->getPropertiesAsAnArray($leftHandedObject, $reflectionOfLeftHandedObject);
71
        $reflectionOfRightHandedObject = new ReflectionClass($rightHandedObject);
72
        $propertiesOfRightHandedObject = $this->getPropertiesAsAnArray(
73
            $rightHandedObject,
74
            $reflectionOfRightHandedObject
75
        );
76
        return $this->checkValuesRecursively($propertiesOfRightHandedObject, $propertiesOfLeftHandedObject);
77
    }
78
79
    private function checkValuesRecursively(
80
        array $propertiesOfLeftHandedObject,
81
        array $propertiesOfRightHandedObject
82
    ) : bool {
83
        $innerEqualsBuilder = self::create();
84
        foreach ($propertiesOfLeftHandedObject as $propertyName => $propertyValue) {
85
            $innerEqualsBuilder = $innerEqualsBuilder->append(
86
                $propertyValue,
87
                $propertiesOfRightHandedObject[$propertyName]
88
            );
89
        }
90
        return $innerEqualsBuilder->isEquals();
91
    }
92
93
    private function getPropertiesAsAnArray($sourceObject, $object) :array
94
    {
95
        $propertyList = [];
96
        foreach ($object->getProperties() as $property) {
97
            if ($property->isProtected() || $property->isPrivate()) {
98
                $property->setAccessible(true);
99
            }
100
            $propertyList[$property->name] = $property->getValue($sourceObject);
101
        }
102
        return $propertyList;
103
    }
104
105
    public function isEquals() : bool
106
    {
107
        return $this->isEquals;
108
    }
109
}
110