Completed
Push — master ( bf375b...cc5661 )
by Rafał
07:07
created

Meta::__construct()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 11
nc 4
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
     * Create Meta class from provided configuration and values.
43
     *
44
     * @param Context             $context
45
     * @param string|array|object $values
46
     * @param array               $configuration
47
     */
48
    public function __construct(Context $context, $values, $configuration)
49
    {
50
        $this->context = $context;
51
        $this->values = $values;
52
        $this->configuration = $configuration;
53
54
        if (is_array($this->values)) {
55
            $this->fillFromArray($this->values, $this->configuration);
56
        } elseif (is_string($this->values) && $this->isJson($this->values)) {
57
            $this->fillFromArray(json_decode($this->values, true), $this->configuration);
58
        } elseif (is_object($this->values)) {
59
            $this->fillFromObject($this->values, $this->configuration);
60
        }
61
62
        $this->context->registerMeta($this);
63
    }
64
65
    /**
66
     * Use to_string property from configuration if provided, json with exposed properties otherwise.
67
     *
68
     * @return string
69
     */
70
    public function __toString()
71
    {
72
        if (array_key_exists('to_string', $this->configuration)) {
73
            $toStringProperty = $this->configuration['to_string'];
74
75
            if (isset($this->$toStringProperty)) {
76
                return $this->$toStringProperty;
77
            }
78
        }
79
80
        return gettype($this->values);
81
    }
82
83
    /**
84
     * @param string $name
85
     * @param mixed  $value
86
     */
87
    public function __set($name, $value)
88
    {
89
        if ($value instanceof \Traversable || is_array($value)) {
90
            $newValue = [];
91
92
            foreach ($value as $key => $item) {
93
                $newValue[$key] = $this->getValueOrMeta($item);
94
            }
95
96
            $this->$name = $newValue;
97
98
            return;
99
        }
100
101
        $this->$name = $this->getValueOrMeta($value);
102
    }
103
104
    private function getValueOrMeta($value)
105
    {
106
        if ($this->context->isSupported($value)) {
107
            return $this->context->getMetaForValue($value);
108
        }
109
110
        return $value;
111
    }
112
113
    /**
114
     * @return array|object|string
115
     */
116
    public function getValues()
117
    {
118
        return $this->values;
119
    }
120
121
    /**
122
     * @return array
123
     */
124
    public function getConfiguration()
125
    {
126
        return $this->configuration;
127
    }
128
129
    /**
130
     * @param array $configuration
131
     */
132
    public function setConfiguration($configuration)
133
    {
134
        $this->configuration = $configuration;
135
    }
136
137
    /**
138
     * @return Context
139
     */
140
    public function getContext()
141
    {
142
        return $this->context;
143
    }
144
145
    /**
146
     * Fill Meta from array. Array must have property names and keys.
147
     *
148
     * @param array $values        Array with properyy names as keys
149
     * @param array $configuration
150
     *
151
     * @return bool
152
     */
153
    private function fillFromArray(array $values, $configuration)
154
    {
155
        foreach ($this->getExposedProperties($values, $configuration) as $key => $propertyValue) {
156
            $this->$key = $propertyValue;
157
        }
158
159
        return true;
160
    }
161
162
    /**
163
     * Fill Meta from object. Object must have public getters for properties.
164
     *
165
     * @param mixed $values        Object with public getters for properties
166
     * @param       $configuration
167
     *
168
     * @return bool
169
     */
170
    private function fillFromObject($values, $configuration)
171
    {
172
        foreach ($configuration['properties'] as $key => $propertyValue) {
173
            $getterName = 'get'.ucfirst($key);
174
            if (method_exists($values, $getterName)) {
175
                $this->$key = $values->$getterName();
176
            }
177
        }
178
179
        return true;
180
    }
181
182
    /**
183
     * Get exposed properties (according to configuration) from provided values.
184
     *
185
     * @param array $values
186
     * @param       $configuration
187
     *
188
     * @return array
189
     */
190
    private function getExposedProperties(array $values = [], $configuration = [])
191
    {
192
        $exposedProperties = [];
193
        if (count($values) > 0 && isset($configuration['properties'])) {
194
            foreach ($values as $key => $propertyValue) {
195
                if (array_key_exists($key, $configuration['properties'])) {
196
                    $exposedProperties[$key] = $propertyValue;
197
                }
198
            }
199
        }
200
201
        return $exposedProperties;
202
    }
203
204
    /**
205
     * Check if string is JSON.
206
     *
207
     * @param  string
208
     *
209
     * @return bool
210
     */
211
    private function isJson($string)
212
    {
213
        json_decode($string);
214
215
        return json_last_error() == JSON_ERROR_NONE;
216
    }
217
218
    /**
219
     * Don't serialize values, context and configuration.
220
     *
221
     * @return array
222
     */
223
    public function __sleep()
224
    {
225
        unset($this->values);
226
        unset($this->context);
227
        unset($this->configuration);
228
229
        return array_keys(get_object_vars($this));
230
    }
231
}
232