Completed
Push — master ( 178130...678bac )
by Paweł
15:27
created

Meta::fillFromObject()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 4
cts 4
cp 1
rs 8.9297
c 0
b 0
f 0
cc 6
nc 8
nop 3
crap 6
1
<?php
2
3
/*
4
 * This file is part of the Superdesk Web Publisher Templates System.
5
 *
6
 * Copyright 2015 Sourcefabric z.ú. and contributors.
7
 *
8
 * For the full copyright and license information, please see the
9
 * AUTHORS and LICENSE files distributed with this source code.
10
 *
11
 * @copyright 2015 Sourcefabric z.ú
12
 * @license http://www.superdesk.org/license
13
 */
14
15
namespace SWP\Component\TemplatesSystem\Gimme\Meta;
16
17
use SWP\Component\TemplatesSystem\Gimme\Context\Context;
18
use SWP\Component\TemplatesSystem\Gimme\Event\MetaEvent;
19
20
class Meta implements MetaInterface
21
{
22
    protected $values;
23
24
    protected $context;
25
26
    protected $configuration;
27
28
    private $copiedValues = [];
29
30
    public function __construct(Context $context, $values, $configuration)
31
    {
32
        $this->context = $context;
33
        $this->values = $values;
34
        $this->configuration = $configuration;
35
36
        $this->context->registerMeta($this);
37
    }
38
39
    /**
40
     * Use to_string property from configuration if provided, json with exposed properties otherwise.
41
     *
42
     * @return string
43
     */
44
    public function __toString()
45
    {
46
        if (array_key_exists('to_string', $this->configuration)) {
47
            $toStringProperty = $this->configuration['to_string'];
48 20
            $this->load($toStringProperty);
49
            if (isset($this->copiedValues[$toStringProperty])) {
50 20
                return (string) $this->copiedValues[$toStringProperty];
51 20
            }
52 20
        }
53
54 20
        return gettype($this->values);
55 2
    }
56 18
57
    /**
58 18
     * @param string $name
59 18
     *
60
     * @return bool
61
     */
62 20
    public function __isset(string $name)
63 20
    {
64
        $this->load($name);
65
        if (array_key_exists($name, $this->copiedValues)) {
66
            return true;
67
        }
68
69
        return false;
70 10
    }
71
72 10
    /**
73 10
     * @param string $name
74
     * @param mixed  $value
75 10
     */
76 5
    public function __set($name, $value)
77
    {
78
        if ($value instanceof \Traversable || is_array($value)) {
79
            $newValue = [];
80 10
81
            foreach ($value as $key => $item) {
82
                $newValue[$key] = $this->getValueOrMeta($item);
83
            }
84
85
            $this->copiedValues[$name] = $newValue;
86
87 19
            return;
88
        }
89 19
90 9
        $this->copiedValues[$name] = $this->getValueOrMeta($value);
91
    }
92 9
93 1
    /**
94
     * @param string $name
95
     *
96 9
     * @return mixed|null
97
     */
98 9
    public function __get(string $name)
99
    {
100
        if (array_key_exists($name, $this->copiedValues)) {
101 19
            return $this->copiedValues[$name];
102 19
        }
103
        $this->load($name);
104 19
105
        return $this->copiedValues[$name];
106 19
    }
107 8
108
    /**
109
     * @return array|object|string
110 19
     */
111
    public function getValues()
112
    {
113
        return $this->values;
114
    }
115
116 10
    public function getConfiguration(): array
117
    {
118 10
        return $this->configuration;
119
    }
120
121
    public function setConfiguration(array $configuration): void
122
    {
123
        $this->configuration = $configuration;
124 20
    }
125
126 20
    public function getContext(): Context
127
    {
128
        return $this->context;
129
    }
130
131
    public function __sleep()
132
    {
133
        unset($this->values, $this->context, $this->configuration);
134
135
        return array_keys(get_object_vars($this));
136
    }
137
138
    private function fillFromArray(array $values, array $configuration, string $name): void
139
    {
140 1
        if (isset($configuration['properties'][$name], $values[$name]) && count($values) > 0) {
141
            $this->$name = $values[$name];
142 1
        }
143
    }
144
145
    private function fillFromObject($values, array $configuration, string $name): void
146
    {
147
        if (!isset($configuration['properties'][$name])) {
148
            return;
149
        }
150
151
        $event = new MetaEvent($this->getValues(), $name);
152
        $this->context->dispatchMetaEvent($event);
153 2
        if ($event->isResultSet()) {
154
            $this->$name = $event->getResult();
155 2
156 2
            return;
157
        }
158
159 2
        $getterName = 'get'.ucfirst($name);
160
        if ('bool' === $configuration['properties'][$name]['type']) {
161
            $getterName = (0 !== strpos($name, 'is')) ? 'is'.ucfirst($name) : $name;
162
        }
163
164
        if (method_exists($values, $getterName)) {
165
            $this->$name = $values->$getterName();
166
        }
167
    }
168
169
    private function isJson(string $string): bool
170 18
    {
171
        json_decode($string, false);
172 18
173 17
        return JSON_ERROR_NONE === json_last_error();
174 17
    }
175 17
176
    /**
177
     * @param mixed $value
178
     *
179 18
     * @return mixed|Meta
180
     */
181 18
    private function getValueOrMeta($value)
182
    {
183
        if ($this->context->isSupported($value)) {
184
            return $this->context->getMetaForValue($value);
185
        }
186
187
        return $value;
188
    }
189
190
    private function load(string $name): void
191
    {
192 2
        if (is_array($this->values)) {
193
            $this->fillFromArray($this->values, $this->configuration, $name);
194 2
        } elseif (is_string($this->values) && $this->isJson($this->values)) {
195 2
            $this->fillFromArray(json_decode($this->values, true), $this->configuration, $name);
196 2
        } elseif (is_object($this->values)) {
197 2
            $this->fillFromObject($this->values, $this->configuration, $name);
198 2
        }
199
    }
200
}
201