Passed
Pull Request — develop (#82)
by Csaba
02:33
created

Resource::get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 7
c 0
b 0
f 0
ccs 0
cts 4
cp 0
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
crap 6
1
<?php
2
namespace Fathomminds\Rest\Database\DynamoDb;
3
4
use Aws\Sdk;
5
use Aws\DynamoDb\DynamoDbClient as Client;
6
use Fathomminds\Rest\Exceptions\RestException;
7
use Fathomminds\Rest\Contracts\IResource;
8
use Fathomminds\Rest\Helpers\Uuid;
9
use Aws\DynamoDb\Exception\DynamoDbException;
10
use Fathomminds\Rest\Database\DynamoDb\QueryConstructor;
11
12
class Resource implements IResource
13
{
14
    protected $client;
15
    protected $databaseName;
16
    protected $collection;
17
    protected $fullTableName;
18
    protected $resourceName;
19
    protected $primaryKey;
20
    protected $queryConstructor;
21
22
    public function __construct($resourceName, $primaryKey, Client $client = null, $databaseName = null)
23
    {
24
        $this->resourceName = $resourceName;
25
        $this->primaryKey = $primaryKey;
26
        $this->client = $client === null ? $this->createClient() : $client;
27
        $this->databaseName = $databaseName === null ? $this->getFullDatabaseName() : $databaseName;
28
        $this->fullTableName = $this->databaseName . '-' . $this->resourceName;
29
        $this->queryConstructor = new QueryConstructor;
30
    }
31
32
    private function createClient()
33
    {
34
        $sdk = new Sdk([
35
            'region'   => getenv('AWS_SDK_REGION'),
36
            'version'  => getenv('AWS_SDK_VERSION'),
37
            'http' => [
38
                'verify' => getenv('AWS_SDK_HTTP_VERIFY') === 'false' ? false : getenv('AWS_SDK_HTTP_VERIFY'),
39
            ]
40
        ]);
41
        return $sdk->createDynamoDb();
42
    }
43
44
    private function getFullDatabaseName()
45
    {
46
        return getenv('AWS_DYNAMODB_NAMESPACE') . '-' . getenv('AWS_DYNAMODB_DATABASE');
47
    }
48
49
    public function get($resourceId = null)
50
    {
51
        if ($resourceId !== null) {
52
            return $this->getOne($resourceId);
53
        }
54
        return $this->getAll();
55
    }
56
57
    protected function getOne($resourceId)
58
    {
59
        $query = $this->queryConstructor->createGetQuery($this->fullTableName, $this->primaryKey, $resourceId);
60
        $res = $this->client->getItem($query);
61
        return $this->queryConstructor->unmarshalItem($res['Item']);
62
    }
63
64
    protected function getAll()
65
    {
66
        $query = $this->queryConstructor->createScanQuery($this->fullTableName);
67
        $res = $this->client->scan($query);
68
        return $this->queryConstructor->unmarshalBatch($res['Items']);
69
    }
70
71
    protected function throwAwsPostError($exception)
72
    {
73
        switch ($exception->getAwsErrorCode()) {
74
            case 'ConditionalCheckFailedException':
75
                throw new RestException(
76
                    'Primary key collision',
77
                    ['exception' => $exception]
78
                );
79
        }
80
        throw new RestException($exception->getMessage(), ['exception' => $exception]);
81
    }
82
83
    public function post($newResource)
84
    {
85
        try {
86
            $query = $this->queryConstructor->createPostQuery($this->fullTableName, $this->primaryKey, $newResource);
87
            $this->client->putItem($query);
88
        } catch (DynamoDbException $ex) {
89
            $this->throwAwsPostError($ex);
90
        } catch (\Exception $ex) {
91
            throw new RestException($ex->getMessage(), ['exception' => $ex]);
92
        }
93
        return $newResource;
94
    }
95
96
    protected function throwAwsPutError($exception)
97
    {
98
        switch ($exception->getAwsErrorCode()) {
99
            case 'ConditionalCheckFailedException':
100
                throw new RestException(
101
                    'Resource does not exist',
102
                    ['exception' => $exception]
103
                );
104
        }
105
        throw new RestException($exception->getMessage(), ['exception' => $exception]);
106
    }
107
108
    public function patch($resourceId, $newResource)
109
    {
110
        return $this->put($resourceId, $newResource);
111
    }
112
113
    public function put($resourceId, $newResource)
114
    {
115
        try {
116
            $newResource->{$this->primaryKey} = $resourceId;
117
            $query = $this->queryConstructor->createPutQuery($this->fullTableName, $this->primaryKey, $newResource);
118
            $res = $this->client->putItem($query);
119
        } catch (DynamoDbException $ex) {
120
            $this->throwAwsPutError($ex);
121
        } catch (\Exception $ex) {
122
            throw new RestException($ex->getMessage(), ['result'=>empty($res) ? null : $res]);
123
        }
124
        return $newResource;
125
    }
126
127
    public function delete($resourceId)
128
    {
129
        try {
130
            $query = $this->queryConstructor->createDeleteQuery($this->fullTableName, $this->primaryKey, $resourceId);
131
            $res = $this->client->deleteItem($query);
132
            return $resourceId;
133
        } catch (\Exception $ex) {
134
            throw new RestException($ex->getMessage(), ['result'=>empty($res) ? null : $res]);
135
        }
136
    }
137
}
138