Completed
Push — master ( c527ef...e35e63 )
by Rafał
02:22
created

Meta::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 3
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
19
/**
20
 * Class Meta.
21
 */
22
class Meta implements MetaInterface
23
{
24
    /**
25
     * Original Meta values (json|array|object).
26
     *
27
     * @var mixed
28
     */
29
    protected $values;
30
31
    /**
32
     * @var Context
33
     */
34
    protected $context;
35
36
    /**
37
     * @var array
38
     */
39
    protected $configuration;
40
41
    /**
42
     * @var array
43
     */
44
    private $copiedValues = [];
45
46
    /**
47
     * Create Meta class from provided configuration and values.
48
     *
49
     * @param Context             $context
50
     * @param string|array|object $values
51
     * @param array               $configuration
52
     */
53
    public function __construct(Context $context, $values, $configuration)
54
    {
55
        $this->context = $context;
56
        $this->values = $values;
57
        $this->configuration = $configuration;
58
59
        $this->context->registerMeta($this);
60
    }
61
62
    /**
63
     * Use to_string property from configuration if provided, json with exposed properties otherwise.
64
     *
65
     * @return string
66
     */
67
    public function __toString()
68
    {
69
        if (array_key_exists('to_string', $this->configuration)) {
70
            $toStringProperty = $this->configuration['to_string'];
71
            $this->__load($toStringProperty);
72
            if (isset($this->copiedValues[$toStringProperty])) {
73
                return $this->copiedValues[$toStringProperty];
74
            }
75
        }
76
77
        return gettype($this->values);
78
    }
79
80
    /**
81
     * @param string $name
82
     *
83
     * @return bool
84
     */
85
    public function __isset(string $name)
86
    {
87
        $this->__load($name);
88
        if (array_key_exists($name, $this->copiedValues)) {
89
            return true;
90
        }
91
92
        return false;
93
    }
94
95
    /**
96
     * @param string $name
97
     * @param mixed  $value
98
     */
99
    public function __set($name, $value)
100
    {
101
        if ($value instanceof \Traversable || is_array($value)) {
102
            $newValue = [];
103
104
            foreach ($value as $key => $item) {
105
                $newValue[$key] = $this->getValueOrMeta($item);
106
            }
107
108
            $this->copiedValues[$name] = $newValue;
109
110
            return;
111
        }
112
113
        $this->copiedValues[$name] = $this->getValueOrMeta($value);
114
    }
115
116
    /**
117
     * @param string $name
118
     *
119
     * @return mixed|null
120
     */
121
    public function __get(string $name)
122
    {
123
        if (array_key_exists($name, $this->copiedValues)) {
124
            return $this->copiedValues[$name];
125
        }
126
        $this->__load($name);
127
128
        return $this->copiedValues[$name];
129
    }
130
131
    /**
132
     * @return array|object|string
133
     */
134
    public function getValues()
135
    {
136
        return $this->values;
137
    }
138
139
    /**
140
     * @return array
141
     */
142
    public function getConfiguration()
143
    {
144
        return $this->configuration;
145
    }
146
147
    /**
148
     * @param array $configuration
149
     */
150
    public function setConfiguration($configuration)
151
    {
152
        $this->configuration = $configuration;
153
    }
154
155
    /**
156
     * @return Context
157
     */
158
    public function getContext()
159
    {
160
        return $this->context;
161
    }
162
163
    /**
164
     * Don't serialize values, context and configuration.
165
     *
166
     * @return array
167
     */
168
    public function __sleep()
169
    {
170
        unset($this->values);
171
        unset($this->context);
172
        unset($this->configuration);
173
174
        return array_keys(get_object_vars($this));
175
    }
176
177
    /**
178
     * @param array  $values
179
     * @param array  $configuration
180
     * @param string $name
181
     *
182
     * @return bool
183
     */
184
    private function fillFromArray(array $values, array $configuration, string $name)
185
    {
186
        if (count($values) > 0 && isset($configuration['properties'][$name]) && isset($values[$name])) {
187
            $this->$name = $values[$name];
188
        }
189
190
        return true;
191
    }
192
193
    /**
194
     * Fill Meta from object. Object must have public getters for properties.
195
     *
196
     * @param mixed $values        Object with public getters for properties
197
     * @param array $configuration
198
     *
199
     * @return bool
200
     */
201
    private function fillFromObject($values, array $configuration, string $name)
202
    {
203
        if (isset($configuration['properties'][$name])) {
204
            $getterName = 'get'.ucfirst($name);
205
            if (method_exists($values, $getterName)) {
206
                $this->$name = $values->$getterName();
207
            }
208
        }
209
210
        unset($values, $configuration);
211
212
        return true;
213
    }
214
215
    /**
216
     * Check if string is JSON.
217
     *
218
     * @param  string
219
     *
220
     * @return bool
221
     */
222
    private function isJson($string)
223
    {
224
        json_decode($string);
225
226
        return JSON_ERROR_NONE === json_last_error();
227
    }
228
229
    /**
230
     * @param $value
231
     *
232
     * @return Meta
233
     */
234
    private function getValueOrMeta($value)
235
    {
236
        if ($this->context->isSupported($value)) {
237
            return $this->context->getMetaForValue($value);
238
        }
239
240
        return $value;
241
    }
242
243
    /**
244
     * @param string $name
245
     */
246
    private function __load(string $name)
247
    {
248
        if (is_array($this->values)) {
249
            $this->fillFromArray($this->values, $this->configuration, $name);
250
        } elseif (is_string($this->values) && $this->isJson($this->values)) {
251
            $this->fillFromArray(json_decode($this->values, true), $this->configuration, $name);
252
        } elseif (is_object($this->values)) {
253
            $this->fillFromObject($this->values, $this->configuration, $name);
254
        }
255
    }
256
}
257