Completed
Push — master ( 3890f4...ffa1fa )
by Guillermo A.
03:24
created

DynamoDbAdapter::findById()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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

49
        $this->setClient(/** @scrutinizer ignore-deprecated */ DynamoDbClient::factory($options));
Loading history...
50 19
        $this->marshaler = MarshalerFactory::factory();
51 19
        RequestFactory::setMarshaler($this->marshaler);
52 19
    }
53
54
    /**
55
     * {@inheritDoc}
56
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#createtable
57
     */
58 10
    public function createTable(array $data, string $tableName = ''): bool
59
    {
60
        try {
61 10
            if (empty($tableName)) {
62 10
                $tableName = $this->tableName;
63
            }
64 10
            $query = RequestFactory::factory('create-table', $tableName, $data)->get();
65 10
            $this->client->createTable($query);
66 8
            $this->client->waitUntil('TableExists', ['TableName' => $tableName]);
67 8
            return true;
68 2
        } catch (DynamoDbException $ex) {
69 1
            throw new DbException($ex->getMessage());
70 1
        } catch (InvalidArgumentException $ex) {
71 1
            throw new DbException('Bad key schema: ' . $ex->getMessage());
72
        }
73
    }
74
75
    /**
76
     * {@inheritDoc}
77
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#deletetable
78
     */
79 9
    public function deleteTable(string $tableName = ''): bool
80
    {
81
        try {
82 9
            if (empty($tableName)) {
83 9
                $tableName = $this->tableName;
84
            }
85 9
            $query = RequestFactory::factory('delete-table', $tableName)->get();
86 9
            $this->client->deleteTable($query);
87 8
            $this->client->waitUntil('TableNotExists', ['TableName' => $tableName]);
88 8
            return true;
89 1
        } catch (DynamoDbException $ex) {
90 1
            throw new DbException($ex->getMessage());
91
        }
92
    }
93
94
    /**
95
     * {@inheritDoc}
96
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#describetable
97
     */
98 2
    public function describeTable(string $tableName = ''): array
99
    {
100
        try {
101 2
            if (empty($tableName)) {
102 2
                $tableName = $this->tableName;
103
            }
104 2
            $query = RequestFactory::factory('describe-table', $tableName)->get();
105 2
            $result = $this->client->describeTable($query);
106 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...
107 1
        } catch (DynamoDbException $ex) {
108 1
            throw new DbException($ex->getMessage());
109
        }
110
    }
111
112
    /**
113
     * {@inheritDoc}
114
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#listtables
115
     */
116 2
    public function tableExists(string $tableName = ''): bool
117
    {
118 2
        if (empty($tableName)) {
119 1
            $tableName = $this->tableName;
120
        }
121 2
        $tables = $this->listTables();
122 2
        return in_array(
123 2
            strtolower($tableName),
124 2
            array_map('strtolower', $tables)
125
        );
126
    }
127
128
    /**
129
     * {@inheritDoc}
130
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#listtables
131
     */
132 19
    public function listTables(): array
133
    {
134 19
        $query = RequestFactory::factory('list-tables')->get();
135 19
        $results = $this->client->listTables($query);
136 19
        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...
137
    }
138
139
    /**
140
     * {@inheritDoc}
141
     */
142 18
    public function useTable(string $tableName): AdapterInterface
143
    {
144 18
        $this->tableName = $tableName;
145 18
        return $this;
146
    }
147
148
    /**
149
     * {@inheritDoc}
150
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#query
151
     */
152 2
    public function findWhere(array $conditions, int $offset = 0, ?int $limit = null): CollectionInterface
153
    {
154
        try {
155 2
            $query = RequestFactory::factory('query', $this->tableName, $conditions)->get();
156 2
            $results = $this->client->query($query);
157 1
            $rows = [];
158 1
            foreach ($results['Items'] as $item) {
159 1
                $rows[] = $this->marshaler->unmarshalItem($item);
160
            }
161 1
            $collection = Collection::make($rows);
162 1
            return $collection->limit($offset, $limit);
163 1
        } catch (DynamoDbException $ex) {
164 1
            throw new DbException($ex->getMessage());
165
        }
166
    }
167
168
    /**
169
     * {@inheritDoc}
170
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#scan
171
     */
172 3
    public function findAll(int $offset = 0, ?int $limit = null): CollectionInterface
173
    {
174
        try {
175 3
            $query = RequestFactory::factory('scan', $this->tableName)->get();
176 3
            $results = $this->client->scan($query);
177 2
            $rows = [];
178 2
            foreach ($results['Items'] as $item) {
179 1
                $rows[] = $this->marshaler->unmarshalItem($item);
180
            }
181 2
            $collection = Collection::make($rows);
182 2
            return $collection->limit($offset, $limit);
183 1
        } catch (DynamoDbException $ex) {
184 1
            throw new DbException($ex->getMessage());
185
        }
186
    }
187
188
    /**
189
     * {@inheritDoc}
190
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#scan
191
     */
192 2
    public function findLatest(): array
193
    {
194
        try {
195 2
            $query = RequestFactory::factory('scan', $this->tableName)
196 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

196
                ->/** @scrutinizer ignore-call */ setLimit(1)
Loading history...
197 2
                ->get();
198 2
            $results = $this->client->scan($query);
199 1
            return $this->marshaler->unmarshalItem($results['Items'][0]);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->marshaler-...m($results['Items'][0]) could return the type stdClass which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
200 1
        } catch (DynamoDbException $ex) {
201 1
            throw new DbException($ex->getMessage());
202
        }
203
    }
204
205
    /**
206
     * {@inheritDoc}
207
     */
208 2
    public function findById($id): array
209
    {
210 2
        return $this->findByPrimaryKey($id);
211
    }
212
213
    /**
214
     * {@inheritDoc}
215
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#getitem
216
     */
217 2
    public function findByPrimaryKey($primaryKey): array
218
    {
219
        try {
220 2
            $query = RequestFactory::factory('get-item', $this->tableName, $primaryKey)->get();
221 2
            $results = $this->client->getItem($query);
222 1
            $item = [];
223 1
            if (is_array($results['Item'])) {
224 1
                $item = $this->marshaler->unmarshalItem($results['Item']);
0 ignored issues
show
Bug introduced by
It seems like $results['Item'] can also be of type null; however, parameter $data of Aws\DynamoDb\Marshaler::unmarshalItem() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

224
                $item = $this->marshaler->unmarshalItem(/** @scrutinizer ignore-type */ $results['Item']);
Loading history...
225
            }
226 1
            return $item;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $item could return the type stdClass which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
227 1
        } catch (DynamoDbException $ex) {
228 1
            throw new DbException($ex->getMessage());
229
        }
230
    }
231
232
    /**
233
     * {@inheritDoc}
234
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#putitem
235
     */
236 6
    public function insert(array $data): bool
237
    {
238
        try {
239 6
            $query = RequestFactory::factory('put-item', $this->tableName, $data)->get();
240 6
            $this->client->putItem($query);
241 5
            return true;
242 1
        } catch (DynamoDbException $ex) {
243 1
            throw new DbException($ex->getMessage());
244
        }
245
    }
246
247
    /**
248
     * {@inheritDoc}
249
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#deleteitem
250
     */
251 2
    public function delete($id): bool
252
    {
253
        try {
254 2
            $query = RequestFactory::factory('delete-item', $this->tableName, $id)->get();
255 2
            $this->client->deleteItem($query);
256 1
            return true;
257 1
        } catch (DynamoDbException $ex) {
258 1
            throw new DbException($ex->getMessage());
259
        }
260
    }
261
262
    /**
263
     * {@inheritDoc}
264
     */
265 19
    public function setClient($client): AdapterInterface
266
    {
267 19
        $this->client = $client;
268 19
        return $this;
269
    }
270
271
    /**
272
     * {@inheritDoc}
273
     */
274 1
    public function getClient(): DynamoDbClient
275
    {
276 1
        return $this->client;
277
    }
278
}
279