Completed
Push — master ( 5874e2...48c27a )
by Joschi
03:10
created

SystemProperties::getLanguage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 2
c 1
b 0
f 1
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 2
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
     * Language property
95
     *
96
     * @var string
97
     */
98
    const PROPERTY_LANGUAGE = 'language';
99
    /**
100
     * Location property
101
     *
102
     * @var string
103
     */
104
    const PROPERTY_LOCATION = 'location';
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 27
     * Language (BCP 47 compliant)
143
     *
144 27
     * @var string
145
     * @see https://tools.ietf.org/html/bcp47
146
     */
147 27
    protected $language = null;
148 25
149
    /**
150
     * System properties constructor
151
     *
152 27
     * @param array $data Property data
153 26
     * @param ObjectInterface $object Owner object
154
     */
155
    public function __construct(array $data, ObjectInterface $object)
156
    {
157 26
        parent::__construct($data, $object);
158 25
159
        // Initialize the object ID
160
        if (array_key_exists(self::PROPERTY_ID, $data)) {
161
            $this->uid = Id::unserialize($data[self::PROPERTY_ID]);
162 26
        }
163 25
164
        // Initialize the object type
165
        if (array_key_exists(self::PROPERTY_TYPE, $data)) {
166
            $this->type = Type::unserialize($data[self::PROPERTY_TYPE]);
167 26
        }
168 20
169
        // Initialize the object revision
170
        if (array_key_exists(self::PROPERTY_REVISION, $data)) {
171
            $this->revision = Revision::unserialize($data[self::PROPERTY_REVISION]);
172 26
        }
173 26
174 26
        // Initialize the object creation date
175
        if (array_key_exists(self::PROPERTY_CREATED, $data)) {
176
            $this->created = new \DateTimeImmutable('@'.$data[self::PROPERTY_CREATED]);
177
        }
178 26
179 25
        // Initialize the object publication date
180 25
        if (array_key_exists(self::PROPERTY_PUBLISHED, $data)) {
181 26
            $this->published = new \DateTimeImmutable('@'.$data[self::PROPERTY_PUBLISHED]);
182
        }
183 1
184 1
        // Initialize the object language
185 1
        if (array_key_exists(self::PROPERTY_LANGUAGE, $data)) {
186
            $this->language = trim($data[self::PROPERTY_LANGUAGE]);
187
        }
188 25
189
        // Initialize the location
190
        $this->location = Kernel::create(
191
            LocationProperties::class,
192
            [empty($data[self::PROPERTY_LOCATION]) ? [] : $data[self::PROPERTY_LOCATION], $this->object]
193
        );
194
195 5
        // Test if all mandatory properties are set
196
        if (!($this->uid instanceof Id)
197 5
            || !($this->type instanceof Type)
198
            || !($this->revision instanceof Revision)
199
            || !($this->created instanceof \DateTimeImmutable)
200
            || !strlen($this->language)
201
        ) {
202
            throw new InvalidArgumentException(
203
                'Invalid system properties',
204
                InvalidArgumentException::INVALID_SYSTEM_PROPERTIES
205 1
            );
206
        }
207 1
    }
208
209
    /**
210
     * Return the object ID
211
     *
212
     * @return Id Object ID
213
     */
214
    public function getId()
215 24
    {
216
        return $this->uid;
217 24
    }
218
219
    /**
220
     * Return the object type
221
     *
222
     * @return Type Object type
223
     */
224
    public function getType()
225 5
    {
226
        return $this->type;
227 5
    }
228
229
    /**
230
     * Return the object revision
231
     *
232
     * @return Revision Object revision
233
     */
234
    public function getRevision()
235 1
    {
236
        return $this->revision;
237 1
    }
238
239
    /**
240
     * Return the object draft mode
241
     *
242
     * @return boolean Object draft mode
243
     */
244
    public function isDraft()
245 1
    {
246
        return !($this->published instanceof \DateTimeImmutable);
247 1
    }
248
249
    /**
250
     * Return the creation date & time of this revision
251
     *
252
     * @return \DateTimeImmutable Creation date & time
253
     */
254
    public function getCreated()
255 1
    {
256
        return $this->created;
257 1
    }
258
259
    /**
260
     * Return the publication date & time of this revision
261
     *
262
     * @return \DateTimeImmutable|null Publication date & time
263
     */
264
    public function getPublished()
265
    {
266 1
        return $this->published;
267
    }
268 1
269 1
    /**
270 1
     * Return the object language
271
     *
272
     * @return string
273
     */
274
    public function getLanguage()
275
    {
276
        return $this->language;
277
    }
278
279 1
    /**
280
     * Return the latitude
281 1
     *
282
     * @return float Latitude
283
     */
284
    public function getLatitude()
285
    {
286
        return $this->location->getLatitude();
287
    }
288
289
    /**
290 1
     * Set the latitude
291
     *
292 1
     * @param float $latitude Latitude
293 1
     * @return SystemProperties Self reference
294 1
     */
295
    public function setLatitude($latitude)
296
    {
297
        return $this->mutatePropertiesProperty(
298
            self::PROPERTY_LOCATION,
299
            $this->location->setLatitude($latitude)
300
        );
301
    }
302
303 1
    /**
304
     * Return the longitude
305 1
     *
306
     * @return float Longitude
307
     */
308
    public function getLongitude()
309
    {
310
        return $this->location->getLongitude();
311
    }
312
313
    /**
314 1
     * Set the longitude
315
     *
316 1
     * @param float $longitude Longitude
317 1
     * @return SystemProperties Self reference
318 1
     */
319
    public function setLongitude($longitude)
320
    {
321
        return $this->mutatePropertiesProperty(
322
            self::PROPERTY_LOCATION,
323
            $this->location->setLongitude($longitude)
324
        );
325
    }
326
327
    /**
328 4
     * Return the elevation
329
     *
330 4
     * @return float Elevation
331
     */
332 4
    public function getElevation()
333 4
    {
334 4
        return $this->location->getElevation();
335 4
    }
336
337 4
    /**
338
     * Set the elevation
339
     *
340
     * @param float $elevation
341
     * @return SystemProperties Self reference
342
     */
343
    public function setElevation($elevation)
344
    {
345
        return $this->mutatePropertiesProperty(
346
            self::PROPERTY_LOCATION,
347 2
            $this->location->setElevation($elevation)
348
        );
349
    }
350 2
351 1
    /**
352 1
     * Derive draft system properties
353 1
     *
354
     * @param Revision $draftRevision Draft revision
355
     * @return SystemProperties Draft system properties
356
     */
357 2
    public function createDraft(Revision $draftRevision)
358 2
    {
359 2
        return new static(
360
            [
361
                self::PROPERTY_ID => $this->uid->getId(),
362
                self::PROPERTY_TYPE => $this->type->getType(),
363
                self::PROPERTY_REVISION => $draftRevision->getRevision(),
364
                self::PROPERTY_CREATED => time(),
365
                self::PROPERTY_LANGUAGE => $this->language,
366
            ],
367 5
            $this->object
368
        );
369 5
    }
370 5
371 5
    /**
372 5
     * Indicate that the object got published
373 5
     *
374 5
     * @return SystemProperties System properties
375 5
     * @throws RuntimeException If the object is already published
376 5
     */
377
    public function publish()
378
    {
379
        // If the object is already published
380
        if ($this->published instanceof \DateTimeImmutable) {
381
            throw new RuntimeException(
382
                'Cannot republish object previously published at '.$this->published->format('c'),
383
                RuntimeException::CANNOT_REPUBLISH_OBJECT
384
            );
385
        }
386
387
        $systemProperties = clone $this;
388
        $systemProperties->published = new \DateTimeImmutable();
389
        return $systemProperties;
390
    }
391
392
    /**
393
     * Return the property values as array
394
     *
395
     * @return array Property values
396
     */
397
    public function toArray()
398
    {
399
        return array_filter([
400
            self::PROPERTY_ID => $this->uid->getId(),
401
            self::PROPERTY_TYPE => $this->type->getType(),
402
            self::PROPERTY_REVISION => $this->revision->getRevision(),
403
            self::PROPERTY_CREATED => $this->created->format('c'),
404
            self::PROPERTY_PUBLISHED => ($this->published instanceof \DateTimeImmutable) ?
405
                $this->published->format('c') : null,
406
            self::PROPERTY_LOCATION => $this->location->toArray(),
407
        ]);
408
    }
409
}
410