Passed
Branch develop (ae1154)
by Csaba
02:58
created

Resource   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 194
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 35
c 4
b 0
f 0
lcom 1
cbo 4
dl 0
loc 194
ccs 101
cts 101
cp 1
rs 9

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 3
A createClient() 0 11 2
A getFullDatabaseName() 0 4 1
A get() 0 7 2
A getOne() 0 6 1
A createGetQuery() 0 8 1
A getAll() 0 6 1
A createScanQuery() 0 7 1
A post() 0 12 3
A createPostQuery() 0 10 1
A put() 0 13 4
A createPutQuery() 0 10 1
A delete() 0 10 3
A createDeleteQuery() 0 8 1
A marshalItem() 0 4 1
A throwAwsPostError() 0 11 2
A throwAwsPutError() 0 11 2
A unmarshalItem() 0 7 2
A unmarshalBatch() 0 11 3
1
<?php
2
namespace Fathomminds\Rest\Database\DynamoDb;
3
4
use Aws\Sdk;
5
use Aws\DynamoDb\DynamoDbClient as Client;
6
use Aws\DynamoDb\Marshaler;
7
use Fathomminds\Rest\Exceptions\RestException;
8
use Fathomminds\Rest\Contracts\IResource;
9
use Fathomminds\Rest\Helpers\Uuid;
10
use Aws\DynamoDb\Exception\DynamoDbException;
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 $marshaler;
21
22 19
    public function __construct($resourceName, $primaryKey, Client $client = null, $databaseName = null)
23
    {
24 19
        $this->resourceName = $resourceName;
25 19
        $this->primaryKey = $primaryKey;
26 19
        $this->client = $client === null ? $this->createClient() : $client;
27 19
        $this->databaseName = $databaseName === null ? $this->getFullDatabaseName() : $databaseName;
28 19
        $this->fullTableName = $this->databaseName . '-' . $this->resourceName;
29 19
        $this->marshaler = new Marshaler;
30 19
    }
31
32 1
    private function createClient()
33
    {
34 1
        $sdk = new Sdk([
35 1
            'region'   => getenv('AWS_SDK_REGION'),
36 1
            'version'  => getenv('AWS_SDK_VERSION'),
37
            'http' => [
38 1
                'verify' => getenv('AWS_SDK_HTTP_VERIFY') === 'false' ? false : getenv('AWS_SDK_HTTP_VERIFY'),
39
            ]
40
        ]);
41 1
        return $sdk->createDynamoDb();
42
    }
43
44 1
    private function getFullDatabaseName()
45
    {
46 1
        return getenv('AWS_DYNAMODB_NAMESPACE') . '-' . getenv('AWS_DYNAMODB_DATABASE');
47
    }
48
49 2
    public function get($resourceId = null)
50
    {
51 2
        if ($resourceId !== null) {
52 1
            return $this->getOne($resourceId);
53
        }
54 1
        return $this->getAll();
55
    }
56
57 1
    protected function getOne($resourceId)
58
    {
59 1
        $query = $this->createGetQuery($resourceId);
60 1
        $res = $this->client->getItem($query);
61 1
        return $this->unmarshalItem($res['Item']);
62
    }
63
64 1
    protected function createGetQuery($resourceId)
65
    {
66
        $query = [
67 1
            'TableName' => $this->fullTableName,
68 1
            'Key' => $this->marshalItem([$this->primaryKey => $resourceId]),
69
        ];
70 1
        return $query;
71
    }
72
73 1
    protected function getAll()
74
    {
75 1
        $query = $this->createScanQuery();
76 1
        $res = $this->client->scan($query);
77 1
        return $this->unmarshalBatch($res['Items']);
78
    }
79
80 1
    protected function createScanQuery()
81
    {
82
        $query = [
83 1
            'TableName' => $this->fullTableName,
84
        ];
85 1
        return $query;
86
    }
87
88 2
    protected function throwAwsPostError($exception)
89
    {
90 2
        switch ($exception->getAwsErrorCode()) {
91 2
            case 'ConditionalCheckFailedException':
92 1
                throw new RestException(
93 1
                    'Primary key collision',
94 1
                    ['exception' => $exception]
95
                );
96
        }
97 1
        throw new RestException($exception->getMessage(), ['exception' => $exception]);
98
    }
99
100 6
    public function post($newResource)
101
    {
102
        try {
103 6
            $query = $this->createPostQuery($newResource);
104 6
            $this->client->putItem($query);
105 4
        } catch (DynamoDbException $ex) {
106 2
            $this->throwAwsPostError($ex);
107 2
        } catch (\Exception $ex) {
108 2
            throw new RestException($ex->getMessage(), ['exception' => $ex]);
109
        }
110 2
        return $newResource;
111
    }
112
113 6
    protected function createPostQuery($newResource)
114
    {
115
        $query = [
116 6
            'TableName' => $this->fullTableName,
117 6
            'Item' => $this->marshalItem($newResource),
118 6
            'ConditionExpression' => 'attribute_not_exists(#pk)',
119 6
            "ExpressionAttributeNames" => ["#pk" => $this->primaryKey],
120
        ];
121 6
        return $query;
122
    }
123
124 2
    protected function throwAwsPutError($exception)
125
    {
126 2
        switch ($exception->getAwsErrorCode()) {
127 2
            case 'ConditionalCheckFailedException':
128 1
                throw new RestException(
129 1
                    'Resource does not exist',
130 1
                    ['exception' => $exception]
131
                );
132
        }
133 1
        throw new RestException($exception->getMessage(), ['exception' => $exception]);
134
    }
135
136 5
    public function put($resourceId, $newResource)
137
    {
138
        try {
139 5
            $newResource->{$this->primaryKey} = $resourceId;
140 5
            $query = $this->createPutQuery($newResource);
141 5
            $res = $this->client->putItem($query);
142 3
        } catch (DynamoDbException $ex) {
143 2
            $this->throwAwsPutError($ex);
144 1
        } catch (\Exception $ex) {
145 1
            throw new RestException($ex->getMessage(), ['result'=>empty($res)?null:$res]);
146
        }
147 2
        return $newResource;
148
    }
149
150 5
    protected function createPutQuery($newResource)
151
    {
152
        $query = [
153 5
            'TableName' => $this->fullTableName,
154 5
            'Item' => $this->marshalItem($newResource),
155 5
            'ConditionExpression' => 'attribute_exists(#pk)',
156 5
            "ExpressionAttributeNames" => ["#pk" => $this->primaryKey],
157
        ];
158 5
        return $query;
159
    }
160
161 2
    public function delete($resourceId)
162
    {
163
        try {
164 2
            $query = $this->createDeleteQuery($resourceId);
165 2
            $res = $this->client->deleteItem($query);
166 1
            return $resourceId;
167 1
        } catch (\Exception $ex) {
168 1
            throw new RestException($ex->getMessage(), ['result'=>empty($res)?null:$res]);
169
        }
170
    }
171
172 2
    protected function createDeleteQuery($resourceId)
173
    {
174
        $query = [
175 2
            'TableName' => $this->fullTableName,
176 2
            'Key' => $this->marshalItem([$this->primaryKey => $resourceId]),
177
        ];
178 2
        return $query;
179
    }
180
181 14
    protected function marshalItem($resource)
182
    {
183 14
        return $this->marshaler->marshalItem($resource);
184
    }
185
186 3
    protected function unmarshalItem($item)
187
    {
188 3
        if ($item === null) {
189 1
            return new \StdClass;
190
        }
191 2
        return $this->marshaler->unmarshalItem($item, true);
192
    }
193
194 2
    protected function unmarshalBatch($itemList)
195
    {
196 2
        if ($itemList === null) {
197 1
            return [];
198
        }
199 1
        $list = [];
200 1
        foreach ($itemList as $item) {
201 1
            $list[] = $this->unmarshalItem($item, true);
0 ignored issues
show
Unused Code introduced by
The call to Resource::unmarshalItem() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
202
        }
203 1
        return $list;
204
    }
205
}
206