CopyInBatch::handle()   F
last analyzed

Complexity

Conditions 19
Paths 506

Size

Total Lines 99
Code Lines 57

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 323.071

Importance

Changes 0
Metric Value
eloc 57
dl 0
loc 99
ccs 3
cts 54
cp 0.0556
rs 1.0361
c 0
b 0
f 0
cc 19
nc 506
nop 1
crap 323.071

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 *  This file is part of the Simple S3 package.
4
 *
5
 * (c) Mauro Cassani<https://github.com/mauretto78>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 */
11
12
namespace Matecat\SimpleS3\Commands\Handlers;
13
14
use Aws\CommandInterface;
15
use Aws\CommandPool;
16
use Aws\Exception\AwsException;
17
use Aws\ResultInterface;
18
use Exception;
19
use GuzzleHttp\Promise\PromiseInterface;
20
use InvalidArgumentException;
21
22
class CopyInBatch extends CopyItem
23
{
24
    /**
25
     * Copy in batch items from a bucket to another one.
26
     * For a complete reference:
27
     * https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html?highlight=copy
28
     *
29
     * @param array $params
30
     *
31
     * Example:
32
     * $input = [
33
     *      'source_bucket' => 'ORIGINAL-BUCKET',
34
     *      'target_bucket' => 'TARGET-BUCKET', (OPTIONAL)
35
     *      'files' => [
36
     *          'source' => [
37
     *              'keyname-1',
38
     *              'keyname-2',
39
     *          ],
40
     *          'target' => [ (OPTIONAL)
41
     *              'keyname-3',
42
     *              'keyname-4',
43
     *          ],
44
     *      ],
45
     * ];
46
     *
47
     * @return bool
48
     * @throws Exception
49
     */
50 1
    public function handle($params = [])
51
    {
52 1
        if (isset($params['target_bucket'])) {
53 1
            $this->client->createBucketIfItDoesNotExist(['bucket' => $params['target_bucket']]);
54
        }
55
56
        if (empty($params['files']['source'])) {
57
            throw new InvalidArgumentException('source files array cannot be empty.');
58
        }
59
60
        $commands = [];
61
        $errors = [];
62
        $targetKeys = [];
63
        $targetBucket = (isset($params['target_bucket'])) ? $params['target_bucket'] : $params['source_bucket'];
64
65
        foreach ($params['files']['source'] as $key => $file) {
66
            $targetKey  = (isset($params['files']['target'][$key])) ? $params['files']['target'][$key] : $file;
67
            $sourceBucket = $params['source_bucket'];
68
69
            if ($this->client->hasEncoder()) {
70
                $targetKey = $this->client->getEncoder()->encode($targetKey);
71
                $file = $this->client->getEncoder()->encode($file);
72
            }
73
74
            $copySource = $this->getCopySource($sourceBucket, $file);
75
            $targetKeys[] = $targetKey;
76
77
            $config = [
78
                'Bucket' => $targetBucket,
79
                'Key'    => $targetKey,
80
                'CopySource' => $copySource,
81
            ];
82
83
            if ($this->client->isBucketVersioned(['bucket' => $sourceBucket])) {
84
                $version = $this->client->getCurrentItemVersion(['bucket' => $sourceBucket, 'key' => $params['source']]);
85
                $config['CopySource'] = $copySource . '?versionId='.$version;
86
            }
87
88
            $commands[] = $this->client->getConn()->getCommand('CopyObject', $config);
89
        }
90
91
        try {
92
            // Create a pool and provide an optional array of configuration
93
            $pool = new CommandPool($this->client->getConn(), $commands, [
94
                'concurrency' => (isset($params['concurrency'])) ? $params['concurrency'] : 25,
95
                'before' => function (CommandInterface $cmd, $iterKey) {
96
                    if (null !== $this->commandHandlerLogger) {
97
                        $this->commandHandlerLogger->log($this, sprintf('About to send \'%s\'', $iterKey));
98
                    }
99
                },
100
                // Invoke this function for each successful transfer
101
                'fulfilled' => function (
102
                    ResultInterface $result,
103
                    $iterKey
104
                ) use ($targetBucket, $targetKeys) {
105
                    if (null !== $this->commandHandlerLogger) {
106
                        $this->commandHandlerLogger->log($this, sprintf('Completed copy of \'%s\'', $targetKeys[$iterKey]));
107
                    }
108
109
                    if ($this->client->hasCache()) {
110
                        $this->client->getCache()->set($targetBucket, $targetKeys[$iterKey], '');
111
                    }
112
                },
113
                // Invoke this function for each failed transfer
114
                'rejected' => function (
115
                    AwsException $reason
116
                ) use (&$errors) {
117
                    $errors[] = $reason;
118
119
                    if (null !== $this->commandHandlerLogger) {
120
                        $this->commandHandlerLogger->logExceptionAndReturnFalse($reason);
121
                    }
122
123
                    throw $reason;
124
                },
125
            ]);
126
127
            // Initiate the pool transfers and waits it ends
128
            $pool->promise()->wait();
129
130
            if (count($errors) === 0) {
131
                if (null !== $this->commandHandlerLogger) {
132
                    $this->commandHandlerLogger->log($this, sprintf('Copy in batch from \'%s\' to \'%s\' was succeded without errors', $params['source_bucket'], $targetBucket));
133
                }
134
135
                return true;
136
            }
137
138
            if (null !== $this->commandHandlerLogger) {
139
                $this->commandHandlerLogger->log($this, sprintf('Something went wrong during copying in batch from \'%s\' to \'%s\'', $params['source_bucket'], (isset($params['target_bucket'])) ? $params['target_bucket'] : $params['source_bucket']), 'warning');
140
            }
141
142
            return false;
143
        } catch (Exception $e) {
144
            if (null !== $this->commandHandlerLogger) {
145
                $this->commandHandlerLogger->logExceptionAndReturnFalse($e);
146
            }
147
148
            throw $e;
149
        }
150
    }
151
152
    /**
153
     * @param array $params
154
     *
155
     * @return bool
156
     */
157 1
    public function validateParams($params = [])
158
    {
159
        return (
160 1
            isset($params['source_bucket']) and
161 1
            isset($params['files']['source'])
162
        );
163
    }
164
}
165