Completed
Push — master ( f20108...eb6666 )
by Marin
03:29
created

Entity   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 214
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 32
lcom 1
cbo 3
dl 0
loc 214
rs 9.6
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getId() 0 4 1
A getMetadata() 0 4 1
A getNormalizedMetadata() 0 9 2
C setMetadata() 0 62 14
A update() 0 10 1
A delete() 0 15 3
A toArray() 0 8 2
A fromJson() 0 7 1
A toDateTime() 0 6 1
A toTimestamp() 0 8 2
A setProperties() 0 10 3
1
<?php
2
3
namespace Anorgan\OnFleet;
4
5
use GuzzleHttp\Exception\ClientException;
6
7
/**
8
 * Class Entity
9
 * @package Anorgan\OnFleet
10
 */
11
abstract class Entity
12
{
13
    protected $id;
14
    protected $metadata = [];
15
16
    /**
17
     * @var Client
18
     */
19
    protected $client;
20
21
    protected $endpoint;
22
    protected static $properties = [];
23
24
    /**
25
     * Entity constructor.
26
     * @param Client $client
27
     */
28
    public function __construct(Client $client)
29
    {
30
        $this->client = $client;
31
    }
32
33
    /**
34
     * @return string
35
     */
36
    public function getId()
37
    {
38
        return $this->id;
39
    }
40
41
    /**
42
     * @internal
43
     */
44
    public function getMetadata()
45
    {
46
        throw new \BadMethodCallException('Entity does not support metadata');
47
    }
48
49
    /**
50
     * @return array
51
     */
52
    public function getNormalizedMetadata()
53
    {
54
        $normalizedMetadata = [];
55
        foreach ($this->metadata as $metadatum) {
56
            $normalizedMetadata[$metadatum['name']] = $metadatum['value'];
57
        }
58
59
        return $normalizedMetadata;
60
    }
61
62
    /**
63
     * @param array $metadata
64
     */
65
    public function setMetadata(array $metadata)
66
    {
67
        $structuredMetadata = [];
68
69
        foreach ($metadata as $property => $value) {
70
            $type    = gettype($value);
71
            $subtype = null;
72
            switch ($type) {
73
                case 'boolean':
74
                case 'string':
75
                case 'object':
76
                    // Valid type
77
                    break;
78
79
                case 'integer':
80
                case 'double':
81
                    $type = 'number';
82
                    break;
83
84
                case 'array':
85
                    if (is_string(reset($value))) {
86
                        $type = 'object';
87
                        break;
88
                    }
89
90
                    $subtype = gettype($value[0]);
91
                    array_walk($value, function ($item) use ($subtype, $property) {
92
                        if (gettype($item) !== $subtype) {
93
                            throw new \InvalidArgumentException('All array items have to be of the same type for metadata property '. $property);
94
                        }
95
                    });
96
97
                    if ($subtype == 'integer' || $subtype === 'double') {
98
                        $subtype = 'number';
99
                    }
100
                    $allowedSubtypes = ['boolean', 'number', 'string', 'object'];
101
                    if (!in_array($subtype, $allowedSubtypes)) {
102
                        throw new \InvalidArgumentException('Unallowed type of '. $subtype .' for array item of metadata property '. $property);
103
                    }
104
105
                    break;
106
107
                default:
108
                    throw new \InvalidArgumentException('Unallowed type of '. $type .' for metadata property '. $property);
109
            }
110
111
            $metadatum = [
112
                'name'       => $property,
113
                'type'       => $type,
114
                'value'      => $value,
115
                'visibility' => ['api']
116
            ];
117
118
            if (isset($subtype)) {
119
                $metadatum['subtype'] = $subtype;
120
            }
121
122
            $structuredMetadata[] = $metadatum;
123
        }
124
125
        $this->metadata = $structuredMetadata;
126
    }
127
128
    /**
129
     * @return Entity
130
     */
131
    public function update()
132
    {
133
        $response = $this->client->put($this->endpoint .'/'. $this->id, [
134
            'json' => $this->toArray()
135
        ]);
136
137
        static::setProperties($this, $response->json(['object' => true]));
138
139
        return $this;
140
    }
141
142
    /**
143
     * @throws \Exception
144
     */
145
    public function delete()
146
    {
147
        try {
148
            $this->client->delete($this->endpoint .'/'. $this->id);
149
        } catch (ClientException $e) {
150
            $error   = $e->getResponse()->json();
151
            $message = $error['message']['message'];
152
            if (isset($error['message']['cause'])) {
153
                $message .= ' '. $error['message']['cause'];
154
            }
155
            throw new \Exception('Unable to delete entity: '. $message);
156
        }
157
158
        $this->id = null;
159
    }
160
161
    /**
162
     * @return array
163
     */
164
    public function toArray()
165
    {
166
        $array = [];
167
        foreach (static::$properties as $property) {
168
            $array[$property] = $this->$property;
169
        }
170
        return $array;
171
    }
172
173
    /**
174
     * @param object $json
175
     * @param Client $client
176
     * @return static
177
     */
178
    public static function fromJson($json, Client $client)
179
    {
180
        $entity = new static($client);
181
        static::setProperties($entity, $json);
182
183
        return $entity;
184
    }
185
186
    /**
187
     * @param int $timestamp Timestamp in milliseconds
188
     * @return \DateTime
189
     */
190
    protected function toDateTime($timestamp): \DateTime
191
    {
192
        $date = new \DateTime();
193
        $date->setTimestamp($timestamp / 1000);
194
        return $date;
195
    }
196
197
    /**
198
     * @param int|\DateTime $time
199
     * @return int
200
     */
201
    protected function toTimestamp($time)
202
    {
203
        if ($time instanceof \DateTime) {
204
            $time = $time->getTimestamp() * 1000;
205
        }
206
207
        return $time;
208
    }
209
210
    /**
211
     * @param Entity $entity
212
     * @param object $data
213
     */
214
    protected static function setProperties(Entity $entity, $data)
215
    {
216
        foreach (static::$properties as $property) {
217
            if (!isset($data->$property)) {
218
                continue;
219
            }
220
221
            $entity->$property = json_decode(json_encode($data->$property), true);
222
        }
223
    }
224
}
225