BaseXmlEntity::fromXml()   B
last analyzed

Complexity

Conditions 8
Paths 4

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 8.0109

Importance

Changes 0
Metric Value
cc 8
eloc 19
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 31
ccs 17
cts 18
cp 0.9444
crap 8.0109
rs 8.4444
1
<?php
2
3
namespace PagOnline\XmlEntities;
4
5
use PagOnline\IgfsUtils;
6
use PagOnline\XmlEntities\Traits\CastProperties;
7
use PagOnline\XmlEntities\Traits\EntityAttributes;
8
use ReflectionObject;
9
use ReflectionProperty;
10
use SimpleXMLElement;
11
12
abstract class BaseXmlEntity implements XmlEntityInterface
13
{
14
    use CastProperties, EntityAttributes;
15
16
    /**
17
     * @var array
18
     */
19
    protected $attributes = [];
20
21
    /**
22
     * BaseXmlEntity constructor.
23
     */
24 19
    public function __construct()
25
    {
26 19
        $this->loadAttributes();
27
    }
28
29
    /**
30
     * Get object attributes.
31
     *
32
     * @return array
33
     */
34 7
    public function getAttributes(): array
35
    {
36 7
        return $this->attributes;
37
    }
38
39
    /**
40
     * Format entity to Xml.
41
     *
42
     * @param string $rootNodeName
43
     *
44
     * @return string
45
     */
46 7
    public function toXml(string $rootNodeName): string
47
    {
48 7
        $body = "<{$rootNodeName}>";
49 7
        foreach ($this->attributes as $attribute) {
50 7
            if (!empty($this->{$attribute})) {
51 7
                if (!$this->isEntityAttribute($attribute)) {
52 7
                    $value = $this->castAttribute($attribute);
53 7
                    if (\is_array($value)) {
54 1
                        foreach ($value as $valueEntry) {
55 1
                            $body .= $this->attributeValueToTagString($attribute, $valueEntry);
56
                        }
57
                    } else {
58 7
                        $body .= $this->attributeValueToTagString($attribute, $value);
59
                    }
60
                } else {
61 3
                    $body .= $this->getCustomAttributeXml($attribute);
62
                }
63
            }
64
        }
65 7
        $body .= "</{$rootNodeName}>";
66
67 7
        return $body;
68
    }
69
70
    /**
71
     * @param array  $response
72
     * @param string $attribute
73
     */
74 5
    public function setAttributeFromResponse($response, $attribute): void
75
    {
76 5
        $value = (string) IgfsUtils::getValue($response, $attribute);
77 5
        if ($this->isDateAttribute($attribute)) {
78 2
            $tmpValue = IgfsUtils::parseXMLGregorianCalendar($value);
79 2
            if ($tmpValue !== null) {
80 2
                $value = $tmpValue->getTimestamp();
81
            } else {
82
                $value = null;
83
            }
84
        }
85 5
        $this->{$attribute} = $value;
86
    }
87
88
    /**
89
     * Generate BaseXmlEntity.
90
     *
91
     * @param string $xml
92
     *
93
     * @return null|\PagOnline\XmlEntities\XmlEntityInterface
94
     */
95 5
    public static function fromXml($xml): ?XmlEntityInterface
96
    {
97 5
        if (empty($xml)) {
98 1
            return null;
99
        }
100
101 5
        $dom = new SimpleXMLElement($xml, LIBXML_NOERROR, false);
102 5
        if ($dom->children()->count() === 0) {
103
            return null;
104
        }
105
106 5
        $xmlArray = IgfsUtils::parseResponseFields($dom);
107 5
        $object = null;
108 5
        if (\count($xmlArray) > 0) {
109 5
            $object = new static();
110 5
            foreach ($object->getAttributes() as $attribute) {
111 5
                if (!$object->isEntityAttribute($attribute)) {
112 5
                    if ($object->getAttributeCastType($attribute) !== 'array') {
113 5
                        $object->setAttributeFromResponse($xmlArray, $attribute);
114
                    } else {
115 5
                        foreach ($dom->xpath($attribute) as $entry) {
116 2
                            $object->{$attribute}[] = $entry->__toString();
117
                        }
118
                    }
119
                } else {
120 2
                    $object->setCustomAttributeFromDom($dom, $attribute);
121
                }
122
            }
123
        }
124
125 5
        return $object;
126
    }
127
128
    /**
129
     * @return array
130
     */
131 2
    public function toArray(): array
132
    {
133 2
        $returnArray = [];
134 2
        foreach ($this->attributes as $attribute) {
135 2
            $returnArray[$attribute] = $this->{$attribute};
136
        }
137
138 2
        return $returnArray;
139
    }
140
141
    /**
142
     * Load attributes from public properties.
143
     */
144 19
    protected function loadAttributes(): void
145
    {
146 19
        $publicProperties = (new ReflectionObject($this))->getProperties(ReflectionProperty::IS_PUBLIC);
147 19
        foreach ($publicProperties as $publicProperty) {
148 19
            $this->attributes[] = $publicProperty->getName();
149
        }
150
    }
151
152
    /**
153
     * @param string $attribute
154
     * @param string $value
155
     *
156
     * @return string
157
     */
158 7
    protected function attributeValueToTagString(string $attribute, string $value): string
159
    {
160 7
        return "<{$attribute}><![CDATA[{$value}]]></{$attribute}>";
161
    }
162
163
    /**
164
     * @param \SimpleXMLElement $dom
165
     * @param string            $attribute
166
     */
167 2
    protected function setCustomAttributeFromDom(SimpleXMLElement $dom, $attribute): void
168
    {
169 2
        if ($this->entityAttributes[$attribute]['type'] === 'array') {
170 2
            $value = [];
171 2
            foreach ($dom->xpath($attribute) as $item) {
172 2
                $value[] = $this->entityAttributes[$attribute]['namespace']::fromXml($item->asXML());
173
            }
174
        } else {
175
            $element = $dom->xpath($attribute);
176
            $value = null;
177
            if (\count($element) > 0) {
178
                $value = $this->entityAttributes[$attribute]['namespace']::fromXml($element[0]->asXML());
179
            }
180
        }
181 2
        $this->{$attribute} = $value;
182
    }
183
}
184