PluginProbe
Media Cloud Sync / 1.4.1
Media Cloud Sync v1.4.1
1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 All 35 releases
media-cloud-sync / includes / sdk / s3 / Aws / S3 / S3ClientTrait.php

S3ClientTrait.php in Media Cloud Sync 1.4.1, at includes/sdk/s3/Aws/S3/S3ClientTrait.php

274 lines 9.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Dudlewebs\WPMCS\s3\Aws\S3;
4
5 use Dudlewebs\WPMCS\s3\Aws\Api\Parser\PayloadParserTrait;
6 use Dudlewebs\WPMCS\s3\Aws\CommandInterface;
7 use Dudlewebs\WPMCS\s3\Aws\Exception\AwsException;
8 use Dudlewebs\WPMCS\s3\Aws\HandlerList;
9 use Dudlewebs\WPMCS\s3\Aws\ResultInterface;
10 use Dudlewebs\WPMCS\s3\Aws\S3\Exception\PermanentRedirectException;
11 use Dudlewebs\WPMCS\s3\Aws\S3\Exception\S3Exception;
12 use Dudlewebs\WPMCS\s3\GuzzleHttp\Promise\PromiseInterface;
13 use Dudlewebs\WPMCS\s3\GuzzleHttp\Promise\RejectedPromise;
14 use Dudlewebs\WPMCS\s3\Psr\Http\Message\ResponseInterface;
15 /**
16 * A trait providing S3-specific functionality. This is meant to be used in
17 * classes implementing \Aws\S3\S3ClientInterface
18 */
19 trait S3ClientTrait
20 {
21 use PayloadParserTrait;
22 /**
23 * @see S3ClientInterface::upload()
24 */
25 public function upload($bucket, $key, $body, $acl = 'private', array $options = [])
26 {
27 return $this->uploadAsync($bucket, $key, $body, $acl, $options)->wait();
28 }
29 /**
30 * @see S3ClientInterface::uploadAsync()
31 */
32 public function uploadAsync($bucket, $key, $body, $acl = 'private', array $options = [])
33 {
34 return (new ObjectUploader($this, $bucket, $key, $body, $acl, $options))->promise();
35 }
36 /**
37 * @see S3ClientInterface::copy()
38 */
39 public function copy($fromB, $fromK, $destB, $destK, $acl = 'private', array $opts = [])
40 {
41 return $this->copyAsync($fromB, $fromK, $destB, $destK, $acl, $opts)->wait();
42 }
43 /**
44 * @see S3ClientInterface::copyAsync()
45 */
46 public function copyAsync($fromB, $fromK, $destB, $destK, $acl = 'private', array $opts = [])
47 {
48 $source = ['Bucket' => $fromB, 'Key' => $fromK];
49 if (isset($opts['version_id'])) {
50 $source['VersionId'] = $opts['version_id'];
51 }
52 $destination = ['Bucket' => $destB, 'Key' => $destK];
53 return (new ObjectCopier($this, $source, $destination, $acl, $opts))->promise();
54 }
55 /**
56 * @see S3ClientInterface::registerStreamWrapper()
57 */
58 public function registerStreamWrapper()
59 {
60 StreamWrapper::register($this);
61 }
62 /**
63 * @see S3ClientInterface::registerStreamWrapperV2()
64 */
65 public function registerStreamWrapperV2()
66 {
67 StreamWrapper::register($this, 's3', null, \true);
68 }
69 /**
70 * @see S3ClientInterface::deleteMatchingObjects()
71 */
72 public function deleteMatchingObjects($bucket, $prefix = '', $regex = '', array $options = [])
73 {
74 $this->deleteMatchingObjectsAsync($bucket, $prefix, $regex, $options)->wait();
75 }
76 /**
77 * @see S3ClientInterface::deleteMatchingObjectsAsync()
78 */
79 public function deleteMatchingObjectsAsync($bucket, $prefix = '', $regex = '', array $options = [])
80 {
81 if (!$prefix && !$regex) {
82 return new RejectedPromise(new \RuntimeException('A prefix or regex is required.'));
83 }
84 $params = ['Bucket' => $bucket, 'Prefix' => $prefix];
85 $iter = $this->getIterator('ListObjects', $params);
86 if ($regex) {
87 $iter = \Dudlewebs\WPMCS\s3\Aws\filter($iter, function ($c) use($regex) {
88 return \preg_match($regex, $c['Key']);
89 });
90 }
91 return BatchDelete::fromIterator($this, $bucket, $iter, $options)->promise();
92 }
93 /**
94 * @see S3ClientInterface::uploadDirectory()
95 */
96 public function uploadDirectory($directory, $bucket, $keyPrefix = null, array $options = [])
97 {
98 $this->uploadDirectoryAsync($directory, $bucket, $keyPrefix, $options)->wait();
99 }
100 /**
101 * @see S3ClientInterface::uploadDirectoryAsync()
102 */
103 public function uploadDirectoryAsync($directory, $bucket, $keyPrefix = null, array $options = [])
104 {
105 $d = "s3://{$bucket}" . ($keyPrefix ? '/' . \ltrim($keyPrefix, '/') : '');
106 return (new Transfer($this, $directory, $d, $options))->promise();
107 }
108 /**
109 * @see S3ClientInterface::downloadBucket()
110 */
111 public function downloadBucket($directory, $bucket, $keyPrefix = '', array $options = [])
112 {
113 $this->downloadBucketAsync($directory, $bucket, $keyPrefix, $options)->wait();
114 }
115 /**
116 * @see S3ClientInterface::downloadBucketAsync()
117 */
118 public function downloadBucketAsync($directory, $bucket, $keyPrefix = '', array $options = [])
119 {
120 $s = "s3://{$bucket}" . ($keyPrefix ? '/' . \ltrim($keyPrefix, '/') : '');
121 return (new Transfer($this, $s, $directory, $options))->promise();
122 }
123 /**
124 * @see S3ClientInterface::determineBucketRegion()
125 */
126 public function determineBucketRegion($bucketName)
127 {
128 return $this->determineBucketRegionAsync($bucketName)->wait();
129 }
130 /**
131 * @see S3ClientInterface::determineBucketRegionAsync()
132 *
133 * @param string $bucketName
134 *
135 * @return PromiseInterface
136 */
137 public function determineBucketRegionAsync($bucketName)
138 {
139 $command = $this->getCommand('HeadBucket', ['Bucket' => $bucketName]);
140 $handlerList = clone $this->getHandlerList();
141 $handlerList->remove('s3.permanent_redirect');
142 $handlerList->remove('signer');
143 $handler = $handlerList->resolve();
144 return $handler($command)->then(static function (ResultInterface $result) {
145 return $result['@metadata']['headers']['x-amz-bucket-region'];
146 }, function (AwsException $e) {
147 $response = $e->getResponse();
148 if ($response === null) {
149 throw $e;
150 }
151 if ($e->getAwsErrorCode() === 'AuthorizationHeaderMalformed') {
152 $region = $this->determineBucketRegionFromExceptionBody($response);
153 if (!empty($region)) {
154 return $region;
155 }
156 throw $e;
157 }
158 return $response->getHeaderLine('x-amz-bucket-region');
159 });
160 }
161 private function determineBucketRegionFromExceptionBody(ResponseInterface $response)
162 {
163 try {
164 $element = $this->parseXml($response->getBody(), $response);
165 if (!empty($element->Region)) {
166 return (string) $element->Region;
167 }
168 } catch (\Exception $e) {
169 // Fallthrough on exceptions from parsing
170 }
171 return \false;
172 }
173 /**
174 * @see S3ClientInterface::doesBucketExist()
175 */
176 public function doesBucketExist($bucket)
177 {
178 return $this->checkExistenceWithCommand($this->getCommand('HeadBucket', ['Bucket' => $bucket]));
179 }
180 /**
181 * @see S3ClientInterface::doesBucketExistV2()
182 */
183 public function doesBucketExistV2($bucket, $accept403 = \false)
184 {
185 $command = $this->getCommand('HeadBucket', ['Bucket' => $bucket]);
186 try {
187 $this->execute($command);
188 return \true;
189 } catch (S3Exception $e) {
190 if ($accept403 && $e->getStatusCode() === 403 || $e instanceof PermanentRedirectException) {
191 return \true;
192 }
193 if ($e->getStatusCode() === 404) {
194 return \false;
195 }
196 throw $e;
197 }
198 }
199 /**
200 * @see S3ClientInterface::doesObjectExist()
201 */
202 public function doesObjectExist($bucket, $key, array $options = [])
203 {
204 return $this->checkExistenceWithCommand($this->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => $key] + $options));
205 }
206 /**
207 * @see S3ClientInterface::doesObjectExistV2()
208 */
209 public function doesObjectExistV2($bucket, $key, $includeDeleteMarkers = \false, array $options = [])
210 {
211 $command = $this->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => $key] + $options);
212 try {
213 $this->execute($command);
214 return \true;
215 } catch (S3Exception $e) {
216 if ($includeDeleteMarkers && $this->useDeleteMarkers($e)) {
217 return \true;
218 }
219 if ($e->getStatusCode() === 404) {
220 return \false;
221 }
222 throw $e;
223 }
224 }
225 private function useDeleteMarkers($exception)
226 {
227 $response = $exception->getResponse();
228 return !empty($response) && $response->getHeader('x-amz-delete-marker');
229 }
230 /**
231 * Determines whether or not a resource exists using a command
232 *
233 * @param CommandInterface $command Command used to poll for the resource
234 *
235 * @return bool
236 * @throws S3Exception|\Exception if there is an unhandled exception
237 */
238 private function checkExistenceWithCommand(CommandInterface $command)
239 {
240 try {
241 $this->execute($command);
242 return \true;
243 } catch (S3Exception $e) {
244 if ($e->getAwsErrorCode() == 'AccessDenied') {
245 return \true;
246 }
247 if ($e->getStatusCode() >= 500) {
248 throw $e;
249 }
250 return \false;
251 }
252 }
253 /**
254 * @see S3ClientInterface::execute()
255 */
256 public abstract function execute(CommandInterface $command);
257 /**
258 * @see S3ClientInterface::getCommand()
259 */
260 public abstract function getCommand($name, array $args = []);
261 /**
262 * @see S3ClientInterface::getHandlerList()
263 *
264 * @return HandlerList
265 */
266 public abstract function getHandlerList();
267 /**
268 * @see S3ClientInterface::getIterator()
269 *
270 * @return \Iterator
271 */
272 public abstract function getIterator($name, array $args = []);
273 }
274