Completed
Push — master ( e15fb0...634cc5 )
by Guillermo A.
02:14
created

DynamoDbAdapter::describeTable()   A

Complexity

Conditions 3
Paths 8

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 8
c 2
b 0
f 0
dl 0
loc 11
ccs 8
cts 8
cp 1
rs 10
cc 3
nc 8
nop 1
crap 3
1
<?php
2
3
namespace Guillermoandrae\Db\DynamoDb;
4
5
use Aws\DynamoDb\DynamoDbClient;
6
use Aws\DynamoDb\Exception\DynamoDbException;
7
use Guillermoandrae\Common\Collection;
8
use Guillermoandrae\Common\CollectionInterface;
9
use Guillermoandrae\Db\AdapterInterface;
10
use Guillermoandrae\Db\DbException;
11
use InvalidArgumentException;
12
13
final class DynamoDbAdapter implements AdapterInterface
14
{
15
    /**
16
     * @var DynamoDbClient The DynamoDb client.
17
     */
18
    private $client;
19
20
    /**
21
     * @var MarshalerFactory The JSON Marshaler.
22
     */
23
    private $marshaler;
24
25
    /**
26
     * @var string The table name.
27
     */
28
    private $tableName;
29
30
    /**
31
     * DynamoDBAdapter constructor.
32
     *
33
     * Registers AWS' DynamoDB client and marshaler with this object. If no options are provided, we pass the options
34
     * needed to connect to a local instance. This constructor also Passes the marshaler over to the request factory.
35
     *
36
     * @param array $options OPTIONAL The DynamoDb client options.
37
     */
38 17
    public function __construct(array $options = [
39
        'region' => 'us-west-2',
40
        'version'  => 'latest',
41
        'endpoint' => 'http://localhost:8000',
42
        'credentials' => [
43
            'key' => 'not-a-real-key',
44
            'secret' => 'not-a-real-secret',
45
        ]
46
    ])
47
    {
48 17
        $this->setClient(DynamoDbClient::factory($options));
0 ignored issues
show
Deprecated Code introduced by
The function Aws\AwsClient::factory() has been deprecated. ( Ignorable by Annotation )

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

48
        $this->setClient(/** @scrutinizer ignore-deprecated */ DynamoDbClient::factory($options));
Loading history...
49 17
        $this->marshaler = MarshalerFactory::factory();
0 ignored issues
show
Documentation Bug introduced by
It seems like Guillermoandrae\Db\Dynam...halerFactory::factory() of type Aws\DynamoDb\Marshaler is incompatible with the declared type Guillermoandrae\Db\DynamoDb\MarshalerFactory of property $marshaler.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
50 17
        RequestFactory::setMarshaler($this->marshaler);
51 17
    }
52
53
    /**
54
     * {@inheritDoc}
55
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#createtable
56
     */
57 9
    public function createTable(array $data, string $tableName = ''): bool
58
    {
59
        try {
60 9
            if (empty($tableName)) {
61 9
                $tableName = $this->tableName;
62
            }
63 9
            $query = RequestFactory::factory('create-table', $tableName, $data)->get();
64 9
            $this->client->createTable($query);
65 7
            $this->client->waitUntil('TableExists', ['TableName' => $tableName]);
66 7
            return true;
67 2
        } catch (DynamoDbException $ex) {
68 1
            throw new DbException($ex->getMessage());
69 1
        } catch (InvalidArgumentException $ex) {
70 1
            throw new DbException('Bad key schema: ' . $ex->getMessage());
71
        }
72
    }
73
74
    /**
75
     * {@inheritDoc}
76
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#deletetable
77
     */
78 8
    public function deleteTable(string $tableName = ''): bool
79
    {
80
        try {
81 8
            if (empty($tableName)) {
82 8
                $tableName = $this->tableName;
83
            }
84 8
            $query = RequestFactory::factory('delete-table', $tableName)->get();
85 8
            $this->client->deleteTable($query);
86 7
            $this->client->waitUntil('TableNotExists', ['TableName' => $tableName]);
87 7
            return true;
88 1
        } catch (DynamoDbException $ex) {
89 1
            throw new DbException($ex->getMessage());
90
        }
91
    }
92
93
    /**
94
     * {@inheritDoc}
95
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#describetable
96
     */
97 2
    public function describeTable(string $tableName = ''): array
98
    {
99
        try {
100 2
            if (empty($tableName)) {
101 2
                $tableName = $this->tableName;
102
            }
103 2
            $query = RequestFactory::factory('describe-table', $tableName)->get();
104 2
            $result = $this->client->describeTable($query);
105 1
            return $result['Table'];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result['Table'] could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
106 1
        } catch (DynamoDbException $ex) {
107 1
            throw new DbException($ex->getMessage());
108
        }
109
    }
110
111
    /**
112
     * {@inheritDoc}
113
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#listtables
114
     */
115 2
    public function tableExists(string $tableName = ''): bool
116
    {
117 2
        if (empty($tableName)) {
118 1
            $tableName = $this->tableName;
119
        }
120 2
        $tables = $this->listTables();
121 2
        return in_array(
122 2
            strtolower($tableName),
123 2
            array_map('strtolower', $tables)
124
        );
125
    }
126
127
    /**
128
     * {@inheritDoc}
129
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#listtables
130
     */
131 17
    public function listTables(): array
132
    {
133 17
        $query = RequestFactory::factory('list-tables')->get();
134 17
        $results = $this->client->listTables($query);
135 17
        return $results['TableNames'];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $results['TableNames'] could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
136
    }
137
138
    /**
139
     * {@inheritDoc}
140
     */
141 16
    public function useTable(string $tableName): AdapterInterface
142
    {
143 16
        $this->tableName = $tableName;
144 16
        return $this;
145
    }
146
147
    /**
148
     * {@inheritDoc}
149
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#query
150
     */
151
    public function findWhere(array $conditions, int $offset = 0, ?int $limit = null): CollectionInterface
152
    {
153
        try {
154
            $query = RequestFactory::factory('query', $this->tableName, $conditions)->get();
155
            $results = $this->client->query($query);
156
            $rows = [];
157
            foreach ($results['Items'] as $item) {
158
                $rows[] = $this->marshaler->unmarshalItem($item);
0 ignored issues
show
Bug introduced by
The method unmarshalItem() does not exist on Guillermoandrae\Db\DynamoDb\MarshalerFactory. ( Ignorable by Annotation )

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

158
                /** @scrutinizer ignore-call */ 
159
                $rows[] = $this->marshaler->unmarshalItem($item);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
159
            }
160
            $collection = Collection::make($rows);
161
            return $collection->limit($offset, $limit);
162
        } catch (DynamoDbException $ex) {
163
            throw new DbException($ex->getMessage());
164
        }
165
    }
166
167
    /**
168
     * {@inheritDoc}
169
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#scan
170
     */
171 3
    public function findAll(int $offset = 0, ?int $limit = null): CollectionInterface
172
    {
173
        try {
174 3
            $query = RequestFactory::factory('scan', $this->tableName)->get();
175 3
            $results = $this->client->scan($query);
176 2
            $rows = [];
177 2
            foreach ($results['Items'] as $item) {
178 1
                $rows[] = $this->marshaler->unmarshalItem($item);
179
            }
180 2
            $collection = Collection::make($rows);
181 2
            return $collection->limit($offset, $limit);
182 1
        } catch (DynamoDbException $ex) {
183 1
            throw new DbException($ex->getMessage());
184
        }
185
    }
186
187
    /**
188
     * {@inheritDoc}
189
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#scan
190
     */
191 2
    public function findLatest(): array
192
    {
193
        try {
194 2
            $query = RequestFactory::factory('scan', $this->tableName)
195 2
                ->setLimit(1)
0 ignored issues
show
Bug introduced by
The method setLimit() does not exist on Guillermoandrae\Db\DynamoDb\RequestInterface. It seems like you code against a sub-type of Guillermoandrae\Db\DynamoDb\RequestInterface such as Guillermoandrae\Db\DynamoDb\ListTablesRequest or Guillermoandrae\Db\Dynam...rExpressionAwareRequest. ( Ignorable by Annotation )

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

195
                ->/** @scrutinizer ignore-call */ setLimit(1)
Loading history...
196 2
                ->get();
197 2
            $results = $this->client->scan($query);
198 1
            return $this->marshaler->unmarshalItem($results['Items'][0]);
199 1
        } catch (DynamoDbException $ex) {
200 1
            throw new DbException($ex->getMessage());
201
        }
202
    }
203
204
    /**
205
     * {@inheritDoc}
206
     */
207 2
    public function findById($id): array
208
    {
209 2
        return $this->findByPrimaryKey($id);
210
    }
211
212
    /**
213
     * {@inheritDoc}
214
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#getitem
215
     */
216 2
    public function findByPrimaryKey($primaryKey): array
217
    {
218
        try {
219 2
            $query = RequestFactory::factory('get-item', $this->tableName, $primaryKey)->get();
220 2
            $results = $this->client->getItem($query);
221 1
            $item = [];
222 1
            if (is_array($results['Item'])) {
223 1
                $item = $this->marshaler->unmarshalItem($results['Item']);
224
            }
225 1
            return $item;
226 1
        } catch (DynamoDbException $ex) {
227 1
            throw new DbException($ex->getMessage());
228
        }
229
    }
230
231
    /**
232
     * {@inheritDoc}
233
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#putitem
234
     */
235 5
    public function insert(array $data): bool
236
    {
237
        try {
238 5
            $query = RequestFactory::factory('put-item', $this->tableName, $data)->get();
239 5
            $this->client->putItem($query);
240 4
            return true;
241 1
        } catch (DynamoDbException $ex) {
242 1
            throw new DbException($ex->getMessage());
243
        }
244
    }
245
246
    /**
247
     * {@inheritDoc}
248
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#deleteitem
249
     */
250 2
    public function delete($id): bool
251
    {
252
        try {
253 2
            $query = RequestFactory::factory('delete-item', $this->tableName, $id)->get();
254 2
            $this->client->deleteItem($query);
255 1
            return true;
256 1
        } catch (DynamoDbException $ex) {
257 1
            throw new DbException($ex->getMessage());
258
        }
259
    }
260
261
    /**
262
     * {@inheritDoc}
263
     */
264 17
    public function setClient($client): AdapterInterface
265
    {
266 17
        $this->client = $client;
267 17
        return $this;
268
    }
269
270
    /**
271
     * {@inheritDoc}
272
     */
273 1
    public function getClient(): DynamoDbClient
274
    {
275 1
        return $this->client;
276
    }
277
}
278