Model::__construct()   B
last analyzed

Complexity

Conditions 8
Paths 8

Size

Total Lines 33
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 20
c 0
b 0
f 0
dl 0
loc 33
rs 8.4444
cc 8
nc 8
nop 2
1
<?php
2
3
namespace Lifeboat\Models;
4
5
use Lifeboat\Connector;
6
use Lifeboat\Exceptions\InvalidArgumentException;
7
use Lifeboat\Factory\ClassMap;
8
use Lifeboat\Resource\ListResource;
9
use Lifeboat\Resource\ObjectResource;
10
use Lifeboat\Factory\ObjectFactory;
11
use Lifeboat\Services\ApiService;
12
use Lifeboat\Utils\ArrayLib;
13
use ErrorException;
14
15
/**
16
 * Class Model
17
 * @package Lifeboat\Models
18
 *
19
 * @property int $ID
20
 */
21
abstract class Model extends ObjectResource {
22
23
    public function __construct(Connector $client, array $_object_data = [])
24
    {
25
        if (!ArrayLib::is_associative($_object_data)) {
26
            throw new InvalidArgumentException("Model::__construct() expects an associative array");
27
        }
28
29
        parent::__construct($client, $_object_data);
30
31
        // Mutate objects if needs be
32
        foreach ($this->toArray() as $field => $value) {
33
            if (is_array($value)) {
34
                if (ArrayLib::is_associative($value)) {
35
                    // Model or Object
36
                    if (!array_key_exists('field_name', $value)) {
37
                        $this->$field = ObjectFactory::make($client, $value);
38
                    } else {
39
                        // Has One Relation - Deprecated
40
                        $name = $value['field_name'];
41
                        $this->$name    = $value['field_value'];
42
                        $this->$field   = ObjectFactory::make($client, $value['object_data']);
43
                    }
44
                } else {
45
                    // HasMany / ManyMany Relation
46
                    $list = [];
47
                    foreach ($value as $item) {
48
                        if (ArrayLib::is_associative($item)) {
49
                            $list[] = ObjectFactory::make($client, $item);
50
                        } else {
51
                            $list[] = $item;
52
                        }
53
                    }
54
55
                    $this->$field = $list;
56
                }
57
            }
58
        }
59
    }
60
61
    /**
62
     * @param bool $flatten
63
     * @return array
64
     */
65
    public function toArray(bool $flatten = false): array
66
    {
67
        if (!$flatten) return iterator_to_array($this->getIterator());
68
69
        $data = [];
70
71
        foreach ($this->getIterator() as $key => $value) {
72
            if ($value instanceof self)         $data[$key] = $value->toArray(true);
73
            else if ($value instanceof ListResource) {
74
                $data[$key] = [];
75
                /** @var self $item */
76
                foreach ($value as $item) $data[$key][] = $item->toArray(true);
77
            } else $data[$key] = $value;
78
        }
79
80
        return $data;
81
    }
82
83
    /**
84
     * @return bool
85
     */
86
    public function exists(): bool
87
    {
88
        return $this->ID > 0;
89
    }
90
91
    /**
92
     * @return ApiService
93
     * @throws ErrorException
94
     */
95
    public function getService(): ApiService
96
    {
97
        foreach (ClassMap::SERVICE_MODEL as $service => $model) {
98
            if ($model === static::class) return new $service($this->getClient());
99
        }
100
101
        throw new ErrorException("Could not determine which service to use for " . static::class);
102
    }
103
104
    /**
105
     * @return $this|null
106
     * @throws ErrorException
107
     */
108
    protected function save(): ?Model
109
    {
110
        $service = $this->getService();
111
112
        if ($this->exists()) {
113
            if (!method_exists($service, 'update')) return $this;
114
            return $service->update($this->ID, $this->toArray());
115
        } else {
116
            if (!method_exists($service, 'create')) return $this;
117
            return $service->create($this->toArray());
118
        }
119
    }
120
}
121