Test Failed
Branch feature/dynamodb (336f9f)
by Csaba
05:26
created

Resource::createDeleteQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 5
nc 1
nop 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
    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->marshaler = new Marshaler;
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->createGetQuery($resourceId);
60
        $res = $this->client->getItem($query);
61
        return $this->unmarshalItem($res['Item']);
62
    }
63
64
    protected function createGetQuery($resourceId)
65
    {
66
        $query = [
67
            'TableName' => $this->fullTableName,
68
            'Key' => $this->marshalItem([$this->primaryKey => $resourceId]),
69
        ];
70
        return $query;
71
    }
72
73
    protected function getAll()
74
    {
75
        $query = $this->createScanQuery();
76
        $res = $this->client->scan($query);
77
        return $this->unmarshalBatch($res['Items']);
78
    }
79
80
    protected function createScanQuery()
81
    {
82
        $query = [
83
            'TableName' => $this->fullTableName,
84
        ];
85
        return $query;
86
    }
87
88
    public function post($newResource)
89
    {
90
        try {
91
            $query = $this->createPostQuery($newResource);
92
            $res = $this->client->putItem($query);
0 ignored issues
show
Unused Code introduced by
$res is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
93
            return $newResource;
94
        } catch (DynamoDbException $ex) {
95
            if ($ex->getAwsErrorCode() === 'ConditionalCheckFailedException') {
96
                throw new RestException(
97
                    'Primary key collision',
98
                    ['exception' => $ex]
99
                );
100
            }
101
            throw new RestException($ex->getMessage(), ['exception' => $ex]);
102
        } catch (\Exception $ex) {
103
            throw new RestException($ex->getMessage(), ['exception' => $ex]);
104
        }
105
    }
106
107
    protected function createPostQuery($newResource)
108
    {
109
        $query = [
110
            'TableName' => $this->fullTableName,
111
            'Item' => $this->marshalItem($newResource),
112
            'ConditionExpression' => 'attribute_not_exists(#pk)',
113
            "ExpressionAttributeNames" => ["#pk" => $this->primaryKey],
114
        ];
115
        return $query;
116
    }
117
118
    public function put($resourceId, $newResource)
119
    {
120
        try {
121
            $newResource->{$this->primaryKey} = $resourceId;
122
            $query = $this->createPutQuery($newResource);
123
            $res = $this->client->putItem($query);
124
            return $newResource;
125
        } catch (DynamoDbException $ex) {
126
            if ($ex->getAwsErrorCode() === 'ConditionalCheckFailedException') {
127
                throw new RestException(
128
                    'Resource does not exist',
129
                    ['exception' => $ex]
130
                );
131
            }
132
            throw new RestException($ex->getMessage(), ['exception' => $ex]);
133
        } catch (\Exception $ex) {
134
            throw new RestException($ex->getMessage(), ['result'=>empty($res)?null:$res]);
135
        }
136
    }
137
138
    protected function createPutQuery($newResource)
139
    {
140
        $query = [
141
            'TableName' => $this->fullTableName,
142
            'Item' => $this->marshalItem($newResource),
143
            'ConditionExpression' => 'attribute_exists(#pk)',
144
            "ExpressionAttributeNames" => ["#pk" => $this->primaryKey],
145
        ];
146
        return $query;
147
    }
148
149
    public function delete($resourceId)
150
    {
151
        try {
152
            $query = $this->createDeleteQuery($resourceId);
153
            $res = $this->client->deleteItem($query);
154
            return $resourceId;
155
        } catch (\Exception $ex) {
156
            throw new RestException($ex->getMessage(), ['result'=>empty($res)?null:$res]);
157
        }
158
    }
159
160
    protected function createDeleteQuery($resourceId)
161
    {
162
        $query = [
163
            'TableName' => $this->fullTableName,
164
            'Key' => $this->marshalItem([$this->primaryKey => $resourceId]),
165
        ];
166
        return $query;
167
    }
168
169
    protected function marshalItem($resource)
170
    {
171
        return $this->marshaler->marshalItem($resource);
172
    }
173
174
    protected function unmarshalItem($item, $mapAsObject = true)
175
    {
176
        if ($item === null) {
177
            return new \StdClass;
178
        }
179
        return $this->marshaler->unmarshalItem($item, $mapAsObject);
180
    }
181
182
    protected function unmarshalBatch($itemList, $mapAsObject = true)
183
    {
184
        if ($itemList === null) {
185
            return [];
186
        }
187
        $list = [];
188
        foreach ($itemList as $item) {
189
            $list[] = $this->unmarshalItem($item, $mapAsObject);
190
        }
191
        return $list;
192
    }
193
}
194