Passed
Push — master ( ca91fe...3bc03f )
by Bruno
06:22
created

Model::getData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 1
eloc 1
c 1
b 1
f 1
nc 1
nop 0
dl 0
loc 3
rs 10
ccs 2
cts 2
cp 1
crap 1
1
<?php declare(strict_types=1);
2
3
namespace Formularium;
4
5
use Formularium\Exception\Exception;
6
7
/**
8
 * Model class, representing a whole object.
9
 */
10
class Model
11
{
12
    /**
13
     * @var string
14
     */
15
    protected $name;
16
17
    /**
18
     * @var Field[]
19
     */
20
    protected $fields;
21
22
23
    /**
24
     * Model data being processed.
25
     * @var array
26
     */
27
    protected $_data;
28
29
    /**
30
     *
31
     * @param string $name
32
     * @throws Exception
33
     */
34 8
    protected function __construct(string $name = '')
35
    {
36 8
        $this->name = $name;
37 8
    }
38
39
    /**
40
     * Loads model from JSON file.
41
     *
42
     * @param array $struct
43
     * @return Model
44
     */
45 4
    public static function fromStruct(array $struct): Model
46
    {
47 4
        $m = new self('');
48 4
        $m->parseStruct($struct);
49 4
        return $m;
50
    }
51
52
    /**
53
     * Loads model from JSON file.
54
     *
55
     * @param string $name The JSON filename.
56
     * @return Model
57
     */
58
    public static function fromJSONFile(string $name): Model
59
    {
60
        $json = file_get_contents($name); // TODO: path
61
        if ($json === false) {
62
            throw new Exception('File not found');
63
        }
64
        return static::fromJSON($json);
65
    }
66
67
    /**
68
     * Loads model from JSON string
69
     *
70
     * @param string $json The JSON string.
71
     * @return Model
72
     */
73 5
    public static function fromJSON(string $json): Model
74
    {
75 5
        $data = \json_decode($json, true);
76 5
        if ($data === null) {
77 1
            throw new Exception('Invalid JSON format');
78
        }
79 4
        $m = new self('');
80 4
        $m->parseStruct($data);
81 1
        return $m;
82
    }
83
84 1
    public function getName(): string
85
    {
86 1
        return $this->name;
87
    }
88
89 1
    public function getFields(): array
90
    {
91 1
        return $this->fields;
92
    }
93
94 2
    public function getData(): array
95
    {
96 2
        return $this->_data;
97
    }
98
99
    /**
100
     * Validates a set of data against this model.
101
     *
102
     * @param array $data A field name => data array.
103
     * @return array
104
     */
105 3
    public function validate(array $data): array
106
    {
107 3
        $this->_data = $data;
108 3
        $validate = [];
109 3
        $errors = [];
110 3
        foreach ($data as $name => $d) {
111 3
            if (!array_key_exists($name, $this->fields)) {
112
                $errors[$name] = "Field $name does not exist in this model";
113
                continue;
114
            }
115 3
            $field = $this->fields[$name];
116
            try {
117 3
                $validate[$name] = $field->getDatatype()->validate($d, $field, $this);
118 2
            } catch (Exception $e) {
119 3
                $errors[$name] = $e->getMessage();
120
            }
121
        }
122 3
        foreach ($this->fields as $name => $field) {
123 3
            if (($field->getValidators()[Datatype::REQUIRED] ?? false)
124 3
                && !array_key_exists($name, $validate)
125 3
                && !array_key_exists($name, $errors)
126
            ) {
127 3
                $errors[$name] = "Field $name is missing";
128
            }
129
        }
130 3
        $this->_data = [];
131 3
        return ['validated' => $validate, 'errors' => $errors];
132
    }
133
134
    /**
135
     * Serializes this model to JSON.
136
     *
137
     * @return array
138
     */
139
    public function serialize(): array
140
    {
141
        $fields = array_map(
142
            function ($f) {
143
                return [
144
                    'datatype' => $f->getDatatype()->getName(),
145
                    'validators' => $f->getValidators(),
146
                    'extensions' => $f->getExtensions()
147
                ];
148
            },
149
            $this->fields
150
        );
151
        $model = [
152
            'name' => $this->name,
153
            'fields' => $fields
154
        ];
155
        return $model;
156
    }
157
158
    public function toJSON(): string
159
    {
160
        $t = json_encode($this->serialize());
161
        if (!$t) {
162
            throw new Exception('Cannot serialize');
163
        }
164
        return $t;
165
    }
166
167
    /**
168
     * Renders a readonly view of the model with given data.
169
     *
170
     * @param array $modelData
171
     * @return string
172
     */
173
    public function viewable(array $modelData): string
174
    {
175
        return FrameworkComposer::viewable($this, $modelData);
176
    }
177
178
    /**
179
     * Renders a form view of the model with given data.
180
     *
181
     * @param array $modelData
182
     * @return string
183
     */
184
    public function editable(array $modelData = []): string
185
    {
186
        return FrameworkComposer::editable($this, $modelData);
187
    }
188
189 1
    public function getRandom(): array
190
    {
191 1
        $data = [];
192 1
        foreach ($this->fields as $f) {
193 1
            $data[$f->getName()] = $f->getDatatype()->getRandom();
194
        }
195 1
        return $data;
196
    }
197
198
    /**
199
     * Returns an array with the default values of each field
200
     *
201
     * @return array Field name => value
202
     */
203
    public function getDefault(): array
204
    {
205
        $data = [];
206
        foreach ($this->fields as $f) {
207
            $data[$f->getName()] = $f->getDatatype()->getDefault();
208
        }
209
        return $data;
210
    }
211
212
    /**
213
     * Parses struct
214
     *
215
     * @param array $data
216
     * @throws Exception
217
     * @return void
218
     */
219 8
    protected function parseStruct(array $data)
220
    {
221 8
        if (!array_key_exists('name', $data)) {
222 1
            throw new Exception('Missing name in model');
223
        }
224 7
        if (!array_key_exists('fields', $data)) {
225 1
            throw new Exception('Missing fields in model');
226
        }
227 6
        $this->name = $data['name'];
228 6
        foreach ($data['fields'] as $fieldName => $fieldData) {
229 6
            $this->fields[$fieldName] = Field::getFromData($fieldName, $fieldData);
230
        }
231 5
    }
232
}
233