Passed
Pull Request — master (#9)
by Csaba
02:38
created

Resource::createDeleteQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
crap 1
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