CreateTableOperation::addSecondaryIndex()   A
last analyzed

Complexity

Conditions 5
Paths 8

Size

Total Lines 36
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 5

Importance

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