diff options
author | Andrew Dolgov <[email protected]> | 2022-11-23 21:14:33 +0300 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2022-11-23 21:14:33 +0300 |
commit | 0c8af4992cb0f7589dcafaad65ada12753c64594 (patch) | |
tree | 18e83d068c3e7dd2499331de977782b382279396 /vendor/aws/aws-sdk-php/src/S3/BatchDelete.php |
initial
Diffstat (limited to 'vendor/aws/aws-sdk-php/src/S3/BatchDelete.php')
-rw-r--r-- | vendor/aws/aws-sdk-php/src/S3/BatchDelete.php | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/vendor/aws/aws-sdk-php/src/S3/BatchDelete.php b/vendor/aws/aws-sdk-php/src/S3/BatchDelete.php new file mode 100644 index 0000000..9243911 --- /dev/null +++ b/vendor/aws/aws-sdk-php/src/S3/BatchDelete.php @@ -0,0 +1,240 @@ +<?php +namespace Aws\S3; + +use Aws\AwsClientInterface; +use Aws\S3\Exception\DeleteMultipleObjectsException; +use GuzzleHttp\Promise; +use GuzzleHttp\Promise\PromisorInterface; +use GuzzleHttp\Promise\PromiseInterface; + +/** + * Efficiently deletes many objects from a single Amazon S3 bucket using an + * iterator that yields keys. Deletes are made using the DeleteObjects API + * operation. + * + * $s3 = new Aws\S3\Client([ + * 'region' => 'us-west-2', + * 'version' => 'latest' + * ]); + * + * $listObjectsParams = ['Bucket' => 'foo', 'Prefix' => 'starts/with/']; + * $delete = Aws\S3\BatchDelete::fromListObjects($s3, $listObjectsParams); + * // Asynchronously delete + * $promise = $delete->promise(); + * // Force synchronous completion + * $delete->delete(); + * + * When using one of the batch delete creational static methods, you can supply + * an associative array of options: + * + * - before: Function invoked before executing a command. The function is + * passed the command that is about to be executed. This can be useful + * for logging, adding custom request headers, etc. + * - batch_size: The size of each delete batch. Defaults to 1000. + * + * @link http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html + */ +class BatchDelete implements PromisorInterface +{ + private $bucket; + /** @var AwsClientInterface */ + private $client; + /** @var callable */ + private $before; + /** @var PromiseInterface */ + private $cachedPromise; + /** @var callable */ + private $promiseCreator; + private $batchSize = 1000; + private $queue = []; + + /** + * Creates a BatchDelete object from all of the paginated results of a + * ListObjects operation. Each result that is returned by the ListObjects + * operation will be deleted. + * + * @param AwsClientInterface $client AWS Client to use. + * @param array $listObjectsParams ListObjects API parameters + * @param array $options BatchDelete options. + * + * @return BatchDelete + */ + public static function fromListObjects( + AwsClientInterface $client, + array $listObjectsParams, + array $options = [] + ) { + $iter = $client->getPaginator('ListObjects', $listObjectsParams); + $bucket = $listObjectsParams['Bucket']; + $fn = function (BatchDelete $that) use ($iter) { + return $iter->each(function ($result) use ($that) { + $promises = []; + if (is_array($result['Contents'])) { + foreach ($result['Contents'] as $object) { + if ($promise = $that->enqueue($object)) { + $promises[] = $promise; + } + } + } + return $promises ? Promise\Utils::all($promises) : null; + }); + }; + + return new self($client, $bucket, $fn, $options); + } + + /** + * Creates a BatchDelete object from an iterator that yields results. + * + * @param AwsClientInterface $client AWS Client to use to execute commands + * @param string $bucket Bucket where the objects are stored + * @param \Iterator $iter Iterator that yields assoc arrays + * @param array $options BatchDelete options + * + * @return BatchDelete + */ + public static function fromIterator( + AwsClientInterface $client, + $bucket, + \Iterator $iter, + array $options = [] + ) { + $fn = function (BatchDelete $that) use ($iter) { + return Promise\Coroutine::of(function () use ($that, $iter) { + foreach ($iter as $obj) { + if ($promise = $that->enqueue($obj)) { + yield $promise; + } + } + }); + }; + + return new self($client, $bucket, $fn, $options); + } + + /** + * @return PromiseInterface + */ + public function promise() + { + if (!$this->cachedPromise) { + $this->cachedPromise = $this->createPromise(); + } + + return $this->cachedPromise; + } + + /** + * Synchronously deletes all of the objects. + * + * @throws DeleteMultipleObjectsException on error. + */ + public function delete() + { + $this->promise()->wait(); + } + + /** + * @param AwsClientInterface $client Client used to transfer the requests + * @param string $bucket Bucket to delete from. + * @param callable $promiseFn Creates a promise. + * @param array $options Hash of options used with the batch + * + * @throws \InvalidArgumentException if the provided batch_size is <= 0 + */ + private function __construct( + AwsClientInterface $client, + $bucket, + callable $promiseFn, + array $options = [] + ) { + $this->client = $client; + $this->bucket = $bucket; + $this->promiseCreator = $promiseFn; + + if (isset($options['before'])) { + if (!is_callable($options['before'])) { + throw new \InvalidArgumentException('before must be callable'); + } + $this->before = $options['before']; + } + + if (isset($options['batch_size'])) { + if ($options['batch_size'] <= 0) { + throw new \InvalidArgumentException('batch_size is not > 0'); + } + $this->batchSize = min($options['batch_size'], 1000); + } + } + + private function enqueue(array $obj) + { + $this->queue[] = $obj; + return count($this->queue) >= $this->batchSize + ? $this->flushQueue() + : null; + } + + private function flushQueue() + { + static $validKeys = ['Key' => true, 'VersionId' => true]; + + if (count($this->queue) === 0) { + return null; + } + + $batch = []; + while ($obj = array_shift($this->queue)) { + $batch[] = array_intersect_key($obj, $validKeys); + } + + $command = $this->client->getCommand('DeleteObjects', [ + 'Bucket' => $this->bucket, + 'Delete' => ['Objects' => $batch] + ]); + + if ($this->before) { + call_user_func($this->before, $command); + } + + return $this->client->executeAsync($command) + ->then(function ($result) { + if (!empty($result['Errors'])) { + throw new DeleteMultipleObjectsException( + $result['Deleted'] ?: [], + $result['Errors'] + ); + } + return $result; + }); + } + + /** + * Returns a promise that will clean up any references when it completes. + * + * @return PromiseInterface + */ + private function createPromise() + { + // Create the promise + $promise = call_user_func($this->promiseCreator, $this); + $this->promiseCreator = null; + + // Cleans up the promise state and references. + $cleanup = function () { + $this->before = $this->client = $this->queue = null; + }; + + // When done, ensure cleanup and that any remaining are processed. + return $promise->then( + function () use ($cleanup) { + return Promise\Create::promiseFor($this->flushQueue()) + ->then($cleanup); + }, + function ($reason) use ($cleanup) { + $cleanup(); + return Promise\Create::rejectionFor($reason); + } + ); + } +} |