GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 08adc9...cc509a )
by James Ekow Abaka
18s queued 10s
created

DataOperations::isItemDeletable()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 6
1
<?php
2
3
/*
4
 * The MIT License
5
 *
6
 * Copyright 2014-2018 James Ekow Abaka Ainooson
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated documentation files (the "Software"), to deal
10
 * in the Software without restriction, including without limitation the rights
11
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
 * copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
 * THE SOFTWARE.
25
 */
26
27
namespace ntentan\nibii;
28
29
use ntentan\atiaa\Driver;
30
31
/**
32
 * Description of DataOperations.
33
 *
34
 * @author ekow
35
 */
36
class DataOperations
37
{
38
    /**
39
     * @var RecordWrapper
40
     */
41
    private $wrapper;
42
43
    /**
44
     * Private instance of driver adapter.
45
     *
46
     * @var DriverAdapter
47
     */
48
    private $adapter;
49
50
    /**
51
     * Copy of data to be manipulated in the operations.
52
     *
53
     * @var array
54
     */
55
    private $data;
56
57
    /**
58
     * Fields that contained errors after save or update operations were performed.
59
     *
60
     * @var array
61
     */
62
    private $invalidFields = [];
63
64
    /**
65
     * Set to true when the model holds multiple records.
66
     *
67
     * @var bool
68
     */
69
    private $hasMultipleData;
70
71
    /**
72
     * An instance of the atiaa driver.
73
     *
74
     * @var Driver
75
     */
76
    private $driver;
77
78
    /**
79
     * Used to indicate save operation is in save mode to create new items.
80
     */
81
    const MODE_SAVE = 0;
82
83
    /**
84
     * Used to indicate save operation is in update mode to update existing items.
85
     */
86
    const MODE_UPDATE = 1;
87
88
    /**
89
     * Create a new instance.
90
     *
91
     * @param \ntentan\nibii\RecordWrapper $wrapper
92
     * @param Driver                       $driver
93
     */
94 34
    public function __construct(RecordWrapper $wrapper, Driver $driver)
95
    {
96 34
        $this->wrapper = $wrapper;
97 34
        $this->adapter = $wrapper->getAdapter();
98 34
        $this->driver = $driver;
99 34
    }
100
101
    /**
102
     * Perform the model save command.
103
     *
104
     * @param bool $hasMultipleData
105
     *
106
     * @return bool
107
     */
108 10
    public function doSave(bool $hasMultipleData): bool
109
    {
110 10
        $this->hasMultipleData = $hasMultipleData;
111 10
        $invalidFields = [];
112 10
        $data = $this->wrapper->getData();
113
114 10
        $primaryKey = $this->wrapper->getDescription()->getPrimaryKey();
115 10
        $succesful = true;
116
117
        // Assign an empty array to force a validation error for empty models
118 10
        if (empty($data)) {
119 2
            $data = [[]];
120
        }
121
122 10
        $this->driver->beginTransaction();
123
124 10
        foreach ($data as $i => $datum) {
125 10
            $status = $this->saveRecord($datum, $primaryKey);
126 10
            $data[$i] = $datum;
127
128 10
            if (!$status['success']) {
129 4
                $succesful = false;
130 4
                $invalidFields[$i] = $status['invalid_fields'];
131 4
                $this->driver->rollback();
132 10
                break;
133
            }
134
        }
135
136 10
        if ($succesful) {
137 6
            $this->driver->commit();
138
        } else {
139 4
            $this->assignValue($this->invalidFields, $invalidFields);
140
        }
141
142 10
        $this->wrapper->setData($hasMultipleData ? $data : $data[0]);
143
144 10
        return $succesful;
145
    }
146
147
    /**
148
     * @return bool|array
149
     */
150
    public function doValidate()
151
    {
152
        $record = $this->wrapper->getData()[0];
153
        $primaryKey = $this->wrapper->getDescription()->getPrimaryKey();
154
        $pkSet = $this->isPrimaryKeySet($primaryKey, $record);
155
156
        return $this->validate($pkSet ? self::MODE_UPDATE : self::MODE_SAVE);
157
    }
158
159
    /**
160
     * Save an individual record.
161
     *
162
     * @param array $record     The record to be saved
163
     * @param array $primaryKey The primary keys of the record
164
     *
165
     * @return array
166
     */
167 10
    private function saveRecord(array &$record, array $primaryKey): array
168
    {
169
        $status = [
170 10
            'success'        => true,
171
            'pk_assigned'    => null,
172
            'invalid_fields' => [],
173
        ];
174
175
        // Determine if the primary key of the record is set.
176 10
        $pkSet = $this->isPrimaryKeySet($primaryKey, $record);
177
178
        // Reset the data in the model to contain only the data to be saved
179 10
        $this->wrapper->setData($record);
180
181
        // Execute all callbacks on the model
182 10
        $this->wrapper->preSaveCallback();
183 10
        if ($pkSet) {
184 2
            $this->wrapper->preUpdateCallback();
185
        } else {
186 8
            $this->wrapper->preCreateCallback();
187
        }
188
189
        // Validate the data
190 10
        $validity = $this->validate($pkSet ? self::MODE_UPDATE : self::MODE_SAVE);
191
192
        // Exit if data is invalid
193 10
        if ($validity !== true) {
194 4
            $status['invalid_fields'] = $validity;
195 4
            $status['success'] = false;
196
197 4
            return $status;
198
        }
199
200 6
        $record = $this->wrapper->getData();
201 6
        $record = reset($record) === false ? [] : reset($record);
202
203
        // Save any relationships that are attached to the data
204 6
        $relationships = $this->wrapper->getDescription()->getRelationships();
205 6
        $relationshipsWithData = [];
206
207 6
        foreach ($relationships ?? [] as $model => $relationship) {
208 6
            if (isset($record[$model])) {
209
                $relationship->preSave($record, $record[$model]);
210 6
                $relationshipsWithData[$model] = $relationship;
211
            }
212
        }
213
214
        // Assign the data to the wrapper again
215 6
        $this->wrapper->setData($record);
216
217
        // Update or save the data and run post callbacks
218 6
        if ($pkSet) {
219 2
            $this->adapter->update($record);
220 2
            $this->wrapper->postUpdateCallback();
221
        } else {
222 4
            $this->adapter->insert($record);
223 4
            $keyValue = $this->driver->getLastInsertId();
224 4
            $this->wrapper->{$primaryKey[0]} = $keyValue;
225 4
            $this->wrapper->postCreateCallback($keyValue);
226
        }
227 6
        $this->wrapper->postSaveCallback();
228
229
        // Reset the data so it contains any modifications made by callbacks
230 6
        $record = $this->wrapper->getData()[0];
231 6
        foreach ($relationshipsWithData as $model => $relationship) {
232
            $relationship->postSave($record);
233
        }
234
235 6
        return $status;
236
    }
237
238
    /**
239
     * @param int $mode
240
     *
241
     * @return bool|array
242
     */
243 10
    private function validate(int $mode)
244
    {
245 10
        $validator = ORMContext::getInstance()->getModelValidatorFactory()->createModelValidator($this->wrapper, $mode);
246 10
        $mainValidatorErrors = [];
247
248 10
        if (!$validator->validate($this->wrapper->toArray())) {
249 4
            $mainValidatorErrors = $validator->getInvalidFields();
250
        }
251 10
        $customValidatorErrors = $this->wrapper->validate();
252 10
        $errors = array_merge_recursive($mainValidatorErrors, $customValidatorErrors);
253
254 10
        return empty($errors) ? true : $errors;
255
    }
256
257
    /**
258
     * @param string|array $primaryKey
259
     * @param array        $data
260
     *
261
     * @return bool
262
     */
263 10
    private function isPrimaryKeySet($primaryKey, array $data) : bool
264
    {
265 10
        if (is_string($primaryKey) && ($data[$primaryKey] !== null || $data[$primaryKey] !== '')) {
266
            return true;
267
        }
268 10
        foreach ($primaryKey as $keyField) {
269 10
            if (!isset($data[$keyField]) || $data[$keyField] === null || $data[$keyField] === '') {
270 10
                return false;
271
            }
272
        }
273
274 2
        return true;
275
    }
276
277
    /**
278
     * @param mixed $property
279
     * @param mixed $value
280
     */
281 4
    private function assignValue(&$property, $value) : void
282
    {
283 4
        if ($this->hasMultipleData) {
284
            $property = $value;
285
        } else {
286 4
            $property = $value[0];
287
        }
288 4
    }
289
290
    /**
291
     * @return array
292
     */
293
    public function getData() : array
294
    {
295
        return $this->data;
296
    }
297
298
    /**
299
     * @return array
300
     */
301 10
    public function getInvalidFields() : array
302
    {
303 10
        return $this->invalidFields;
304
    }
305
306
    /**
307
     * @param string $primaryKey
308
     * @param array  $data
309
     *
310
     * @return bool
311
     */
312
    public function isItemDeletable(string $primaryKey, array $data) : bool
313
    {
314
        if ($this->isPrimaryKeySet($primaryKey, $data)) {
315
            return true;
316
        } else {
317
            return false;
318
        }
319
    }
320
}
321