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

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

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

197
                ->/** @scrutinizer ignore-call */ setLimit(1)
Loading history...
198 2
                ->get();
199 2
            $results = $this->client->scan($query);
200 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|null. Consider adding an additional type-check to rule them out.
Loading history...
201 1
        } catch (DynamoDbException $ex) {
202 1
            throw new Exception($ex->getMessage());
203
        }
204
    }
205
206
    /**
207
     * {@inheritDoc}
208
     */
209 2
    public function findById($id): array
210
    {
211 2
        return $this->findByPrimaryKey($id);
212
    }
213
214
    /**
215
     * {@inheritDoc}
216
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#getitem
217
     */
218 2
    public function findByPrimaryKey($primaryKey): array
219
    {
220
        try {
221 2
            $query = RequestFactory::factory('get-item', $this->tableName, $primaryKey)->get();
222 2
            $results = $this->client->getItem($query);
223 1
            $item = [];
224 1
            if (is_array($results['Item'])) {
225 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

225
                $item = $this->marshaler->unmarshalItem(/** @scrutinizer ignore-type */ $results['Item']);
Loading history...
226
            }
227 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...
228 1
        } catch (DynamoDbException $ex) {
229 1
            throw new Exception($ex->getMessage());
230
        }
231
    }
232
233
    /**
234
     * {@inheritDoc}
235
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#putitem
236
     */
237 6
    public function insert(array $data): bool
238
    {
239
        try {
240 6
            $query = RequestFactory::factory('put-item', $this->tableName, $data)->get();
241 6
            $this->client->putItem($query);
242 5
            return true;
243 1
        } catch (DynamoDbException $ex) {
244 1
            throw new Exception($ex->getMessage());
245
        }
246
    }
247
248
    /**
249
     * {@inheritDoc}
250
     * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#deleteitem
251
     */
252 2
    public function delete($id): bool
253
    {
254
        try {
255 2
            $query = RequestFactory::factory('delete-item', $this->tableName, $id)->get();
256 2
            $this->client->deleteItem($query);
257 1
            return true;
258 1
        } catch (DynamoDbException $ex) {
259 1
            throw new Exception($ex->getMessage());
260
        }
261
    }
262
263
    /**
264
     * {@inheritDoc}
265
     */
266 19
    public function setClient($client): DynamoDbAdapterInterface
267
    {
268 19
        $this->client = $client;
269 19
        return $this;
270
    }
271
272
    /**
273
     * {@inheritDoc}
274
     */
275 1
    public function getClient(): DynamoDbClient
276
    {
277 1
        return $this->client;
278
    }
279
}
280