| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 | 
							- <?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(): PromiseInterface
 
-     {
 
-         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);
 
-             }
 
-         );
 
-     }
 
- }
 
 
  |