UploadItem   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 127
Duplicated Lines 0 %

Test Coverage

Coverage 30.56%

Importance

Changes 0
Metric Value
wmc 24
eloc 54
dl 0
loc 127
ccs 11
cts 36
cp 0.3056
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
C multipartUpload() 0 59 13
A validateParams() 0 6 3
B handle() 0 27 8
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\Exception\MultipartUploadException;
16
use Aws\ResultInterface;
17
use Aws\S3\MultipartUploader;
18
use Matecat\SimpleS3\Commands\CommandHandler;
19
use Matecat\SimpleS3\Components\Validators\S3ObjectSafeNameValidator;
20
use Matecat\SimpleS3\Components\Validators\S3StorageClassNameValidator;
21
use Matecat\SimpleS3\Exceptions\InvalidS3NameException;
22
use Matecat\SimpleS3\Helpers\File;
23
24
class UploadItem extends CommandHandler
25
{
26
    const MAX_FILESIZE = 6291456; // 6 Mb
27
28
    /**
29
     * Upload a file to S3.
30
     * Il filesize is > 6Mb a multipart upload is performed.
31
     * For a complete reference of put object see:
32
     * https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html?highlight=put
33
     *
34
     * @param array $params
35
     *
36
     * @return bool
37
     * @throws \Exception
38
     */
39 1
    public function handle($params = [])
40
    {
41 1
        $bucketName = $params['bucket'];
42 1
        $keyName = $params['key'];
43 1
        $source = $params['source'];
44
45 1
        if (isset($params['bucket_check']) and true === $params['bucket_check']) {
46
            $this->client->createBucketIfItDoesNotExist(['bucket' => $bucketName]);
47
        }
48
49 1
        if (false === S3ObjectSafeNameValidator::isValid($keyName)) {
50 1
            throw new InvalidS3NameException(sprintf('%s is not a valid S3 object name. ['.implode(', ', S3ObjectSafeNameValidator::validate($keyName)).']', $keyName));
51
        }
52
53
        if ((isset($params['storage']) and false === S3StorageClassNameValidator::isValid($params['storage']))) {
54
            throw new \InvalidArgumentException(S3StorageClassNameValidator::validate($params['storage'])[0]);
55
        }
56
57
        if (File::getSize($source) > self::MAX_FILESIZE) {
58
            return $this->multipartUpload($bucketName, $keyName, $source, $params);
59
        }
60
61
        return (new UploadItemFromBody($this->client))->handle([
62
            'bucket' => $bucketName,
63
            'key' => $keyName,
64
            'body' => File::open($source),
65
            'storage' => (isset($params['storage'])) ? $params['storage'] : null
66
        ]);
67
    }
68
69
    /**
70
     * @param array $params
71
     *
72
     * @return bool
73
     */
74 1
    public function validateParams($params = [])
75
    {
76
        return (
77 1
            isset($params['bucket']) and
78 1
            isset($params['key']) and
79 1
            isset($params['source'])
80
        );
81
    }
82
83
    /**
84
     * @param string $bucketName
85
     * @param string $keyName
86
     * @param string $source
87
     * @param array $params
88
     *
89
     * @return bool
90
     * @throws \Exception
91
     */
92
    private function multipartUpload($bucketName, $keyName, $source, $params = [])
93
    {
94
        $uploader = new MultipartUploader(
95
            $this->client->getConn(),
96
            $source,
97
            [
98
                'bucket' => $bucketName,
99
                'key'    => $keyName,
100
                'before_initiate' => function (CommandInterface $command) use ($source, $params, $keyName) {
101
                    if (extension_loaded('fileinfo')) {
102
                        $command['ContentType'] = File::getMimeType($source);
103
                    }
104
105
                    if ((isset($params['storage']))) {
106
                        $command['StorageClass'] = $params['storage'];
107
                    }
108
109
                    if ((isset($params['Metadata']))) {
110
                        $command['Metadata'] = $params['meta'];
111
                    }
112
113
                    $command['Metadata'][ 'original_name'] = File::getBaseName($keyName);
114
                    $command['MetadataDirective'] =  'REPLACE';
115
                }
116
            ]
117
        );
118
119
        try {
120
            $upload = $uploader->upload();
121
122
            if (($upload instanceof ResultInterface) and $upload['@metadata']['statusCode'] === 200) {
123
                if (null !== $this->commandHandlerLogger) {
124
                    $this->commandHandlerLogger->log($this, sprintf('File \'%s\' was successfully uploaded in \'%s\' bucket', $keyName, $bucketName));
125
                }
126
127
                return true;
128
            }
129
130
            if (null !== $this->commandHandlerLogger) {
131
                $this->commandHandlerLogger->log($this, sprintf('Something went wrong during upload of file \'%s\' in \'%s\' bucket', $keyName, $bucketName), 'warning');
132
            }
133
134
            // update cache
135
            if ((!isset($params['storage'])) and $this->client->hasCache()) {
136
                $version = null;
137
                if (isset($upload['@metadata']['headers']['x-amz-version-id'])) {
138
                    $version = $upload['@metadata']['headers']['x-amz-version-id'];
139
                }
140
141
                $this->client->getCache()->set($bucketName, $keyName, '', $version);
142
            }
143
144
            return false;
145
        } catch (MultipartUploadException $e) {
146
            if (null !== $this->commandHandlerLogger) {
147
                $this->commandHandlerLogger->logExceptionAndReturnFalse($e);
148
            }
149
150
            throw $e;
151
        }
152
    }
153
}
154