Passed
Push — master ( d10e42...360ee2 )
by Bao
02:17
created

DynamoDbModel::saveAsync()   B

Complexity

Conditions 9
Paths 5

Size

Total Lines 33
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 9.3752

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 33
ccs 15
cts 18
cp 0.8333
rs 8.0555
c 0
b 0
f 0
cc 9
nc 5
nop 1
crap 9.3752
1
<?php
2
3
namespace BaoPham\DynamoDb;
4
5
use Exception;
6
use DateTime;
7
use Illuminate\Database\Eloquent\Model;
8
9
/**
10
 * Class DynamoDbModel.
11
 */
12
abstract class DynamoDbModel extends Model
13
{
14
    /**
15
     * Always set this to false since DynamoDb does not support incremental Id.
16
     *
17
     * @var bool
18
     */
19
    public $incrementing = false;
20
21
    /**
22
     * @var \BaoPham\DynamoDb\DynamoDbClientInterface
23
     */
24
    protected static $dynamoDb;
25
26
    /**
27
     * @deprecated
28
     * @var \Aws\DynamoDb\Marshaler
29
     */
30
    protected $marshaler;
31
32
    /**
33
     * @deprecated
34
     * @var \BaoPham\DynamoDb\EmptyAttributeFilter
35
     */
36
    protected $attributeFilter;
37
38
    /**
39
     * Indexes.
40
     *   [
41
     *     '<simple_index_name>' => [
42
     *          'hash' => '<index_key>'
43
     *     ],
44
     *     '<composite_index_name>' => [
45
     *          'hash' => '<index_hash_key>',
46
     *          'range' => '<index_range_key>'
47
     *     ],
48
     *   ]
49
     *
50
     * @var array
51
     */
52
    protected $dynamoDbIndexKeys = [];
53
54
    /**
55
     * Array of your composite key.
56
     * ['<hash>', '<range>']
57
     *
58
     * @var array
59
     */
60
    protected $compositeKey = [];
61
62
    /**
63
     * Default Date format
64
     * ISO 8601 Compliant
65
     */
66
    protected $dateFormat = DateTime::ATOM;
67
68
69 127
    public function __construct(array $attributes = [])
70
    {
71 127
        $this->bootIfNotBooted();
72
73 127
        $this->syncOriginal();
74
75 127
        $this->fill($attributes);
76
77 127
        $this->setupDynamoDb();
78 127
    }
79
80
    /**
81
     * Get the DynamoDbClient service that is being used by the models.
82
     *
83
     * @return DynamoDbClientInterface
84
     */
85 3
    public static function getDynamoDbClientService()
86
    {
87 3
        return static::$dynamoDb;
88
    }
89
90
    /**
91
     * Set the DynamoDbClient used by models.
92
     *
93
     * @param DynamoDbClientInterface $dynamoDb
94
     *
95
     * @return void
96
     */
97 142
    public static function setDynamoDbClientService(DynamoDbClientInterface $dynamoDb)
98
    {
99 142
        static::$dynamoDb = $dynamoDb;
100 142
    }
101
102
    /**
103
     * Unset the DynamoDbClient service for models.
104
     *
105
     * @return void
106
     */
107 3
    public static function unsetDynamoDbClientService()
108
    {
109 3
        static::$dynamoDb = null;
110 3
    }
111
112 127
    protected function setupDynamoDb()
113
    {
114 127
        $this->marshaler = static::$dynamoDb->getMarshaler();
115 127
        $this->attributeFilter = static::$dynamoDb->getAttributeFilter();
116 127
    }
117
118 90
    public function newCollection(array $models = [], $index = null)
119
    {
120 90
        return new DynamoDbCollection($models, $index);
121
    }
122
123 8
    public function save(array $options = [])
124
    {
125 8
        $create = !$this->exists;
126
127 8
        if ($this->fireModelEvent('saving') === false) {
128
            return false;
129
        }
130
131 8
        if ($create && $this->fireModelEvent('creating')  === false) {
132
            return false;
133
        }
134
135 8
        if (!$create && $this->fireModelEvent('updating') === false) {
136
            return false;
137
        }
138
139 8
        if ($this->usesTimestamps()) {
140 8
            $this->updateTimestamps();
141
        }
142
143 8
        $saved = $this->newQuery()->save();
144
145 8
        if (!$saved) {
146
            return $saved;
147
        }
148
149 8
        $this->exists = true;
150 8
        $this->wasRecentlyCreated = $create;
151 8
        $this->fireModelEvent($create ? 'created' : 'updated', false);
152
153 8
        $this->finishSave($options);
154
155 8
        return $saved;
156
    }
157
158
    /**
159
     * Saves the model to DynamoDb asynchronously and returns a promise
160
     * @param array $options
161
     * @return bool|\GuzzleHttp\Promise\Promise
162
     */
163 6
    public function saveAsync(array $options = [])
164
    {
165 6
        $create = !$this->exists;
166
167 6
        if ($this->fireModelEvent('saving') === false) {
168
            return false;
169
        }
170
171 6
        if ($create && $this->fireModelEvent('creating')  === false) {
172
            return false;
173
        }
174
175 6
        if (!$create && $this->fireModelEvent('updating') === false) {
176
            return false;
177
        }
178
179 6
        if ($this->usesTimestamps()) {
180 6
            $this->updateTimestamps();
181
        }
182
183 6
        $savePromise = $this->newQuery()->saveAsync();
184
185
        $savePromise->then(function ($result) use ($create, $options) {
186 6
            if (array_get($result, '@metadata.statusCode') === 200) {
187 6
                $this->exists = true;
188 6
                $this->wasRecentlyCreated = $create;
189 6
                $this->fireModelEvent($create ? 'created' : 'updated', false);
190
191 6
                $this->finishSave($options);
192
            }
193 6
        });
194
195 6
        return $savePromise;
196
    }
197
198 3
    public function update(array $attributes = [], array $options = [])
199
    {
200 3
        return $this->fill($attributes)->save();
201
    }
202
203 2
    public function updateAsync(array $attributes = [], array $options = [])
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

203
    public function updateAsync(array $attributes = [], /** @scrutinizer ignore-unused */ array $options = [])

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
204
    {
205 2
        return $this->fill($attributes)->saveAsync();
206
    }
207
208
    public static function create(array $attributes = [])
209
    {
210
        $model = new static;
211
212
        $model->fill($attributes)->save();
213
214
        return $model;
215
    }
216
217 2
    public function delete()
218
    {
219 2
        if (is_null($this->getKeyName())) {
0 ignored issues
show
introduced by
The condition is_null($this->getKeyName()) is always false.
Loading history...
220
            throw new Exception('No primary key defined on model.');
221
        }
222
223 2
        if ($this->exists) {
224 2
            if ($this->fireModelEvent('deleting') === false) {
225
                return false;
226
            }
227
228 2
            $this->exists = false;
229
230 2
            $success = $this->newQuery()->delete();
231
232 2
            if ($success) {
233 2
                $this->fireModelEvent('deleted', false);
234
            }
235
236 2
            return $success;
237
        }
238
    }
239
240 2
    public function deleteAsync()
241
    {
242 2
        if (is_null($this->getKeyName())) {
243
            throw new Exception('No primary key defined on model.');
244
        }
245
246 2
        if ($this->exists) {
247 2
            if ($this->fireModelEvent('deleting') === false) {
248
                return false;
249
            }
250
251 2
            $this->exists = false;
252
253 2
            $deletePromise = $this->newQuery()->deleteAsync();
254
255
            $deletePromise->then(function () {
256 2
                $this->fireModelEvent('deleted', false);
257 2
            });
258
259 2
            return $deletePromise;
260
        }
261
    }
262
263 7
    public static function all($columns = [])
264
    {
265 7
        $instance = new static;
266
267 7
        return $instance->newQuery()->get($columns);
268
    }
269
270 2
    public function refresh()
271
    {
272 2
        if (! $this->exists) {
273
            return $this;
274
        }
275
276 2
        $query = $this->newQuery();
277
278 2
        $refreshed = $query->find($this->getKeys());
279
280 2
        $this->setRawAttributes($refreshed->toArray());
281
282 2
        return $this;
283
    }
284
285
    /**
286
     * @return DynamoDbQueryBuilder
287
     */
288 127
    public function newQuery()
289
    {
290 127
        $builder = new DynamoDbQueryBuilder($this);
291
292 127
        foreach ($this->getGlobalScopes() as $identifier => $scope) {
293 7
            $builder->withGlobalScope($identifier, $scope);
294
        }
295
296 127
        return $builder;
297
    }
298
299 110
    public function hasCompositeKey()
300
    {
301 110
        return !empty($this->compositeKey);
302
    }
303
304
    /**
305
     * @deprecated
306
     * @param $item
307
     * @return array
308
     */
309
    public function marshalItem($item)
310
    {
311
        return $this->marshaler->marshalItem($item);
312
    }
313
314
    /**
315
     * @deprecated
316
     * @param $value
317
     * @return array
318
     */
319
    public function marshalValue($value)
320
    {
321
        return $this->marshaler->marshalValue($value);
322
    }
323
324
    /**
325
     * @deprecated
326
     * @param $item
327
     * @return array|\stdClass
328
     */
329
    public function unmarshalItem($item)
330
    {
331
        return $this->marshaler->unmarshalItem($item);
332
    }
333
334 36
    public function setId($id)
335
    {
336 36
        if (!is_array($id)) {
337 14
            $this->setAttribute($this->getKeyName(), $id);
338
339 14
            return $this;
340
        }
341
342 24
        foreach ($id as $keyName => $value) {
343 24
            $this->setAttribute($keyName, $value);
344
        }
345
346 24
        return $this;
347
    }
348
349
    /**
350
     * @return \Aws\DynamoDb\DynamoDbClient
351
     */
352 127
    public function getClient()
353
    {
354 127
        return static::$dynamoDb->getClient($this->connection);
355
    }
356
357
    /**
358
     * Get the value of the model's primary key.
359
     *
360
     * @return mixed
361
     */
362
    public function getKey()
363
    {
364
        return $this->getAttribute($this->getKeyName());
365
    }
366
367
    /**
368
     * Get the value of the model's primary / composite key.
369
     * Use this if you always want the key values in associative array form.
370
     *
371
     * @return array
372
     *
373
     * ['id' => 'foo']
374
     *
375
     * or
376
     *
377
     * ['id' => 'foo', 'id2' => 'bar']
378
     */
379 46
    public function getKeys()
380
    {
381 46
        if ($this->hasCompositeKey()) {
382 22
            $key = [];
383
384 22
            foreach ($this->compositeKey as $name) {
385 22
                $key[$name] = $this->getAttribute($name);
386
            }
387
388 22
            return $key;
389
        }
390
391 24
        $name = $this->getKeyName();
392
393 24
        return [$name => $this->getAttribute($name)];
394
    }
395
396
    /**
397
     * Get the primary key for the model.
398
     *
399
     * @return string
400
     */
401 28
    public function getKeyName()
402
    {
403 28
        return $this->primaryKey;
404
    }
405
406
    /**
407
     * Get the primary/composite key for the model.
408
     *
409
     * @return array
410
     */
411 104
    public function getKeyNames()
412
    {
413 104
        return $this->hasCompositeKey() ? $this->compositeKey : [$this->primaryKey];
414
    }
415
416
    /**
417
     * @return array
418
     */
419 70
    public function getDynamoDbIndexKeys()
420
    {
421 70
        return $this->dynamoDbIndexKeys;
422
    }
423
424
    /**
425
     * @param array $dynamoDbIndexKeys
426
     */
427
    public function setDynamoDbIndexKeys($dynamoDbIndexKeys)
428
    {
429
        $this->dynamoDbIndexKeys = $dynamoDbIndexKeys;
430
    }
431
432
    /**
433
     * @deprecated
434
     * @return \Aws\DynamoDb\Marshaler
435
     */
436
    public function getMarshaler()
437
    {
438
        return $this->marshaler;
439
    }
440
441
    /**
442
     * Remove non-serializable properties when serializing.
443
     *
444
     * @return array
445
     */
446 2
    public function __sleep()
447
    {
448 2
        return array_keys(
449 2
            array_except(get_object_vars($this), ['marshaler', 'attributeFilter'])
450
        );
451
    }
452
453
    /**
454
     * When a model is being unserialized, check if it needs to be booted and setup DynamoDB.
455
     *
456
     * @return void
457
     */
458 2
    public function __wakeup()
459
    {
460 2
        parent::__wakeup();
461 2
        $this->setupDynamoDb();
462 2
    }
463
}
464