| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 | <?phpnamespace Aws\S3;use Aws\Api\Parser\PayloadParserTrait;use Aws\CommandInterface;use Aws\Exception\AwsException;use Aws\HandlerList;use Aws\ResultInterface;use Aws\S3\Exception\PermanentRedirectException;use Aws\S3\Exception\S3Exception;use GuzzleHttp\Promise\PromiseInterface;use GuzzleHttp\Promise\RejectedPromise;use Psr\Http\Message\ResponseInterface;/** * A trait providing S3-specific functionality. This is meant to be used in * classes implementing \Aws\S3\S3ClientInterface */trait S3ClientTrait{    use PayloadParserTrait;    /**     * @see S3ClientInterface::upload()     */    public function upload(        $bucket,        $key,        $body,        $acl = 'private',        array $options = []    ) {        return $this            ->uploadAsync($bucket, $key, $body, $acl, $options)            ->wait();    }    /**     * @see S3ClientInterface::uploadAsync()     */    public function uploadAsync(        $bucket,        $key,        $body,        $acl = 'private',        array $options = []    ) {        return (new ObjectUploader($this, $bucket, $key, $body, $acl, $options))            ->promise();    }    /**     * @see S3ClientInterface::copy()     */    public function copy(        $fromB,        $fromK,        $destB,        $destK,        $acl = 'private',        array $opts = []    ) {        return $this->copyAsync($fromB, $fromK, $destB, $destK, $acl, $opts)            ->wait();    }    /**     * @see S3ClientInterface::copyAsync()     */    public function copyAsync(        $fromB,        $fromK,        $destB,        $destK,        $acl = 'private',        array $opts = []    ) {        $source = [            'Bucket' => $fromB,            'Key' => $fromK,        ];        if (isset($opts['version_id'])) {            $source['VersionId'] = $opts['version_id'];        }        $destination = [            'Bucket' => $destB,            'Key' => $destK        ];        return (new ObjectCopier($this, $source, $destination, $acl, $opts))            ->promise();    }    /**     * @see S3ClientInterface::registerStreamWrapper()     */    public function registerStreamWrapper()    {        StreamWrapper::register($this);    }    /**     * @see S3ClientInterface::registerStreamWrapperV2()     */    public function registerStreamWrapperV2()    {        StreamWrapper::register(            $this,            's3',            null,            true        );    }    /**     * @see S3ClientInterface::deleteMatchingObjects()     */    public function deleteMatchingObjects(        $bucket,        $prefix = '',        $regex = '',        array $options = []    ) {        $this->deleteMatchingObjectsAsync($bucket, $prefix, $regex, $options)            ->wait();    }    /**     * @see S3ClientInterface::deleteMatchingObjectsAsync()     */    public function deleteMatchingObjectsAsync(        $bucket,        $prefix = '',        $regex = '',        array $options = []    ) {        if (!$prefix && !$regex) {            return new RejectedPromise(                new \RuntimeException('A prefix or regex is required.')            );        }        $params = ['Bucket' => $bucket, 'Prefix' => $prefix];        $iter = $this->getIterator('ListObjects', $params);        if ($regex) {            $iter = \Aws\filter($iter, function ($c) use ($regex) {                return preg_match($regex, $c['Key']);            });        }        return BatchDelete::fromIterator($this, $bucket, $iter, $options)            ->promise();    }    /**     * @see S3ClientInterface::uploadDirectory()     */    public function uploadDirectory(        $directory,        $bucket,        $keyPrefix = null,        array $options = []    ) {        $this->uploadDirectoryAsync($directory, $bucket, $keyPrefix, $options)            ->wait();    }    /**     * @see S3ClientInterface::uploadDirectoryAsync()     */    public function uploadDirectoryAsync(        $directory,        $bucket,        $keyPrefix = null,        array $options = []    ) {        $d = "s3://$bucket" . ($keyPrefix ? '/' . ltrim($keyPrefix, '/') : '');        return (new Transfer($this, $directory, $d, $options))->promise();    }    /**     * @see S3ClientInterface::downloadBucket()     */    public function downloadBucket(        $directory,        $bucket,        $keyPrefix = '',        array $options = []    ) {        $this->downloadBucketAsync($directory, $bucket, $keyPrefix, $options)            ->wait();    }    /**     * @see S3ClientInterface::downloadBucketAsync()     */    public function downloadBucketAsync(        $directory,        $bucket,        $keyPrefix = '',        array $options = []    ) {        $s = "s3://$bucket" . ($keyPrefix ? '/' . ltrim($keyPrefix, '/') : '');        return (new Transfer($this, $s, $directory, $options))->promise();    }    /**     * @see S3ClientInterface::determineBucketRegion()     */    public function determineBucketRegion($bucketName)    {        return $this->determineBucketRegionAsync($bucketName)->wait();    }    /**     * @see S3ClientInterface::determineBucketRegionAsync()     *     * @param string $bucketName     *     * @return PromiseInterface     */    public function determineBucketRegionAsync($bucketName)    {        $command = $this->getCommand('HeadBucket', ['Bucket' => $bucketName]);        $handlerList = clone $this->getHandlerList();        $handlerList->remove('s3.permanent_redirect');        $handlerList->remove('signer');        $handler = $handlerList->resolve();        return $handler($command)            ->then(static function (ResultInterface $result) {                return $result['@metadata']['headers']['x-amz-bucket-region'];            }, function (AwsException $e) {                $response = $e->getResponse();                if ($response === null) {                    throw $e;                }                if ($e->getAwsErrorCode() === 'AuthorizationHeaderMalformed') {                    $region = $this->determineBucketRegionFromExceptionBody(                        $response                    );                    if (!empty($region)) {                        return $region;                    }                    throw $e;                }                return $response->getHeaderLine('x-amz-bucket-region');            });    }    private function determineBucketRegionFromExceptionBody(ResponseInterface $response)    {        try {            $element = $this->parseXml($response->getBody(), $response);            if (!empty($element->Region)) {                return (string)$element->Region;            }        } catch (\Exception $e) {            // Fallthrough on exceptions from parsing        }        return false;    }    /**     * @see S3ClientInterface::doesBucketExist()     */    public function doesBucketExist($bucket)    {        return $this->checkExistenceWithCommand(            $this->getCommand('HeadBucket', ['Bucket' => $bucket])        );    }    /**     * @see S3ClientInterface::doesBucketExistV2()     */    public function doesBucketExistV2($bucket, $accept403 = false)    {        $command = $this->getCommand('HeadBucket', ['Bucket' => $bucket]);        try {            $this->execute($command);            return true;        } catch (S3Exception $e) {            if (                ($accept403 && $e->getStatusCode() === 403)                || $e instanceof PermanentRedirectException            ) {                return true;            }            if ($e->getStatusCode() === 404)  {                return false;            }            throw $e;        }    }    /**     * @see S3ClientInterface::doesObjectExist()     */    public function doesObjectExist($bucket, $key, array $options = [])    {        return $this->checkExistenceWithCommand(            $this->getCommand('HeadObject', [                    'Bucket' => $bucket,                    'Key'    => $key                ] + $options)        );    }    /**     * @see S3ClientInterface::doesObjectExistV2()     */    public function doesObjectExistV2(        $bucket,        $key,        $includeDeleteMarkers = false,        array $options = []    ){        $command = $this->getCommand('HeadObject', [                'Bucket' => $bucket,                'Key'    => $key            ] + $options        );        try {            $this->execute($command);            return true;        } catch (S3Exception $e) {            if ($includeDeleteMarkers                && $this->useDeleteMarkers($e)            ) {                return true;            }            if ($e->getStatusCode() === 404) {                return false;            }            throw $e;        }    }    private function useDeleteMarkers($exception)    {        $response = $exception->getResponse();        return !empty($response)            && $response->getHeader('x-amz-delete-marker');    }    /**     * Determines whether or not a resource exists using a command     *     * @param CommandInterface $command Command used to poll for the resource     *     * @return bool     * @throws S3Exception|\Exception if there is an unhandled exception     */    private function checkExistenceWithCommand(CommandInterface $command)    {        try {            $this->execute($command);            return true;        } catch (S3Exception $e) {            if ($e->getAwsErrorCode() == 'AccessDenied') {                return true;            }            if ($e->getStatusCode() >= 500) {                throw $e;            }            return false;        }    }    /**     * @see S3ClientInterface::execute()     */    abstract public function execute(CommandInterface $command);    /**     * @see S3ClientInterface::getCommand()     */    abstract public function getCommand($name, array $args = []);    /**     * @see S3ClientInterface::getHandlerList()     *     * @return HandlerList     */    abstract public function getHandlerList();    /**     * @see S3ClientInterface::getIterator()     *     * @return \Iterator     */    abstract public function getIterator($name, array $args = []);}
 |