Completed
Push — master ( 1b95ce...a8eec6 )
by Guillermo A.
02:21
created

CreateTableOperation::setPartitionKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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