Completed
Push — master ( 7fe6b0...d8a5ea )
by Paweł
02:19
created

AbstractItem::grabData()   B

Complexity

Conditions 8
Paths 27

Size

Total Lines 33
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 8

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 8
eloc 17
c 1
b 1
f 0
nc 27
nop 1
dl 0
loc 33
ccs 15
cts 15
cp 1
crap 8
rs 8.4444
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of Wszetko Sitemap.
7
 *
8
 * (c) Paweł Kłopotek-Główczewski <[email protected]>
9
 *
10
 * This source file is subject to the MIT license that is bundled
11
 * with this source code in the file LICENSE.
12
 */
13
14
namespace Wszetko\Sitemap\Items;
15
16
use ReflectionClass;
17
use ReflectionProperty;
18
use Wszetko\Sitemap\Interfaces\DataType;
19
use Wszetko\Sitemap\Interfaces\Item;
20
use Wszetko\Sitemap\Items\DataTypes\ArrayType;
21
use Wszetko\Sitemap\Traits\Domain;
22
use Wszetko\Sitemap\Traits\IsAssoc;
23
24
/**
25
 * Class AbstractItem.
26
 *
27
 * @package Wszetko\Sitemap\Items
28
 */
29
abstract class AbstractItem implements Item
30
{
31
    use IsAssoc;
32
    use Domain;
33
34
    /**
35
     * AbstractItem constructor.
36
     *
37
     * @throws \ReflectionException
38
     */
39 496
    public function __construct()
40
    {
41 496
        $class = new ReflectionClass($this);
42 496
        $properties = $class->getProperties(ReflectionProperty::IS_PROTECTED);
43
44 496
        foreach ($properties as $property) {
45 494
            $data = $this->grabData($property);
46
47 494
            if (!empty($data['type']) &&
48 494
                class_exists($data['type']) &&
49 494
                in_array('Wszetko\Sitemap\Interfaces\DataType', class_implements($data['type']))) {
50 494
                if (!empty($data['dataType']) && class_exists($data['dataType'])) {
51 380
                    $this->{$property->getName()} = new ArrayType($property->getName(), $data['dataType']);
52 380
                    $this->{$property->getName()}->getBaseDataType()->addAttributes($data['attributes']);
53
                } else {
54 476
                    $this->{$property->getName()} = new $data['type']($property->getName());
55 476
                    $this->{$property->getName()}->addAttributes($data['attributes']);
56
                }
57
            }
58
        }
59 496
    }
60
61
    /**
62
     * @param $name
63
     * @param $arguments
64
     *
65
     * @return mixed
66
     */
67 494
    public function __call($name, $arguments)
68
    {
69 494
        $operation = mb_substr($name, 0, 3);
70 494
        $property = lcfirst(mb_substr($name, 3));
71
72 494
        if (property_exists($this, $property) &&
73 494
            in_array($operation, ['add', 'set', 'get']) &&
74 494
            ($this->{$property} instanceof DataType)) {
75 494
            switch ($operation) {
76 494
                case 'add':
77 46
                    $this->{$property}->addValue($arguments[0], array_slice($arguments, 1));
78
79 44
                    return $this;
80 480
                case 'set':
81 476
                    $this->{$property}->setValue($arguments[0], array_slice($arguments, 1));
82
83 472
                    return $this;
84 436
                case 'get':
85 436
                    if (method_exists($this, 'getDomain') &&
86 436
                        method_exists($this->{$property}, 'setDomain') &&
87 436
                        null !== $this->getDomain()
88
                        ) {
89 80
                        $this->{$property}->setDomain($this->getDomain());
90
                    }
91
92 436
                    return $this->{$property}->getValue();
93
            }
94
        }
95 2
    }
96
97
    /**
98
     * @return array
99
     */
100 20
    public function toArray(): array
101
    {
102 20
        $array = [];
103
104 20
        if (static::NAMESPACE_NAME && static::ELEMENT_NAME) {
105
            $array = [
106 12
                '_namespace' => static::NAMESPACE_NAME,
107 12
                '_element' => static::ELEMENT_NAME,
108
            ];
109
        }
110
111 20
        $array[static::ELEMENT_NAME] = [];
112
113 20
        foreach (get_object_vars($this) as $property => $value) {
114 20
            if (is_object($this->{$property})) {
115 18
                $method = 'get' . ucfirst($property);
116 18
                preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $property, $matches);
117 18
                $property = $matches[0];
118
119 18
                foreach ($property as &$match) {
120 18
                    $match = $match == mb_strtoupper($match) ? mb_strtolower($match) : lcfirst($match);
121
                }
122
123 18
                $property = implode('_', $property);
124 18
                $data = $this->{$method}();
125
126 18
                if (is_array($data)) {
127 4
                    if ($this->isAssoc($data)) {
128 4
                        $item = array_key_first($data);
129 4
                        $array[static::ELEMENT_NAME][$property]['_value'] = $item;
130
131 4
                        foreach ($data[$item] as $attr => $val) {
132 4
                            $array[static::ELEMENT_NAME][$property]['_attributes'][$attr] = $val;
133
                        }
134
                    } else {
135 4
                        foreach ($data as $element) {
136 4
                            $array[static::ELEMENT_NAME][$property][] = $element;
137
                        }
138
                    }
139 18
                } elseif (!empty($data)) {
140 18
                    $array[static::ELEMENT_NAME][$property] = $data;
141
                }
142
            }
143
        }
144
145 20
        return $array;
146
    }
147
148
    /**
149
     * @param \ReflectionProperty $property
150
     *
151
     * @return array
152
     */
153 494
    private function grabData(ReflectionProperty $property): array
154
    {
155 494
        preg_match_all('/@var\s+(?\'type\'[^\s]+)|@dataType\s+(?\'dataType\'[^\s]+)|@attribute\s+(?\'attribute\'[^\s]+)|@attributeDataType\s+(?\'attributeDataType\'[^\s]+)/m', $property->getDocComment(), $matches);
156
157
        $results = [
158 494
            'type' => null,
159
            'dataType' => null,
160
            'attributes' => [],
161
        ];
162
163 494
        foreach ($matches['type'] as $match) {
164 494
            if (!empty($match)) {
165 494
                $results['type'] = $match;
166
167 494
                break;
168
            }
169
        }
170
171 494
        foreach ($matches['dataType'] as $match) {
172 494
            if (!empty($match)) {
173 380
                $results['dataType'] = $match;
174
175 380
                break;
176
            }
177
        }
178
179 494
        foreach ($matches['attribute'] as $key => $match) {
180 494
            if (!empty($match) && !empty($matches['attributeDataType'][$key + 1])) {
181 320
                $results['attributes'][$match] = $matches['attributeDataType'][$key + 1];
182
            }
183
        }
184
185 494
        return $results;
186
    }
187
}
188