S3ClientTrait.php 7.5 KB

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