Test Failed
Push — master ( a92e12...446184 )
by Domenico
04:27
created

GetItemsInABucket::handle()   C

Complexity

Conditions 13
Paths 87

Size

Total Lines 38
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 15.2016

Importance

Changes 0
Metric Value
eloc 18
dl 0
loc 38
ccs 13
cts 17
cp 0.7647
rs 6.6166
c 0
b 0
f 0
cc 13
nc 87
nop 1
crap 15.2016

How to fix   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\S3\Exception\S3Exception;
15
use Matecat\SimpleS3\Commands\CommandHandler;
16
use Matecat\SimpleS3\Helpers\File;
17
18
class GetItemsInABucket extends CommandHandler
19
{
20
    /**
21
     * Get the list of keys in a bucket.
22
     * If 'hydrate' parameter is set to true, an array of hydrated Aws\Result is returned instead.
23
     *
24
     * @param array $params
25
     *
26
     * @return array|mixed
27
     * @throws \Exception
28
     */
29 18
    public function handle($params = [])
30
    {
31 18
        $bucketName = $params['bucket'];
32
33
        try {
34
            $config = [
35 18
                'Bucket' => $bucketName,
36
            ];
37
38 18
            if (isset($params['prefix'])) {
39
40
                // add a final slash to prefix
41 10
                if (false === File::endsWith($params['prefix'], $this->client->getPrefixSeparator())) {
42 8
                    $params['prefix'] .= $this->client->getPrefixSeparator();
43
                }
44
45 10
                $config['Delimiter'] = (isset($params['delimiter'])) ? $params['delimiter'] : $this->client->getPrefixSeparator();
46 10
                $config['Prefix'] = $params['prefix'];
47
            }
48
49
            // 1. If 'exclude-cache' is set, return records always from S3
50 18
            if (isset($params['exclude-cache']) and true === $params['exclude-cache']) {
51 2
                return $this->returnItemsFromS3($bucketName, $config, (isset($params['hydrate'])) ? $params['hydrate'] : null);
52
            }
53
54
            // 2. If the cache is set and there is a prefix, return records from cache
55 16
            if ($this->client->hasCache() and isset($config['Prefix'])) {
56 7
                return $this->returnItemsFromCache($bucketName, $config, (isset($params['hydrate'])) ? $params['hydrate'] : null);
57
            }
58
59
            // 3. Otherwise, return records from S3
60 9
            return $this->returnItemsFromS3($bucketName, $config, (isset($params['hydrate'])) ? $params['hydrate'] : null);
61
        } catch (S3Exception $e) {
62
            if (null !== $this->commandHandlerLogger) {
63
                $this->commandHandlerLogger->logExceptionAndReturnFalse($e);
64
            }
65
66
            throw $e;
67
        }
68
    }
69
70
    /**
71
     * @param array $params
72
     *
73
     * @return bool
74
     */
75 18
    public function validateParams($params = [])
76
    {
77 18
        return (isset($params['bucket']));
78
    }
79
80
    /**
81
     * @param string $bucketName
82
     * @param array $config
83
     * @param null $hydrate
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $hydrate is correct as it would always require null to be passed?
Loading history...
84
     *
85
     * @return array
86
     */
87 7
    protected function returnItemsFromCache($bucketName, $config, $hydrate = null)
88
    {
89 7
        $itemsFromCache = $this->client->getCache()->search($bucketName, $config['Prefix']);
90
91
        // no data was found, try to retrieve data from S3
92 7
        if (count($itemsFromCache) == 0) {
93
            return $this->returnItemsFromS3($bucketName, $config, $hydrate);
94
        }
95
96
        // no hydrate, simply return the array of keys stored in redis
97 7
        if (null == $hydrate) {
0 ignored issues
show
introduced by
The condition null == $hydrate is always true.
Loading history...
98 5
            if (null !== $this->commandHandlerLogger) {
99 5
                $this->commandHandlerLogger->log($this, sprintf('Files of \'%s\' bucket were successfully obtained from CACHE', $bucketName));
100
            }
101
102 5
            return $itemsFromCache;
103
        }
104
105
        // hydrate the key with the entire AWS\Result Object
106 2
        $items = [];
107 2
        foreach ($itemsFromCache as $key) {
108 2
            $version = null;
109 2
            $originalKey = $key;
110
111 2
            if (strpos($key, '<VERSION_ID:') !== false) {
112 1
                $v = explode('<VERSION_ID:', $key);
113 1
                $version = str_replace('>', '', $v[1]);
114 1
                $key = $v[0];
115
            }
116
117 2
            if ($this->client->hasEncoder()) {
118 2
                $key = $this->client->getEncoder()->decode($key);
119
            }
120
121 2
            $items[$originalKey] = $this->client->getItem(['bucket' => $bucketName, 'key' => $key, 'version' => $version]);
122
        }
123
124 2
        if (null !== $this->commandHandlerLogger) {
125 2
            $this->commandHandlerLogger->log($this, sprintf('Files of \'%s\' bucket were successfully obtained from CACHE', $bucketName));
126
        }
127
128 2
        return $items;
129
    }
130
131
    /**
132
     * @param string $bucketName
133
     * @param array $config
134
     *
135
     * @return array
136
     */
137 11
    protected function returnItemsFromS3($bucketName, $config, $hydrate = null)
138
    {
139 11
        if ($this->client->isBucketVersioned(['bucket' => $bucketName])) {
140 1
            return $this->returnVersionedItemsFromS3($bucketName, $config, $hydrate);
141
        }
142
143 11
        $resultPaginator = $this->client->getConn()->getPaginator('ListObjects', $config);
144 11
        $items = [];
145
146 11
        foreach ($resultPaginator as $result) {
147 11
            if (is_array($contents = $result->get('Contents'))) {
148 9
                for ($i = 0; $i < count($contents); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
149 9
                    $key = $contents[$i]['Key'];
150
151 9
                    if (false === File::endsWith($key, $this->client->getPrefixSeparator())) {
152 9
                        if ($this->client->hasEncoder()) {
153 6
                            $key = $this->client->getEncoder()->decode($key);
154
                        }
155
156 9
                        if (null != $hydrate and true === $hydrate) {
157 2
                            $items[$key] = $this->client->getItem(['bucket' => $bucketName, 'key' => $key]);
158
                        } else {
159 7
                            $items[] = $key;
160
                        }
161
162
                        // send to cache, just to be sure that S3 is syncronized with cache
163 9
                        if ($this->client->hasCache()) {
164 6
                            $this->client->getCache()->set($bucketName, $contents[$i]['Key'], $this->client->getItem(['bucket' => $bucketName, 'key' => $key]));
165
                        }
166
                    }
167
                }
168
            }
169
        }
170
171 11
        if (null !== $this->commandHandlerLogger) {
172 10
            $this->commandHandlerLogger->log($this, sprintf('Files were successfully obtained from \'%s\' bucket', $bucketName));
173
        }
174
175 11
        return $items;
176
    }
177
178
    /**
179
     * @param string $bucketName
180
     * @param array $config
181
     * @param null $hydrate
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $hydrate is correct as it would always require null to be passed?
Loading history...
182
     *
183
     * @return array
184
     */
185 1
    protected function returnVersionedItemsFromS3($bucketName, $config, $hydrate = null)
186
    {
187 1
        $results = $this->client->getConn()->listObjectVersions($config);
188 1
        $items = [];
189
190 1
        if (false === isset($results['Versions'])) {
191
            return $items;
192
        }
193
194 1
        foreach ($results['Versions'] as $result) {
195 1
            $key = $result['Key'];
196 1
            $version = $result['VersionId'];
197
198 1
            if (false === File::endsWith($key, $this->client->getPrefixSeparator())) {
199 1
                if ($this->client->hasEncoder()) {
200 1
                    $key = $this->client->getEncoder()->decode($key);
201
                }
202
203 1
                $index = $key.'<VERSION_ID:'.$version.'>';
204
205 1
                if (null != $hydrate and true === $hydrate) {
206
                    $items[$index] = $this->client->getItem(['bucket' => $bucketName, 'key' => $key, 'version' => $version]);
207
                } else {
208 1
                    $items[] = $index;
209
                }
210
211
                // send to cache, just to be sure that S3 is syncronized with cache
212 1
                if ($this->client->hasCache()) {
213 1
                    $this->client->getCache()->set($bucketName, $result['Key'], $this->client->getItem(['bucket' => $bucketName, 'key' => $key, 'version' => $version]), $version);
214
                }
215
            }
216
        }
217
218 1
        if (null !== $this->commandHandlerLogger) {
219 1
            $this->commandHandlerLogger->log($this, sprintf('Files (versioned) were successfully obtained from \'%s\' bucket', $bucketName));
220
        }
221
222 1
        return $items;
223
    }
224
}
225