Completed
Push — master ( 863650...abf17e )
by Joschi
03:17
created

SystemProperties::getLongitude()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
cc 1
eloc 2
nc 1
nop 0
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
/**
4
 * apparat-object
5
 *
6
 * @category    Apparat
7
 * @package     Apparat\Object
8
 * @subpackage  Apparat\Object\Application
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license     http://opensource.org/licenses/MIT The MIT License (MIT)
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Apparat\Object\Domain\Model\Properties;
38
39
use Apparat\Kernel\Tests\Kernel;
40
use Apparat\Object\Domain\Model\Object\Id;
41
use Apparat\Object\Domain\Model\Object\ObjectInterface;
42
use Apparat\Object\Domain\Model\Object\Revision;
43
use Apparat\Object\Domain\Model\Object\RuntimeException;
44
use Apparat\Object\Domain\Model\Object\Type;
45
46
/**
47
 * Object system properties collection
48
 *
49
 * In general, the system properties are used as read-only collection, with one exception: Draft objects don't have the
50
 * `published` property set, so there's a {@link publish()} method for advancing an object's state.
51
 *
52
 * @package Apparat\Object
53
 * @subpackage Apparat\Object\Application
54
 */
55
class SystemProperties extends AbstractProperties
56
{
57
    /**
58
     * Collection name
59
     *
60
     * @var string
61
     */
62
    const COLLECTION = 'system';
63
    /**
64
     * ID property
65
     *
66
     * @var string
67
     */
68
    const PROPERTY_ID = 'id';
69
    /**
70
     * Type property
71
     *
72
     * @var string
73
     */
74
    const PROPERTY_TYPE = 'type';
75
    /**
76
     * Revision property
77
     *
78
     * @var string
79
     */
80
    const PROPERTY_REVISION = 'revision';
81
    /**
82
     * Created property
83
     *
84
     * @var string
85
     */
86
    const PROPERTY_CREATED = 'created';
87
    /**
88
     * Published property
89
     *
90
     * @var string
91
     */
92
    const PROPERTY_PUBLISHED = 'published';
93
    /**
94
     * LocationProperties property
95
     *
96
     * @var string
97
     */
98
    const PROPERTY_LOCATION = 'location';
99
    /**
100
     * Hash property
101
     *
102
     * @var string
103
     */
104
    const PROPERTY_HASH = 'hash';
105
    /**
106
     * Object ID (constant throughout revisions)
107
     *
108
     * @var Id
109
     */
110
    protected $uid = null;
111
    /**
112
     * Object type (constant throughout revisions)
113
     *
114
     * @var Type
115
     */
116
    protected $type = null;
117
    /**
118
     * Object revision
119
     *
120
     * @var Revision
121
     */
122
    protected $revision = null;
123
    /**
124
     * Creation date of this revision
125
     *
126
     * @var \DateTimeImmutable
127
     */
128
    protected $created = null;
129
    /**
130
     * Publication date of this revision
131
     *
132
     * @var \DateTimeImmutable
133
     */
134
    protected $published = null;
135
    /**
136
     * Location
137
     *
138
     * @var LocationProperties
139
     */
140
    protected $location = null;
141
    /**
142
     * Object hash of this revision
143
     *
144
     * @var string
145
     */
146
    protected $hash = '';
147
148
    /**
149
     * System properties constructor
150
     *
151
     * @param array $data Property data
152
     * @param ObjectInterface $object Owner object
153
     */
154 23
    public function __construct(array $data, ObjectInterface $object)
155
    {
156 23
        parent::__construct($data, $object);
157
158
        // Initialize the object ID
159 23
        if (array_key_exists(self::PROPERTY_ID, $data)) {
160 21
            $this->uid = Id::unserialize($data[self::PROPERTY_ID]);
161
        }
162
163
        // Initialize the object type
164 23
        if (array_key_exists(self::PROPERTY_TYPE, $data)) {
165 22
            $this->type = Type::unserialize($data[self::PROPERTY_TYPE]);
166
        }
167
168
        // Initialize the object revision
169 22
        if (array_key_exists(self::PROPERTY_REVISION, $data)) {
170 21
            $this->revision = Revision::unserialize($data[self::PROPERTY_REVISION]);
171
        }
172
173
        // Initialize the object creation date
174 22
        if (array_key_exists(self::PROPERTY_CREATED, $data)) {
175 21
            $this->created = new \DateTimeImmutable('@'.$data[self::PROPERTY_CREATED]);
176
        }
177
178
        // Initialize the object publication date
179 22
        if (array_key_exists(self::PROPERTY_PUBLISHED, $data)) {
180 16
            $this->published = new \DateTimeImmutable('@'.$data[self::PROPERTY_PUBLISHED]);
181
        }
182
183
        // Initialize the location
184 22
        $this->location = Kernel::create(
185 22
            LocationProperties::class,
186 22
            [empty($data[self::PROPERTY_LOCATION]) ? [] : $data[self::PROPERTY_LOCATION], $this->object]
187
        );
188
189
        // Initialize the object hash
190 22
        if (array_key_exists(self::PROPERTY_HASH, $data)) {
191 20
            $this->hash = $data[self::PROPERTY_HASH];
192
        }
193
194
        // Test if all mandatory properties are set
195 22
        if (!($this->uid instanceof Id)
196 21
            || !($this->type instanceof Type)
197 21
            || !($this->revision instanceof Revision)
198 22
            || !($this->created instanceof \DateTimeImmutable)
199
//            || !$this->hasValidHash()
200
        ) {
201 1
            throw new InvalidArgumentException(
202 1
                'Invalid system properties',
203 1
                InvalidArgumentException::INVALID_SYSTEM_PROPERTIES
204
            );
205
        }
206 21
    }
207
208
    /**
209
     * Return the object ID
210
     *
211
     * @return Id Object ID
212
     */
213 5
    public function getId()
214
    {
215 5
        return $this->uid;
216
    }
217
218
    /**
219
     * Return the object type
220
     *
221
     * @return Type Object type
222
     */
223 1
    public function getType()
224
    {
225 1
        return $this->type;
226
    }
227
228
    /**
229
     * Return the object revision
230
     *
231
     * @return Revision Object revision
232
     */
233 20
    public function getRevision()
234
    {
235 20
        return $this->revision;
236
    }
237
238
    /**
239
     * Return the object draft mode
240
     *
241
     * @return boolean Object draft mode
242
     */
243 4
    public function isDraft()
244
    {
245 4
        return !($this->published instanceof \DateTimeImmutable);
246
    }
247
248
    /**
249
     * Return the creation date & time of this revision
250
     *
251
     * @return \DateTimeImmutable Creation date & time
252
     */
253 1
    public function getCreated()
254
    {
255 1
        return $this->created;
256
    }
257
258
    /**
259
     * Return the publication date & time of this revision
260
     *
261
     * @return \DateTimeImmutable|null Publication date & time
262
     */
263 1
    public function getPublished()
264
    {
265 1
        return $this->published;
266
    }
267
268
    /**
269
     * Return the latitude
270
     *
271
     * @return float Latitude
272
     */
273 1
    public function getLatitude()
274
    {
275 1
        return $this->location->getLatitude();
276
    }
277
278
    /**
279
     * Set the latitude
280
     *
281
     * @param float $latitude Latitude
282
     * @return SystemProperties Self reference
283
     */
284 1
    public function setLatitude($latitude)
285
    {
286 1
        return $this->mutatePropertiesProperty(
287 1
            self::PROPERTY_LOCATION,
288 1
            $this->location->setLatitude($latitude)
289
        );
290
    }
291
292
    /**
293
     * Return the longitude
294
     *
295
     * @return float Longitude
296
     */
297 1
    public function getLongitude()
298
    {
299 1
        return $this->location->getLongitude();
300
    }
301
302
    /**
303
     * Set the longitude
304
     *
305
     * @param float $longitude Longitude
306
     * @return SystemProperties Self reference
307
     */
308 1
    public function setLongitude($longitude)
309
    {
310 1
        return $this->mutatePropertiesProperty(
311 1
            self::PROPERTY_LOCATION,
312 1
            $this->location->setLongitude($longitude)
313
        );
314
    }
315
316
    /**
317
     * Return the elevation
318
     *
319
     * @return float Elevation
320
     */
321
    public function getElevation()
322
    {
323
        return $this->location->getElevation();
324
    }
325
326
    /**
327
     * Set the elevation
328
     *
329
     * @param float $elevation
330
     * @return SystemProperties Self reference
331
     */
332 1
    public function setElevation($elevation)
333
    {
334 1
        return $this->mutatePropertiesProperty(
335 1
            self::PROPERTY_LOCATION,
336 1
            $this->location->setElevation($elevation)
337
        );
338
    }
339
340
    /**
341
     * Return the object hash of this revision
342
     *
343
     * @return string Object hash
344
     */
345 1
    public function getHash()
346
    {
347 1
        return $this->hash;
348
    }
349
350
    /**
351
     * Derive draft system properties
352
     *
353
     * @param Revision $draftRevision Draft revision
354
     * @return SystemProperties Draft system properties
355
     */
356 3
    public function createDraft(Revision $draftRevision)
357
    {
358 3
        return new static(
359
            [
360 3
                self::PROPERTY_ID => $this->uid->getId(),
361 3
                self::PROPERTY_TYPE => $this->type->getType(),
362 3
                self::PROPERTY_REVISION => $draftRevision->getRevision(),
363 3
                self::PROPERTY_CREATED => time(),
364
            ],
365 3
            $this->object
366
        );
367
    }
368
369
    /**
370
     * Indicate that the object got published
371
     *
372
     * @return SystemProperties System properties
373
     * @throws RuntimeException If the object is already published
374
     */
375 2
    public function publish()
376
    {
377
        // If the object is already published
378 2
        if ($this->published instanceof \DateTimeImmutable) {
379 1
            throw new RuntimeException(
380 1
                'Cannot republish object previously published at '.$this->published->format('c'),
381 1
                RuntimeException::CANNOT_REPUBLISH_OBJECT
382
            );
383
        }
384
385 2
        $systemProperties = clone $this;
386 2
        $systemProperties->published = new \DateTimeImmutable();
387 2
        return $systemProperties;
388
    }
389
390
    /**
391
     * Return the property values as array
392
     *
393
     * @return array Property values
394
     */
395 5
    public function toArray()
396
    {
397 5
        return array_filter([
398 5
            self::PROPERTY_ID => $this->uid->getId(),
399 5
            self::PROPERTY_TYPE => $this->type->getType(),
400 5
            self::PROPERTY_REVISION => $this->revision->getRevision(),
401 5
            self::PROPERTY_CREATED => $this->created->format('c'),
402 5
            self::PROPERTY_PUBLISHED => ($this->published instanceof \DateTimeImmutable) ?
403 5
                $this->published->format('c') : null,
404 5
            self::PROPERTY_LOCATION => $this->location->toArray(),
405 5
            self::PROPERTY_HASH => $this->hash,
406
        ]);
407
    }
408
409
    /**
410
     * Test if the object hash is a valid sha1 value
411
     *
412
     * @return bool The object hash is a valid sha1 value
413
     */
414
    protected function hasValidHash()
415
    {
416
        return preg_match('%[a-fA-F0-9]{40}%', $this->hash);
417
    }
418
}
419