Test Failed
Branch master (3a0aa4)
by Domenico
03:45
created

CopyItem::handle()   B

Complexity

Conditions 7
Paths 42

Size

Total Lines 47
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 7.251

Importance

Changes 0
Metric Value
eloc 28
dl 0
loc 47
ccs 24
cts 29
cp 0.8276
rs 8.5386
c 0
b 0
f 0
cc 7
nc 42
nop 1
crap 7.251
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\ResultInterface;
15
use Aws\S3\Exception\S3Exception;
16
use Exception;
17
use Matecat\SimpleS3\Commands\CommandHandler;
18
19
class CopyItem extends CommandHandler
20
{
21
    /**
22
     * Copy an item from a bucket to another one.
23
     * For a complete reference:
24
     * https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html?highlight=copy
25
     *
26
     * @param array $params
27
     *
28
     * @return bool
29
     * @throws Exception
30
     */
31 5
    public function handle(array $params = []): bool
32
    {
33 5
        $targetBucketName = $params[ 'target_bucket' ];
34 5
        $targetKeyname    = $params[ 'target' ];
35 5
        $sourceBucket     = $params[ 'source_bucket' ];
36 5
        $sourceKeyname    = $params[ 'source' ];
37
38 5
        $this->client->createBucketIfItDoesNotExist(['bucket' => $targetBucketName]);
39
40 5
        if ($this->client->hasEncoder()) {
41 3
            $targetKeyname = $this->client->getEncoder()->encode($targetKeyname);
42 3
            $sourceKeyname = $this->client->getEncoder()->encode($sourceKeyname);
43
        }
44
45 5
        $copySource = trim($this->getCopySource($sourceBucket, $sourceKeyname));
46
47
        try {
48 5
            $config = [
49 5
                    'Bucket'     => $targetBucketName,
50 5
                    'Key'        => $targetKeyname,
51 5
                    'CopySource' => $copySource,
52 5
            ];
53
54 5
            if ($this->client->isBucketVersioned(['bucket' => $sourceBucket])) {
55 1
                $version                = $this->client->getCurrentItemVersion(['bucket' => $sourceBucket, 'key' => $params[ 'source' ]]);
56 1
                $config[ 'CopySource' ] = $copySource . '?versionId=' . $version;
57
            }
58
59 5
            $copied = $this->client->getConn()->copyObject($config);
60
61 5
            if (($copied instanceof ResultInterface) and $copied[ '@metadata' ][ 'statusCode' ] === 200) {
62 5
                $this->commandHandlerLogger?->log($this, sprintf('File \'%s/%s\' was successfully copied to \'%s/%s\'', $sourceBucket, $sourceKeyname, $targetBucketName, $targetKeyname));
63
64 5
                if ($this->client->hasCache()) {
65 3
                    $this->client->getCache()->set($targetBucketName, $targetKeyname, '');
66
                }
67
68 5
                return true;
69
            }
70
71
            $this->commandHandlerLogger?->log($this, sprintf('Something went wrong in copying file \'%s/%s\'', $sourceBucket, $sourceKeyname), 'warning');
72
73
            return false;
74
        } catch (S3Exception $exception) {
75
            $this->commandHandlerLogger?->logExceptionAndReturnFalse($exception);
76
77
            throw $exception;
78
        }
79
    }
80
81
    /**
82
     * @param array $params
83
     *
84
     * @return bool
85
     */
86 5
    public function validateParams(array $params = []): bool
87
    {
88 5
        return (
89 5
                isset($params[ 'target_bucket' ]) and
90 5
                isset($params[ 'target' ]) and
91 5
                isset($params[ 'source_bucket' ]) and
92 5
                isset($params[ 'source' ])
93 5
        );
94
    }
95
96
    /**
97
     * Returns an urlencoded string for PUT requests
98
     *
99
     * @param string $sourceBucket
100
     * @param string $sourceKeyname
101
     *
102
     * @return string
103
     */
104 8
    protected function getCopySource(string $sourceBucket, string $sourceKeyname): string
105
    {
106 8
        if ($this->client->hasEncoder()) {
107 5
            return $sourceBucket . $this->client->getPrefixSeparator() . $sourceKeyname;
108
        }
109
110 3
        $encoded = [];
111
112 3
        foreach (explode($this->client->getPrefixSeparator(), $sourceKeyname) as $word) {
113 3
            $encoded[] = urlencode($word);
114
        }
115
116 3
        return $sourceBucket . $this->client->getPrefixSeparator() . implode($this->client->getPrefixSeparator(), $encoded);
117
    }
118
}
119