Test Failed
Branch master (3a0aa4)
by Domenico
16:55
created

CopyInBatch::handle()   C

Complexity

Conditions 13
Paths 254

Size

Total Lines 87
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 151.6732

Importance

Changes 0
Metric Value
eloc 51
dl 0
loc 87
ccs 3
cts 47
cp 0.0638
rs 5.1083
c 0
b 0
f 0
cc 13
nc 254
nop 1
crap 151.6732

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