Completed
Push — master ( a8eec6...0c808d )
by Guillermo A.
02:01
created

CreateTableOperation::setBillingMode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 4
rs 10
ccs 3
cts 3
cp 1
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Guillermoandrae\DynamoDb\Operation;
4
5
use Aws\DynamoDb\DynamoDbClient;
6
use Aws\DynamoDb\Exception\DynamoDbException;
7
use Aws\DynamoDb\Marshaler;
8
use Guillermoandrae\DynamoDb\Constant\BillingModes;
9
use Guillermoandrae\DynamoDb\Constant\KeyTypes;
10
use Guillermoandrae\DynamoDb\Contract\AbstractTableOperation;
11
use Guillermoandrae\DynamoDb\Exception\Exception;
12
use Guillermoandrae\DynamoDb\Factory\ExceptionFactory;
13
14
/**
15
 * @link https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#createtable
16
 */
17
final class CreateTableOperation extends AbstractTableOperation
18
{
19
    /**
20
     * @var array Attributes describing the key schema.
21
     */
22
    private $attributeDefinitions = [];
23
24
    /**
25
     * @var array The primary key.
26
     */
27
    private $keySchema = [];
28
29
    /**
30
     * @var int The maximum number of strongly consistent reads consumed per second.
31
     */
32
    private $readCapacityUnits = 5;
33
34
    /**
35
     * @var int The maximum number of writes consumed per second.
36
     */
37
    private $writeCapacityUnits = 5;
38
39
    /**
40
     * @var string The billing mode.
41
     */
42
    private $billingMode = BillingModes::PROVISIONED;
43
44
    /**
45
     * @var array The server-side encryption settings.
46
     */
47
    private $sseSpecification = [];
48
49
    /**
50
     * @var array The stream specification.
51
     */
52
    private $streamSpecification = [];
53
54
    /**
55
     * @var array The global secondary indexes.
56
     */
57
    private $globalSecondaryIndexes = [];
58
59
    /**
60
     * @var array The local secondary indexes.
61
     */
62
    private $localSecondaryIndexes = [];
63
64
    /**
65
     * @var array The tags.
66
     */
67
    private $tags = [];
68
69
    /**
70
     * CreateTableRequest constructor.
71
     *
72
     * @param DynamoDbClient $client The DynamoDb client.
73
     * @param Marshaler $marshaler The Marshaler.
74
     * @param string $tableName The table name.
75
     * @param array $keySchema OPTIONAL The key schema.
76
     */
77 20
    public function __construct(DynamoDbClient $client, Marshaler $marshaler, string $tableName, array $keySchema = [])
78
    {
79 20
        parent::__construct($client, $marshaler, $tableName);
80 20
        if (!empty($keySchema)) {
81 9
            $this->setKeySchema($keySchema);
82
        }
83 20
    }
84
85
    /**
86
     * Registers the key schema and attribute definitions.
87
     *
88
     * The key schema argument should be an associative array with the following keys:
89
     *
90
     * $keySchema = [
91
     *      'MyAttribute' => [ // this is the name of your attribute
92
     *          'S', // this must be one of the AttributeTypes constants
93
     *          'HASH' // this must be one of the KeyTypes constants
94
     *     ]
95
     * ];
96
     *
97
     * This method will use the information available in the provided array to build the 'KeySchema' and
98
     * 'AttributeDefinitions' arrays needed for table creation requests.
99
     *
100
     * @param array $keySchema The key schema.
101
     * @return CreateTableOperation This object.
102
     */
103 11
    public function setKeySchema(array $keySchema): CreateTableOperation
104
    {
105 11
        foreach ($keySchema as $name => $data) {
106 11
            $this->keySchema[] = [
107 11
                'AttributeName' => $name,
108 11
                'KeyType' => $data[1]
109
            ];
110 11
            $this->attributeDefinitions[] = [
111 11
                'AttributeName' => $name,
112 11
                'AttributeType' => $data[0]
113
            ];
114
        }
115 11
        return $this;
116
    }
117
118
    /**
119
     * Registers the partition key.
120
     *
121
     * @param string $name The name of the partition key.
122
     * @param string $attributeType The attribute type.
123
     * @return CreateTableOperation This object.
124
     */
125 1
    public function setPartitionKey(string $name, string $attributeType): CreateTableOperation
126
    {
127 1
        $this->setKeySchema([
128 1
            $name => [$attributeType, KeyTypes::HASH]
129
        ]);
130 1
        return $this;
131
    }
132
133
    /**
134
     * Registers the sort key.
135
     *
136
     * @param string $name The name of the sort key.
137
     * @param string $attributeType The attribute type.
138
     * @return CreateTableOperation This object.
139
     */
140 1
    public function setSortKey(string $name, string $attributeType): CreateTableOperation
141
    {
142 1
        $this->setKeySchema([
143 1
            $name => [$attributeType, KeyTypes::RANGE]
144
        ]);
145 1
        return $this;
146
    }
147
148
    /**
149
     * Registers the maximum number of strongly consistent reads consumed per second.
150
     *
151
     * @param integer $readCapacityUnits The maximum number of strongly consistent reads consumed per second.
152
     * @return CreateTableOperation This object.
153
     */
154 1
    public function setReadCapacityUnits(int $readCapacityUnits): CreateTableOperation
155
    {
156 1
        $this->readCapacityUnits = $readCapacityUnits;
157 1
        return $this;
158
    }
159
160
    /**
161
     * Registers the maximum number of writes consumed per second.
162
     *
163
     * @param integer $writeCapacityUnits The maximum number of writes consumed per second.
164
     * @return CreateTableOperation This object.
165
     */
166 1
    public function setWriteCapacityUnits(int $writeCapacityUnits): CreateTableOperation
167
    {
168 1
        $this->writeCapacityUnits = $writeCapacityUnits;
169 1
        return $this;
170
    }
171
172
    /**
173
     * Registers the billing mode.
174
     *
175
     * @param string $billingMode The billing mode.
176
     * @return CreateTableOperation This object.
177
     */
178 1
    public function setBillingMode(string $billingMode)
179
    {
180 1
        $this->billingMode = $billingMode;
181 1
        return $this;
182
    }
183
184
    /**
185
     * Registers the server-side encryption settings.
186
     *
187
     * @param bool $isEnabled Whether or not SSE is enabled.
188
     * @param string $masterKeyId OPTIONAL The ID of the master key.
189
     * @return CreateTableOperation This object.
190
     */
191 1
    public function setSSESpecification(bool $isEnabled, string $masterKeyId = '')
192
    {
193 1
        $sseSpecification = [];
194 1
        if ($isEnabled) {
195
            $sseSpecification = [
196 1
                'Enabled' => $isEnabled,
197 1
                'SSEType' => 'KMS'
198
            ];
199 1
            if (!empty($masterKeyId)) {
200 1
                $sseSpecification['KMSMasterKeyId'] = $masterKeyId;
201
            }
202
        }
203 1
        $this->sseSpecification = $sseSpecification;
204 1
        return $this;
205
    }
206
207
    /**
208
     * Adds a global secondary index.
209
     *
210
     * @see CreateTableOperation::addSecondaryIndex()
211
     * @param string $indexName The index name.
212
     * @param array $keySchema The key schema.
213
     * @param array $projection The projection.
214
     * @param array|null $provisionedThroughput OPTIONAL The provisioned throughput.
215
     * @return CreateTableOperation This object.
216
     */
217 2
    public function addGlobalSecondaryIndex(
218
        string $indexName,
219
        array $keySchema,
220
        array $projection,
221
        ?array $provisionedThroughput = []
222
    ): CreateTableOperation {
223 2
        return $this->addSecondaryIndex('global', $indexName, $keySchema, $projection, $provisionedThroughput);
224
    }
225
226
    /**
227
     * Adds a local secondary index.
228
     *
229
     * @see CreateTableOperation::addSecondaryIndex()
230
     * @param string $indexName The index name.
231
     * @param array $keySchema The key schema.
232
     * @param array $projection The projection.
233
     * @return CreateTableOperation This object.
234
     */
235 1
    public function addLocalSecondaryIndex(
236
        string $indexName,
237
        array $keySchema,
238
        array $projection
239
    ): CreateTableOperation {
240 1
        return $this->addSecondaryIndex('local', $indexName, $keySchema, $projection);
241
    }
242
243
    /**
244
     * Registers the stream specification.
245
     *
246
     * @param bool $isEnabled Whether or not the stream specification is enabled.
247
     * @param string|null $viewType OPTIONAL The stream view type.
248
     * @return CreateTableOperation This object.
249
     */
250 1
    public function setStreamSpecification(bool $isEnabled, ?string $viewType = ''): CreateTableOperation
251
    {
252 1
        $this->streamSpecification = [
253 1
            'StreamEnabled' => $isEnabled
254
        ];
255 1
        if ($isEnabled && !empty($viewType)) {
256 1
            $this->streamSpecification['StreamViewType'] = $viewType;
257
        }
258 1
        return $this;
259
    }
260
261
    /**
262
     * Registers a tag.
263
     *
264
     * @param string $key The tag key.
265
     * @param string $value The tag value.
266
     * @return CreateTableOperation This object.
267
     */
268 1
    public function addTag(string $key, string $value)
269
    {
270 1
        $this->tags[] = [
271 1
            'Key' => $key,
272 1
            'Value' => $value
273
        ];
274 1
        return $this;
275
    }
276
277
    /**
278
     * {@inheritDoc}
279
     */
280 9
    public function execute(): bool
281
    {
282
        try {
283 9
            $this->client->createTable($this->toArray());
284
            //$this->client->waitUntil('TableExists', ['TableName' => $this->toArray()['TableName']]);
285 7
            return true;
286 2
        } catch (DynamoDbException $ex) {
287 1
            throw ExceptionFactory::factory($ex);
288 1
        } catch (\Exception $ex) {
289 1
            throw new Exception($ex->getMessage());
290
        }
291
    }
292
293
    /**
294
     * {@inheritDoc}
295
     */
296 20
    public function toArray(): array
297
    {
298 20
        $operation = parent::toArray();
299 20
        $operation['KeySchema'] = $this->keySchema;
300 20
        $operation['AttributeDefinitions'] = $this->attributeDefinitions;
301 20
        $operation['BillingMode'] = $this->billingMode;
302 20
        $operation['ProvisionedThroughput'] = [
303 20
            'ReadCapacityUnits' => $this->readCapacityUnits,
304 20
            'WriteCapacityUnits' => $this->writeCapacityUnits,
305
        ];
306 20
        if (!empty($this->sseSpecification)) {
307 1
            $operation['SSESpecification'] = $this->sseSpecification;
308
        }
309 20
        if (!empty($this->streamSpecification)) {
310 1
            $operation['StreamSpecification'] = $this->streamSpecification;
311
        }
312 20
        if (!empty($this->globalSecondaryIndexes)) {
313 2
            $operation['GlobalSecondaryIndexes'] = $this->globalSecondaryIndexes;
314
        }
315 20
        if (!empty($this->localSecondaryIndexes)) {
316 1
            $operation['LocalSecondaryIndexes'] = $this->localSecondaryIndexes;
317
        }
318 20
        if (!empty($this->tags)) {
319 1
            $operation['Tags'] = $this->tags;
320
        }
321 20
        return $operation;
322
    }
323
324
    /**
325
     * Adds a secondary index.
326
     *
327
     * @see CreateTableOperation::addSecondaryIndex()
328
     * @param string $indexType The index type.
329
     * @param string $indexName The index name.
330
     * @param array $keySchema The key schema.
331
     * @param array $projection The projection.
332
     * @param array|null $provisionedThroughput OPTIONAL The provisioned throughput.
333
     * @return CreateTableOperation This object.
334
     */
335 3
    private function addSecondaryIndex(
336
        string $indexType,
337
        string $indexName,
338
        array $keySchema,
339
        array $projection,
340
        ?array $provisionedThroughput = []
341
    ): CreateTableOperation {
342
        $index = [
343 3
            'IndexName' => $indexName,
344
            'KeySchema' => [],
345
            'Projection' => [
346 3
                'NonKeyAttributes' => $projection[0],
347 3
                'ProjectionType' => $projection[1]
348
            ]
349
        ];
350 3
        foreach ($keySchema as $key) {
351 3
            $index['KeySchema'][] = [
352 3
                'AttributeName' => $key[0],
353 3
                'KeyType' => $key[1]
354
            ];
355
        }
356 3
        switch ($indexType) {
357 3
            case 'local':
358 1
                $this->localSecondaryIndexes[] = $index;
359 1
                break;
360 2
            case 'global':
361 2
                if (!empty($provisionedThroughput)) {
362 1
                    $index['ProvisionedThroughput'] = [
363 1
                        'ReadCapacityUnits' => $provisionedThroughput[0],
364 1
                        'WriteCapacityUnits' => $provisionedThroughput[1],
365
                    ];
366
                }
367 2
                $this->globalSecondaryIndexes[] = $index;
368 2
                break;
369
        }
370 3
        return $this;
371
    }
372
}
373