Completed
Push — master ( f41d77...47f5da )
by Alexander
02:28
created

XmlDifferenceService::difference()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 35
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 35
ccs 21
cts 21
cp 1
rs 8.439
c 0
b 0
f 0
cc 6
eloc 21
nc 3
nop 0
crap 6
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: horat1us
5
 * Date: 5/11/17
6
 * Time: 6:41 PM
7
 */
8
9
namespace Horat1us\Services;
10
11
use Horat1us\Arrays\Collection;
12
use Horat1us\XmlConvertibleInterface;
13
use Horat1us\XmlConvertibleObject;
14
15
16
/**
17
 * Class XmlDifferenceService
18
 * @package Horat1us\Services
19
 */
20
class XmlDifferenceService
21
{
22
    /**
23
     * @var XmlConvertibleInterface
24
     */
25
    protected $source;
26
27
    /**
28
     * @var XmlConvertibleInterface
29
     */
30
    protected $target;
31
32
33
    /**
34
     * XmlDifferenceService constructor.
35
     * @param XmlConvertibleInterface $source
36
     * @param XmlConvertibleInterface $target
37
     */
38 4
    public function __construct(
39
        XmlConvertibleInterface $source,
40
        XmlConvertibleInterface $target
41
    )
42
    {
43
        $this
44 4
            ->setSource($source)
45 4
            ->setTarget($target);
46 4
    }
47
48
    /**
49
     * @return XmlConvertibleInterface|null
50
     */
51 4
    public function difference()
52
    {
53 4
        $current = $this->getSource();
54 4
        $compared = $this->getTarget();
55
56
        if (
57 4
            $current->getXmlElementName() !== $compared->getXmlElementName()
58 4
            || empty($current->getXmlChildren()) && !empty($compared->getXmlChildren())
59 4
            || $this->getIsDifferentProperties()
60
        ) {
61 4
            return clone $current;
62
        }
63
64
65 2
        $newChildren = Collection::from($current->getXmlChildren() ?? [])
66
            ->map(function ($child) {
67 2
                return $this->transform($child);
68 2
            })
69
            ->map(function (XmlConvertibleInterface $child) use ($compared) {
70 2
                return $this->findDifference($child);
71 2
            })
72 2
            ->filter(function ($child) {
73 2
                return $child !== null;
74 2
            })
75 2
            ->array;
76
77 2
        if (empty($newChildren)) {
78 2
            return null;
79
        }
80
81 2
        $target = clone $current;
82 2
        $target->setXmlChildren($newChildren);
83
84 2
        return clone $target;
85
    }
86
87
    /**
88
     * @param XmlConvertibleInterface|\DOMNode|\DOMDocument $object
89
     * @return XmlConvertibleInterface
90
     */
91 2
    protected function transform($object)
92
    {
93 2
        return $object instanceof XmlConvertibleInterface
94 2
            ? $object
95 2
            : XmlConvertibleObject::fromXml($object);
0 ignored issues
show
Documentation introduced by
$object is of type object<DOMNode>, but the function expects a object<DOMDocument>|object<DOMElement>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
96
    }
97
98
    /**
99
     * Finding difference in properties
100
     *
101
     * @return bool
102
     */
103 3
    protected function getIsDifferentProperties()
104
    {
105 3
        foreach ($this->getSource()->getXmlProperties() as $property) {
106
            if (
107 3
                !property_exists($this->getTarget(), $property)
108 3
                || $this->getSource()->{$property} !== $this->getTarget()->{$property}
109
            ) {
110 3
                return true;
111
            }
112
        }
113
114 2
        return false;
115
    }
116
117
    /**
118
     * @param XmlConvertibleInterface $child
119
     * @return XmlConvertibleInterface|null
120
     */
121 2
    protected function findDifference(
122
        XmlConvertibleInterface $child
123
    )
124
    {
125 2
        foreach ($this->getTarget()->getXmlChildren() ?? [] as $comparedChild) {
126 2
            $target = $this->transform($comparedChild);
127
128 2
            if ($difference = $child->xmlDiff($target)) {
129 2
                return $difference;
130
            }
131
        }
132
133 2
        return null;
134
    }
135
136
    /**
137
     * @return XmlConvertibleInterface
138
     */
139 4
    public function getSource(): XmlConvertibleInterface
140
    {
141 4
        return $this->source;
142
    }
143
144
    /**
145
     * @param XmlConvertibleInterface $source
146
     * @return $this
147
     */
148 4
    public function setSource(XmlConvertibleInterface $source)
149
    {
150 4
        $this->source = $source;
151
152 4
        return $this;
153
    }
154
155
    /**
156
     * @return XmlConvertibleInterface
157
     */
158 4
    public function getTarget(): XmlConvertibleInterface
159
    {
160 4
        return $this->target;
161
    }
162
163
    /**
164
     * @param XmlConvertibleInterface $target
165
     * @return $this
166
     */
167 4
    public function setTarget(XmlConvertibleInterface $target)
168
    {
169 4
        $this->target = $target;
170
171 4
        return $this;
172
    }
173
}