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 / ObjectCopier.php

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

120 lines 5.4 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\Arn\ArnParser;
6 use Dudlewebs\WPMCS\s3\Aws\Arn\S3\AccessPointArn;
7 use Dudlewebs\WPMCS\s3\Aws\Exception\MultipartUploadException;
8 use Dudlewebs\WPMCS\s3\Aws\Result;
9 use Dudlewebs\WPMCS\s3\Aws\S3\Exception\S3Exception;
10 use Dudlewebs\WPMCS\s3\GuzzleHttp\Promise\Coroutine;
11 use Dudlewebs\WPMCS\s3\GuzzleHttp\Promise\PromiseInterface;
12 use Dudlewebs\WPMCS\s3\GuzzleHttp\Promise\PromisorInterface;
13 use InvalidArgumentException;
14 /**
15 * Copies objects from one S3 location to another, utilizing a multipart copy
16 * when appropriate.
17 */
18 class ObjectCopier implements PromisorInterface
19 {
20 const DEFAULT_MULTIPART_THRESHOLD = MultipartUploader::PART_MAX_SIZE;
21 private $client;
22 private $source;
23 private $destination;
24 private $acl;
25 private $options;
26 private static $defaults = ['before_lookup' => null, 'before_upload' => null, 'concurrency' => 5, 'mup_threshold' => self::DEFAULT_MULTIPART_THRESHOLD, 'params' => [], 'part_size' => null, 'version_id' => null];
27 /**
28 * @param S3ClientInterface $client The S3 Client used to execute
29 * the copy command(s).
30 * @param array $source The object to copy, specified as
31 * an array with a 'Bucket' and
32 * 'Key' keys. Provide a
33 * 'VersionID' key to copy a
34 * specified version of an object.
35 * @param array $destination The bucket and key to which to
36 * copy the $source, specified as
37 * an array with a 'Bucket' and
38 * 'Key' keys.
39 * @param string $acl ACL to apply to the copy
40 * (default: private).
41 * @param array $options Options used to configure the
42 * copy process. Options passed in
43 * through 'params' are added to
44 * the sub commands.
45 *
46 * @throws InvalidArgumentException
47 */
48 public function __construct(S3ClientInterface $client, array $source, array $destination, $acl = 'private', array $options = [])
49 {
50 $this->validateLocation($source);
51 $this->validateLocation($destination);
52 $this->client = $client;
53 $this->source = $source;
54 $this->destination = $destination;
55 $this->acl = $acl;
56 $this->options = $options + self::$defaults;
57 }
58 /**
59 * Perform the configured copy asynchronously. Returns a promise that is
60 * fulfilled with the result of the CompleteMultipartUpload or CopyObject
61 * operation or rejected with an exception.
62 *
63 * @return Coroutine
64 */
65 public function promise() : PromiseInterface
66 {
67 return Coroutine::of(function () {
68 $headObjectCommand = $this->client->getCommand('HeadObject', $this->options['params'] + $this->source);
69 if (\is_callable($this->options['before_lookup'])) {
70 $this->options['before_lookup']($headObjectCommand);
71 }
72 $objectStats = (yield $this->client->executeAsync($headObjectCommand));
73 if ($objectStats['ContentLength'] > $this->options['mup_threshold']) {
74 $mup = new MultipartCopy($this->client, $this->getSourcePath(), ['source_metadata' => $objectStats, 'acl' => $this->acl] + $this->destination + $this->options);
75 (yield $mup->promise());
76 } else {
77 $defaults = ['ACL' => $this->acl, 'MetadataDirective' => 'COPY', 'CopySource' => $this->getSourcePath()];
78 $params = \array_diff_key($this->options, self::$defaults) + $this->destination + $defaults + $this->options['params'];
79 (yield $this->client->executeAsync($this->client->getCommand('CopyObject', $params)));
80 }
81 });
82 }
83 /**
84 * Perform the configured copy synchronously. Returns the result of the
85 * CompleteMultipartUpload or CopyObject operation.
86 *
87 * @return Result
88 *
89 * @throws S3Exception
90 * @throws MultipartUploadException
91 */
92 public function copy()
93 {
94 return $this->promise()->wait();
95 }
96 private function validateLocation(array $location)
97 {
98 if (empty($location['Bucket']) || empty($location['Key'])) {
99 throw new \InvalidArgumentException('Locations provided to an' . ' Aws\\S3\\ObjectCopier must have a non-empty Bucket and Key');
100 }
101 }
102 private function getSourcePath()
103 {
104 $path = "/{$this->source['Bucket']}/";
105 if (ArnParser::isArn($this->source['Bucket'])) {
106 try {
107 new AccessPointArn($this->source['Bucket']);
108 $path = "{$this->source['Bucket']}/object/";
109 } catch (\Exception $e) {
110 throw new \InvalidArgumentException('Provided ARN was a not a valid S3 access point ARN (' . $e->getMessage() . ')', 0, $e);
111 }
112 }
113 $sourcePath = $path . \rawurlencode($this->source['Key']);
114 if (isset($this->source['VersionId'])) {
115 $sourcePath .= "?versionId={$this->source['VersionId']}";
116 }
117 return $sourcePath;
118 }
119 }
120