├── .gitattributes ├── CHANGELOG.md ├── LICENSE ├── README.md ├── composer.json └── src ├── Enum ├── ArchiveStatus.php ├── BucketCannedACL.php ├── BucketLocationConstraint.php ├── BucketType.php ├── ChecksumAlgorithm.php ├── ChecksumMode.php ├── ChecksumType.php ├── DataRedundancy.php ├── EncodingType.php ├── Event.php ├── FilterRuleName.php ├── IntelligentTieringAccessTier.php ├── LocationType.php ├── MetadataDirective.php ├── ObjectCannedACL.php ├── ObjectLockLegalHoldStatus.php ├── ObjectLockMode.php ├── ObjectOwnership.php ├── ObjectStorageClass.php ├── ObjectVersionStorageClass.php ├── OptionalObjectAttributes.php ├── Permission.php ├── ReplicationStatus.php ├── RequestCharged.php ├── RequestPayer.php ├── ServerSideEncryption.php ├── StorageClass.php ├── TaggingDirective.php └── Type.php ├── Exception ├── BucketAlreadyExistsException.php ├── BucketAlreadyOwnedByYouException.php ├── EncryptionTypeMismatchException.php ├── InvalidObjectStateException.php ├── InvalidRequestException.php ├── InvalidWriteOffsetException.php ├── NoSuchBucketException.php ├── NoSuchKeyException.php ├── NoSuchUploadException.php ├── ObjectNotInActiveTierErrorException.php └── TooManyPartsException.php ├── Input ├── AbortMultipartUploadRequest.php ├── CompleteMultipartUploadRequest.php ├── CopyObjectRequest.php ├── CreateBucketRequest.php ├── CreateMultipartUploadRequest.php ├── DeleteBucketCorsRequest.php ├── DeleteBucketRequest.php ├── DeleteObjectRequest.php ├── DeleteObjectTaggingRequest.php ├── DeleteObjectsRequest.php ├── GetBucketCorsRequest.php ├── GetBucketEncryptionRequest.php ├── GetObjectAclRequest.php ├── GetObjectRequest.php ├── GetObjectTaggingRequest.php ├── HeadBucketRequest.php ├── HeadObjectRequest.php ├── ListBucketsRequest.php ├── ListMultipartUploadsRequest.php ├── ListObjectVersionsRequest.php ├── ListObjectsV2Request.php ├── ListPartsRequest.php ├── PutBucketCorsRequest.php ├── PutBucketNotificationConfigurationRequest.php ├── PutBucketTaggingRequest.php ├── PutObjectAclRequest.php ├── PutObjectRequest.php ├── PutObjectTaggingRequest.php ├── UploadPartCopyRequest.php └── UploadPartRequest.php ├── Result ├── AbortMultipartUploadOutput.php ├── BucketExistsWaiter.php ├── BucketNotExistsWaiter.php ├── CompleteMultipartUploadOutput.php ├── CopyObjectOutput.php ├── CreateBucketOutput.php ├── CreateMultipartUploadOutput.php ├── DeleteObjectOutput.php ├── DeleteObjectTaggingOutput.php ├── DeleteObjectsOutput.php ├── GetBucketCorsOutput.php ├── GetBucketEncryptionOutput.php ├── GetObjectAclOutput.php ├── GetObjectOutput.php ├── GetObjectTaggingOutput.php ├── HeadObjectOutput.php ├── ListBucketsOutput.php ├── ListMultipartUploadsOutput.php ├── ListObjectVersionsOutput.php ├── ListObjectsV2Output.php ├── ListPartsOutput.php ├── ObjectExistsWaiter.php ├── ObjectNotExistsWaiter.php ├── PutObjectAclOutput.php ├── PutObjectOutput.php ├── PutObjectTaggingOutput.php ├── UploadPartCopyOutput.php └── UploadPartOutput.php ├── S3Client.php ├── Signer └── SignerV4ForS3.php └── ValueObject ├── AccessControlPolicy.php ├── AwsObject.php ├── Bucket.php ├── BucketInfo.php ├── CORSConfiguration.php ├── CORSRule.php ├── CommonPrefix.php ├── CompletedMultipartUpload.php ├── CompletedPart.php ├── CopyObjectResult.php ├── CopyPartResult.php ├── CreateBucketConfiguration.php ├── Delete.php ├── DeleteMarkerEntry.php ├── DeletedObject.php ├── Error.php ├── EventBridgeConfiguration.php ├── FilterRule.php ├── Grant.php ├── Grantee.php ├── Initiator.php ├── LambdaFunctionConfiguration.php ├── LocationInfo.php ├── MultipartUpload.php ├── NotificationConfiguration.php ├── NotificationConfigurationFilter.php ├── ObjectIdentifier.php ├── ObjectVersion.php ├── Owner.php ├── Part.php ├── QueueConfiguration.php ├── RestoreStatus.php ├── S3KeyFilter.php ├── ServerSideEncryptionByDefault.php ├── ServerSideEncryptionConfiguration.php ├── ServerSideEncryptionRule.php ├── Tag.php ├── Tagging.php └── TopicConfiguration.php /.gitattributes: -------------------------------------------------------------------------------- 1 | /.github export-ignore 2 | /tests export-ignore 3 | /.gitignore export-ignore 4 | /Makefile export-ignore 5 | /phpunit.xml.dist export-ignore 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Jérémy Derussé, Tobias Nyholm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AsyncAws S3 Client 2 | 3 | ![](https://github.com/async-aws/s3/workflows/Tests/badge.svg?branch=master) 4 | ![](https://github.com/async-aws/s3/workflows/BC%20Check/badge.svg?branch=master) 5 | 6 | An API client for S3. 7 | 8 | ## Install 9 | 10 | ```cli 11 | composer require async-aws/s3 12 | ``` 13 | 14 | ## Documentation 15 | 16 | See https://async-aws.com/clients/s3.html for documentation. 17 | 18 | ## Contribute 19 | 20 | Contributions are welcome and appreciated. Please read https://async-aws.com/contribute/ 21 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "async-aws/s3", 3 | "description": "S3 client, part of the AWS SDK provided by AsyncAws.", 4 | "license": "MIT", 5 | "type": "library", 6 | "keywords": [ 7 | "aws", 8 | "amazon", 9 | "sdk", 10 | "async-aws", 11 | "s3" 12 | ], 13 | "require": { 14 | "php": "^7.2.5 || ^8.0", 15 | "ext-dom": "*", 16 | "ext-filter": "*", 17 | "ext-hash": "*", 18 | "ext-simplexml": "*", 19 | "async-aws/core": "^1.22" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "AsyncAws\\S3\\": "src" 24 | } 25 | }, 26 | "autoload-dev": { 27 | "psr-4": { 28 | "AsyncAws\\S3\\Tests\\": "tests/" 29 | } 30 | }, 31 | "extra": { 32 | "branch-alias": { 33 | "dev-master": "2.9-dev" 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Enum/ArchiveStatus.php: -------------------------------------------------------------------------------- 1 | true, 14 | self::DEEP_ARCHIVE_ACCESS => true, 15 | ][$value]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Enum/BucketCannedACL.php: -------------------------------------------------------------------------------- 1 | true, 16 | self::PRIVATE => true, 17 | self::PUBLIC_READ => true, 18 | self::PUBLIC_READ_WRITE => true, 19 | ][$value]); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Enum/BucketLocationConstraint.php: -------------------------------------------------------------------------------- 1 | true, 45 | self::AP_EAST_1 => true, 46 | self::AP_NORTHEAST_1 => true, 47 | self::AP_NORTHEAST_2 => true, 48 | self::AP_NORTHEAST_3 => true, 49 | self::AP_SOUTHEAST_1 => true, 50 | self::AP_SOUTHEAST_2 => true, 51 | self::AP_SOUTHEAST_3 => true, 52 | self::AP_SOUTHEAST_4 => true, 53 | self::AP_SOUTHEAST_5 => true, 54 | self::AP_SOUTH_1 => true, 55 | self::AP_SOUTH_2 => true, 56 | self::CA_CENTRAL_1 => true, 57 | self::CN_NORTHWEST_1 => true, 58 | self::CN_NORTH_1 => true, 59 | self::EU => true, 60 | self::EU_CENTRAL_1 => true, 61 | self::EU_CENTRAL_2 => true, 62 | self::EU_NORTH_1 => true, 63 | self::EU_SOUTH_1 => true, 64 | self::EU_SOUTH_2 => true, 65 | self::EU_WEST_1 => true, 66 | self::EU_WEST_2 => true, 67 | self::EU_WEST_3 => true, 68 | self::IL_CENTRAL_1 => true, 69 | self::ME_CENTRAL_1 => true, 70 | self::ME_SOUTH_1 => true, 71 | self::SA_EAST_1 => true, 72 | self::US_EAST_2 => true, 73 | self::US_GOV_EAST_1 => true, 74 | self::US_GOV_WEST_1 => true, 75 | self::US_WEST_1 => true, 76 | self::US_WEST_2 => true, 77 | ][$value]); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Enum/BucketType.php: -------------------------------------------------------------------------------- 1 | true, 13 | ][$value]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Enum/ChecksumAlgorithm.php: -------------------------------------------------------------------------------- 1 | true, 17 | self::CRC32C => true, 18 | self::CRC64NVME => true, 19 | self::SHA1 => true, 20 | self::SHA256 => true, 21 | ][$value]); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Enum/ChecksumMode.php: -------------------------------------------------------------------------------- 1 | true, 13 | ][$value]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Enum/ChecksumType.php: -------------------------------------------------------------------------------- 1 | true, 14 | self::FULL_OBJECT => true, 15 | ][$value]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Enum/DataRedundancy.php: -------------------------------------------------------------------------------- 1 | true, 14 | self::SINGLE_LOCAL_ZONE => true, 15 | ][$value]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Enum/EncodingType.php: -------------------------------------------------------------------------------- 1 | When using the URL encoding type, non-ASCII characters that are used in an object's key name will be 13 | * > percent-encoded according to UTF-8 code values. For example, the object `test_file(3).png` will appear as 14 | * > `test_file%283%29.png`. 15 | * 16 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html 17 | * [^2]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html#object-key-guidelines 18 | */ 19 | final class EncodingType 20 | { 21 | public const URL = 'url'; 22 | 23 | public static function exists(string $value): bool 24 | { 25 | return isset([ 26 | self::URL => true, 27 | ][$value]); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Enum/Event.php: -------------------------------------------------------------------------------- 1 | true, 42 | self::S3_LIFECYCLE_EXPIRATION_ALL => true, 43 | self::S3_LIFECYCLE_EXPIRATION_DELETE => true, 44 | self::S3_LIFECYCLE_EXPIRATION_DELETE_MARKER_CREATED => true, 45 | self::S3_LIFECYCLE_TRANSITION => true, 46 | self::S3_OBJECT_ACL_PUT => true, 47 | self::S3_OBJECT_CREATED_ALL => true, 48 | self::S3_OBJECT_CREATED_COMPLETE_MULTIPART_UPLOAD => true, 49 | self::S3_OBJECT_CREATED_COPY => true, 50 | self::S3_OBJECT_CREATED_POST => true, 51 | self::S3_OBJECT_CREATED_PUT => true, 52 | self::S3_OBJECT_REMOVED_ALL => true, 53 | self::S3_OBJECT_REMOVED_DELETE => true, 54 | self::S3_OBJECT_REMOVED_DELETE_MARKER_CREATED => true, 55 | self::S3_OBJECT_RESTORE_ALL => true, 56 | self::S3_OBJECT_RESTORE_COMPLETED => true, 57 | self::S3_OBJECT_RESTORE_DELETE => true, 58 | self::S3_OBJECT_RESTORE_POST => true, 59 | self::S3_OBJECT_TAGGING_ALL => true, 60 | self::S3_OBJECT_TAGGING_DELETE => true, 61 | self::S3_OBJECT_TAGGING_PUT => true, 62 | self::S3_REDUCED_REDUNDANCY_LOST_OBJECT => true, 63 | self::S3_REPLICATION_ALL => true, 64 | self::S3_REPLICATION_OPERATION_FAILED_REPLICATION => true, 65 | self::S3_REPLICATION_OPERATION_MISSED_THRESHOLD => true, 66 | self::S3_REPLICATION_OPERATION_NOT_TRACKED => true, 67 | self::S3_REPLICATION_OPERATION_REPLICATED_AFTER_THRESHOLD => true, 68 | ][$value]); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Enum/FilterRuleName.php: -------------------------------------------------------------------------------- 1 | true, 14 | self::SUFFIX => true, 15 | ][$value]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Enum/IntelligentTieringAccessTier.php: -------------------------------------------------------------------------------- 1 | true, 14 | self::DEEP_ARCHIVE_ACCESS => true, 15 | ][$value]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Enum/LocationType.php: -------------------------------------------------------------------------------- 1 | true, 14 | self::LOCAL_ZONE => true, 15 | ][$value]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Enum/MetadataDirective.php: -------------------------------------------------------------------------------- 1 | true, 14 | self::REPLACE => true, 15 | ][$value]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Enum/ObjectCannedACL.php: -------------------------------------------------------------------------------- 1 | true, 19 | self::AWS_EXEC_READ => true, 20 | self::BUCKET_OWNER_FULL_CONTROL => true, 21 | self::BUCKET_OWNER_READ => true, 22 | self::PRIVATE => true, 23 | self::PUBLIC_READ => true, 24 | self::PUBLIC_READ_WRITE => true, 25 | ][$value]); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Enum/ObjectLockLegalHoldStatus.php: -------------------------------------------------------------------------------- 1 | true, 14 | self::ON => true, 15 | ][$value]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Enum/ObjectLockMode.php: -------------------------------------------------------------------------------- 1 | true, 14 | self::GOVERNANCE => true, 15 | ][$value]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Enum/ObjectOwnership.php: -------------------------------------------------------------------------------- 1 | This functionality is not supported for directory buckets. Directory buckets use the bucket owner enforced setting 25 | * > for S3 Object Ownership. 26 | * 27 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html 28 | */ 29 | final class ObjectOwnership 30 | { 31 | public const BUCKET_OWNER_ENFORCED = 'BucketOwnerEnforced'; 32 | public const BUCKET_OWNER_PREFERRED = 'BucketOwnerPreferred'; 33 | public const OBJECT_WRITER = 'ObjectWriter'; 34 | 35 | public static function exists(string $value): bool 36 | { 37 | return isset([ 38 | self::BUCKET_OWNER_ENFORCED => true, 39 | self::BUCKET_OWNER_PREFERRED => true, 40 | self::OBJECT_WRITER => true, 41 | ][$value]); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Enum/ObjectStorageClass.php: -------------------------------------------------------------------------------- 1 | true, 23 | self::EXPRESS_ONEZONE => true, 24 | self::GLACIER => true, 25 | self::GLACIER_IR => true, 26 | self::INTELLIGENT_TIERING => true, 27 | self::ONEZONE_IA => true, 28 | self::OUTPOSTS => true, 29 | self::REDUCED_REDUNDANCY => true, 30 | self::SNOW => true, 31 | self::STANDARD => true, 32 | self::STANDARD_IA => true, 33 | ][$value]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Enum/ObjectVersionStorageClass.php: -------------------------------------------------------------------------------- 1 | true, 13 | ][$value]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Enum/OptionalObjectAttributes.php: -------------------------------------------------------------------------------- 1 | true, 13 | ][$value]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Enum/Permission.php: -------------------------------------------------------------------------------- 1 | true, 17 | self::READ => true, 18 | self::READ_ACP => true, 19 | self::WRITE => true, 20 | self::WRITE_ACP => true, 21 | ][$value]); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Enum/ReplicationStatus.php: -------------------------------------------------------------------------------- 1 | true, 17 | self::COMPLETED => true, 18 | self::FAILED => true, 19 | self::PENDING => true, 20 | self::REPLICA => true, 21 | ][$value]); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Enum/RequestCharged.php: -------------------------------------------------------------------------------- 1 | This functionality is not supported for directory buckets. 10 | * 11 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/RequesterPaysBuckets.html 12 | */ 13 | final class RequestCharged 14 | { 15 | public const REQUESTER = 'requester'; 16 | 17 | public static function exists(string $value): bool 18 | { 19 | return isset([ 20 | self::REQUESTER => true, 21 | ][$value]); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Enum/RequestPayer.php: -------------------------------------------------------------------------------- 1 | This functionality is not supported for directory buckets. 12 | * 13 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectsinRequesterPaysBuckets.html 14 | */ 15 | final class RequestPayer 16 | { 17 | public const REQUESTER = 'requester'; 18 | 19 | public static function exists(string $value): bool 20 | { 21 | return isset([ 22 | self::REQUESTER => true, 23 | ][$value]); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Enum/ServerSideEncryption.php: -------------------------------------------------------------------------------- 1 | true, 15 | self::AWS_KMS => true, 16 | self::AWS_KMS_DSSE => true, 17 | ][$value]); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Enum/StorageClass.php: -------------------------------------------------------------------------------- 1 | true, 23 | self::EXPRESS_ONEZONE => true, 24 | self::GLACIER => true, 25 | self::GLACIER_IR => true, 26 | self::INTELLIGENT_TIERING => true, 27 | self::ONEZONE_IA => true, 28 | self::OUTPOSTS => true, 29 | self::REDUCED_REDUNDANCY => true, 30 | self::SNOW => true, 31 | self::STANDARD => true, 32 | self::STANDARD_IA => true, 33 | ][$value]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Enum/TaggingDirective.php: -------------------------------------------------------------------------------- 1 | true, 14 | self::REPLACE => true, 15 | ][$value]); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Enum/Type.php: -------------------------------------------------------------------------------- 1 | true, 15 | self::CANONICAL_USER => true, 16 | self::GROUP => true, 17 | ][$value]); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Exception/BucketAlreadyExistsException.php: -------------------------------------------------------------------------------- 1 | accessTier; 40 | } 41 | 42 | /** 43 | * @return StorageClass::*|null 44 | */ 45 | public function getStorageClass(): ?string 46 | { 47 | return $this->storageClass; 48 | } 49 | 50 | protected function populateResult(ResponseInterface $response): void 51 | { 52 | $data = new \SimpleXMLElement($response->getContent(false)); 53 | if (0 < $data->Error->count()) { 54 | $data = $data->Error; 55 | } 56 | $this->storageClass = (null !== $v = $data->StorageClass[0]) ? (string) $v : null; 57 | $this->accessTier = (null !== $v = $data->AccessTier[0]) ? (string) $v : null; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Exception/InvalidRequestException.php: -------------------------------------------------------------------------------- 1 | bucket = $input['Bucket'] ?? null; 39 | $this->expectedBucketOwner = $input['ExpectedBucketOwner'] ?? null; 40 | parent::__construct($input); 41 | } 42 | 43 | /** 44 | * @param array{ 45 | * Bucket?: string, 46 | * ExpectedBucketOwner?: null|string, 47 | * '@region'?: string|null, 48 | * }|DeleteBucketCorsRequest $input 49 | */ 50 | public static function create($input): self 51 | { 52 | return $input instanceof self ? $input : new self($input); 53 | } 54 | 55 | public function getBucket(): ?string 56 | { 57 | return $this->bucket; 58 | } 59 | 60 | public function getExpectedBucketOwner(): ?string 61 | { 62 | return $this->expectedBucketOwner; 63 | } 64 | 65 | /** 66 | * @internal 67 | */ 68 | public function request(): Request 69 | { 70 | // Prepare headers 71 | $headers = ['content-type' => 'application/xml']; 72 | if (null !== $this->expectedBucketOwner) { 73 | $headers['x-amz-expected-bucket-owner'] = $this->expectedBucketOwner; 74 | } 75 | 76 | // Prepare query 77 | $query = []; 78 | 79 | // Prepare URI 80 | $uri = []; 81 | if (null === $v = $this->bucket) { 82 | throw new InvalidArgument(\sprintf('Missing parameter "Bucket" for "%s". The value cannot be null.', __CLASS__)); 83 | } 84 | $uri['Bucket'] = $v; 85 | $uriString = '/' . rawurlencode($uri['Bucket']) . '?cors'; 86 | 87 | // Prepare Body 88 | $body = ''; 89 | 90 | // Return the Request 91 | return new Request('DELETE', $uriString, $query, $headers, StreamFactory::create($body)); 92 | } 93 | 94 | public function setBucket(?string $value): self 95 | { 96 | $this->bucket = $value; 97 | 98 | return $this; 99 | } 100 | 101 | public function setExpectedBucketOwner(?string $value): self 102 | { 103 | $this->expectedBucketOwner = $value; 104 | 105 | return $this; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/Input/DeleteBucketRequest.php: -------------------------------------------------------------------------------- 1 | For directory buckets, this header is not supported in this API operation. If you specify this header, the request 35 | * > fails with the HTTP status code `501 Not Implemented`. 36 | * 37 | * @var string|null 38 | */ 39 | private $expectedBucketOwner; 40 | 41 | /** 42 | * @param array{ 43 | * Bucket?: string, 44 | * ExpectedBucketOwner?: null|string, 45 | * '@region'?: string|null, 46 | * } $input 47 | */ 48 | public function __construct(array $input = []) 49 | { 50 | $this->bucket = $input['Bucket'] ?? null; 51 | $this->expectedBucketOwner = $input['ExpectedBucketOwner'] ?? null; 52 | parent::__construct($input); 53 | } 54 | 55 | /** 56 | * @param array{ 57 | * Bucket?: string, 58 | * ExpectedBucketOwner?: null|string, 59 | * '@region'?: string|null, 60 | * }|DeleteBucketRequest $input 61 | */ 62 | public static function create($input): self 63 | { 64 | return $input instanceof self ? $input : new self($input); 65 | } 66 | 67 | public function getBucket(): ?string 68 | { 69 | return $this->bucket; 70 | } 71 | 72 | public function getExpectedBucketOwner(): ?string 73 | { 74 | return $this->expectedBucketOwner; 75 | } 76 | 77 | /** 78 | * @internal 79 | */ 80 | public function request(): Request 81 | { 82 | // Prepare headers 83 | $headers = ['content-type' => 'application/xml']; 84 | if (null !== $this->expectedBucketOwner) { 85 | $headers['x-amz-expected-bucket-owner'] = $this->expectedBucketOwner; 86 | } 87 | 88 | // Prepare query 89 | $query = []; 90 | 91 | // Prepare URI 92 | $uri = []; 93 | if (null === $v = $this->bucket) { 94 | throw new InvalidArgument(\sprintf('Missing parameter "Bucket" for "%s". The value cannot be null.', __CLASS__)); 95 | } 96 | $uri['Bucket'] = $v; 97 | $uriString = '/' . rawurlencode($uri['Bucket']); 98 | 99 | // Prepare Body 100 | $body = ''; 101 | 102 | // Return the Request 103 | return new Request('DELETE', $uriString, $query, $headers, StreamFactory::create($body)); 104 | } 105 | 106 | public function setBucket(?string $value): self 107 | { 108 | $this->bucket = $value; 109 | 110 | return $this; 111 | } 112 | 113 | public function setExpectedBucketOwner(?string $value): self 114 | { 115 | $this->expectedBucketOwner = $value; 116 | 117 | return $this; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/Input/GetBucketCorsRequest.php: -------------------------------------------------------------------------------- 1 | bucket = $input['Bucket'] ?? null; 49 | $this->expectedBucketOwner = $input['ExpectedBucketOwner'] ?? null; 50 | parent::__construct($input); 51 | } 52 | 53 | /** 54 | * @param array{ 55 | * Bucket?: string, 56 | * ExpectedBucketOwner?: null|string, 57 | * '@region'?: string|null, 58 | * }|GetBucketCorsRequest $input 59 | */ 60 | public static function create($input): self 61 | { 62 | return $input instanceof self ? $input : new self($input); 63 | } 64 | 65 | public function getBucket(): ?string 66 | { 67 | return $this->bucket; 68 | } 69 | 70 | public function getExpectedBucketOwner(): ?string 71 | { 72 | return $this->expectedBucketOwner; 73 | } 74 | 75 | /** 76 | * @internal 77 | */ 78 | public function request(): Request 79 | { 80 | // Prepare headers 81 | $headers = ['content-type' => 'application/xml']; 82 | if (null !== $this->expectedBucketOwner) { 83 | $headers['x-amz-expected-bucket-owner'] = $this->expectedBucketOwner; 84 | } 85 | 86 | // Prepare query 87 | $query = []; 88 | 89 | // Prepare URI 90 | $uri = []; 91 | if (null === $v = $this->bucket) { 92 | throw new InvalidArgument(\sprintf('Missing parameter "Bucket" for "%s". The value cannot be null.', __CLASS__)); 93 | } 94 | $uri['Bucket'] = $v; 95 | $uriString = '/' . rawurlencode($uri['Bucket']) . '?cors'; 96 | 97 | // Prepare Body 98 | $body = ''; 99 | 100 | // Return the Request 101 | return new Request('GET', $uriString, $query, $headers, StreamFactory::create($body)); 102 | } 103 | 104 | public function setBucket(?string $value): self 105 | { 106 | $this->bucket = $value; 107 | 108 | return $this; 109 | } 110 | 111 | public function setExpectedBucketOwner(?string $value): self 112 | { 113 | $this->expectedBucketOwner = $value; 114 | 115 | return $this; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/Input/GetBucketEncryptionRequest.php: -------------------------------------------------------------------------------- 1 | For directory buckets, this header is not supported in this API operation. If you specify this header, the request 35 | * > fails with the HTTP status code `501 Not Implemented`. 36 | * 37 | * @var string|null 38 | */ 39 | private $expectedBucketOwner; 40 | 41 | /** 42 | * @param array{ 43 | * Bucket?: string, 44 | * ExpectedBucketOwner?: null|string, 45 | * '@region'?: string|null, 46 | * } $input 47 | */ 48 | public function __construct(array $input = []) 49 | { 50 | $this->bucket = $input['Bucket'] ?? null; 51 | $this->expectedBucketOwner = $input['ExpectedBucketOwner'] ?? null; 52 | parent::__construct($input); 53 | } 54 | 55 | /** 56 | * @param array{ 57 | * Bucket?: string, 58 | * ExpectedBucketOwner?: null|string, 59 | * '@region'?: string|null, 60 | * }|GetBucketEncryptionRequest $input 61 | */ 62 | public static function create($input): self 63 | { 64 | return $input instanceof self ? $input : new self($input); 65 | } 66 | 67 | public function getBucket(): ?string 68 | { 69 | return $this->bucket; 70 | } 71 | 72 | public function getExpectedBucketOwner(): ?string 73 | { 74 | return $this->expectedBucketOwner; 75 | } 76 | 77 | /** 78 | * @internal 79 | */ 80 | public function request(): Request 81 | { 82 | // Prepare headers 83 | $headers = ['content-type' => 'application/xml']; 84 | if (null !== $this->expectedBucketOwner) { 85 | $headers['x-amz-expected-bucket-owner'] = $this->expectedBucketOwner; 86 | } 87 | 88 | // Prepare query 89 | $query = []; 90 | 91 | // Prepare URI 92 | $uri = []; 93 | if (null === $v = $this->bucket) { 94 | throw new InvalidArgument(\sprintf('Missing parameter "Bucket" for "%s". The value cannot be null.', __CLASS__)); 95 | } 96 | $uri['Bucket'] = $v; 97 | $uriString = '/' . rawurlencode($uri['Bucket']) . '?encryption'; 98 | 99 | // Prepare Body 100 | $body = ''; 101 | 102 | // Return the Request 103 | return new Request('GET', $uriString, $query, $headers, StreamFactory::create($body)); 104 | } 105 | 106 | public function setBucket(?string $value): self 107 | { 108 | $this->bucket = $value; 109 | 110 | return $this; 111 | } 112 | 113 | public function setExpectedBucketOwner(?string $value): self 114 | { 115 | $this->expectedBucketOwner = $value; 116 | 117 | return $this; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/Input/HeadBucketRequest.php: -------------------------------------------------------------------------------- 1 | Object Lambda access points are not supported by directory buckets. 36 | * 37 | * **S3 on Outposts** - When you use this action with S3 on Outposts, you must direct requests to the S3 on Outposts 38 | * hostname. The S3 on Outposts hostname takes the form 39 | * `*AccessPointName*-*AccountId*.*outpostID*.s3-outposts.*Region*.amazonaws.com`. When you use this action with S3 on 40 | * Outposts, the destination bucket must be the Outposts access point ARN or the access point alias. For more 41 | * information about S3 on Outposts, see What is S3 on Outposts? [^4] in the *Amazon S3 User Guide*. 42 | * 43 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-bucket-naming-rules.html 44 | * [^2]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-access-points.html 45 | * [^3]: https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html#ErrorCodeList 46 | * [^4]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/S3onOutposts.html 47 | * 48 | * @required 49 | * 50 | * @var string|null 51 | */ 52 | private $bucket; 53 | 54 | /** 55 | * The account ID of the expected bucket owner. If the account ID that you provide does not match the actual owner of 56 | * the bucket, the request fails with the HTTP status code `403 Forbidden` (access denied). 57 | * 58 | * @var string|null 59 | */ 60 | private $expectedBucketOwner; 61 | 62 | /** 63 | * @param array{ 64 | * Bucket?: string, 65 | * ExpectedBucketOwner?: null|string, 66 | * '@region'?: string|null, 67 | * } $input 68 | */ 69 | public function __construct(array $input = []) 70 | { 71 | $this->bucket = $input['Bucket'] ?? null; 72 | $this->expectedBucketOwner = $input['ExpectedBucketOwner'] ?? null; 73 | parent::__construct($input); 74 | } 75 | 76 | /** 77 | * @param array{ 78 | * Bucket?: string, 79 | * ExpectedBucketOwner?: null|string, 80 | * '@region'?: string|null, 81 | * }|HeadBucketRequest $input 82 | */ 83 | public static function create($input): self 84 | { 85 | return $input instanceof self ? $input : new self($input); 86 | } 87 | 88 | public function getBucket(): ?string 89 | { 90 | return $this->bucket; 91 | } 92 | 93 | public function getExpectedBucketOwner(): ?string 94 | { 95 | return $this->expectedBucketOwner; 96 | } 97 | 98 | /** 99 | * @internal 100 | */ 101 | public function request(): Request 102 | { 103 | // Prepare headers 104 | $headers = ['content-type' => 'application/xml']; 105 | if (null !== $this->expectedBucketOwner) { 106 | $headers['x-amz-expected-bucket-owner'] = $this->expectedBucketOwner; 107 | } 108 | 109 | // Prepare query 110 | $query = []; 111 | 112 | // Prepare URI 113 | $uri = []; 114 | if (null === $v = $this->bucket) { 115 | throw new InvalidArgument(\sprintf('Missing parameter "Bucket" for "%s". The value cannot be null.', __CLASS__)); 116 | } 117 | $uri['Bucket'] = $v; 118 | $uriString = '/' . rawurlencode($uri['Bucket']); 119 | 120 | // Prepare Body 121 | $body = ''; 122 | 123 | // Return the Request 124 | return new Request('HEAD', $uriString, $query, $headers, StreamFactory::create($body)); 125 | } 126 | 127 | public function setBucket(?string $value): self 128 | { 129 | $this->bucket = $value; 130 | 131 | return $this; 132 | } 133 | 134 | public function setExpectedBucketOwner(?string $value): self 135 | { 136 | $this->expectedBucketOwner = $value; 137 | 138 | return $this; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/Input/ListBucketsRequest.php: -------------------------------------------------------------------------------- 1 | If you specify the `bucket-region`, `prefix`, or `continuation-token` query parameters without using `max-buckets` 29 | * > to set the maximum number of buckets returned in the response, Amazon S3 applies a default page size of 10,000 and 30 | * > provides a continuation token if there are more buckets. 31 | * 32 | * @var string|null 33 | */ 34 | private $continuationToken; 35 | 36 | /** 37 | * Limits the response to bucket names that begin with the specified bucket name prefix. 38 | * 39 | * @var string|null 40 | */ 41 | private $prefix; 42 | 43 | /** 44 | * Limits the response to buckets that are located in the specified Amazon Web Services Region. The Amazon Web Services 45 | * Region must be expressed according to the Amazon Web Services Region code, such as `us-west-2` for the US West 46 | * (Oregon) Region. For a list of the valid values for all of the Amazon Web Services Regions, see Regions and Endpoints 47 | * [^1]. 48 | * 49 | * > Requests made to a Regional endpoint that is different from the `bucket-region` parameter are not supported. For 50 | * > example, if you want to limit the response to your buckets in Region `us-west-2`, the request must be made to an 51 | * > endpoint in Region `us-west-2`. 52 | * 53 | * [^1]: https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region 54 | * 55 | * @var string|null 56 | */ 57 | private $bucketRegion; 58 | 59 | /** 60 | * @param array{ 61 | * MaxBuckets?: null|int, 62 | * ContinuationToken?: null|string, 63 | * Prefix?: null|string, 64 | * BucketRegion?: null|string, 65 | * '@region'?: string|null, 66 | * } $input 67 | */ 68 | public function __construct(array $input = []) 69 | { 70 | $this->maxBuckets = $input['MaxBuckets'] ?? null; 71 | $this->continuationToken = $input['ContinuationToken'] ?? null; 72 | $this->prefix = $input['Prefix'] ?? null; 73 | $this->bucketRegion = $input['BucketRegion'] ?? null; 74 | parent::__construct($input); 75 | } 76 | 77 | /** 78 | * @param array{ 79 | * MaxBuckets?: null|int, 80 | * ContinuationToken?: null|string, 81 | * Prefix?: null|string, 82 | * BucketRegion?: null|string, 83 | * '@region'?: string|null, 84 | * }|ListBucketsRequest $input 85 | */ 86 | public static function create($input): self 87 | { 88 | return $input instanceof self ? $input : new self($input); 89 | } 90 | 91 | public function getBucketRegion(): ?string 92 | { 93 | return $this->bucketRegion; 94 | } 95 | 96 | public function getContinuationToken(): ?string 97 | { 98 | return $this->continuationToken; 99 | } 100 | 101 | public function getMaxBuckets(): ?int 102 | { 103 | return $this->maxBuckets; 104 | } 105 | 106 | public function getPrefix(): ?string 107 | { 108 | return $this->prefix; 109 | } 110 | 111 | /** 112 | * @internal 113 | */ 114 | public function request(): Request 115 | { 116 | // Prepare headers 117 | $headers = ['content-type' => 'application/xml']; 118 | 119 | // Prepare query 120 | $query = []; 121 | if (null !== $this->maxBuckets) { 122 | $query['max-buckets'] = (string) $this->maxBuckets; 123 | } 124 | if (null !== $this->continuationToken) { 125 | $query['continuation-token'] = $this->continuationToken; 126 | } 127 | if (null !== $this->prefix) { 128 | $query['prefix'] = $this->prefix; 129 | } 130 | if (null !== $this->bucketRegion) { 131 | $query['bucket-region'] = $this->bucketRegion; 132 | } 133 | 134 | // Prepare URI 135 | $uriString = '/'; 136 | 137 | // Prepare Body 138 | $body = ''; 139 | 140 | // Return the Request 141 | return new Request('GET', $uriString, $query, $headers, StreamFactory::create($body)); 142 | } 143 | 144 | public function setBucketRegion(?string $value): self 145 | { 146 | $this->bucketRegion = $value; 147 | 148 | return $this; 149 | } 150 | 151 | public function setContinuationToken(?string $value): self 152 | { 153 | $this->continuationToken = $value; 154 | 155 | return $this; 156 | } 157 | 158 | public function setMaxBuckets(?int $value): self 159 | { 160 | $this->maxBuckets = $value; 161 | 162 | return $this; 163 | } 164 | 165 | public function setPrefix(?string $value): self 166 | { 167 | $this->prefix = $value; 168 | 169 | return $this; 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/Input/PutBucketNotificationConfigurationRequest.php: -------------------------------------------------------------------------------- 1 | bucket = $input['Bucket'] ?? null; 56 | $this->notificationConfiguration = isset($input['NotificationConfiguration']) ? NotificationConfiguration::create($input['NotificationConfiguration']) : null; 57 | $this->expectedBucketOwner = $input['ExpectedBucketOwner'] ?? null; 58 | $this->skipDestinationValidation = $input['SkipDestinationValidation'] ?? null; 59 | parent::__construct($input); 60 | } 61 | 62 | /** 63 | * @param array{ 64 | * Bucket?: string, 65 | * NotificationConfiguration?: NotificationConfiguration|array, 66 | * ExpectedBucketOwner?: null|string, 67 | * SkipDestinationValidation?: null|bool, 68 | * '@region'?: string|null, 69 | * }|PutBucketNotificationConfigurationRequest $input 70 | */ 71 | public static function create($input): self 72 | { 73 | return $input instanceof self ? $input : new self($input); 74 | } 75 | 76 | public function getBucket(): ?string 77 | { 78 | return $this->bucket; 79 | } 80 | 81 | public function getExpectedBucketOwner(): ?string 82 | { 83 | return $this->expectedBucketOwner; 84 | } 85 | 86 | public function getNotificationConfiguration(): ?NotificationConfiguration 87 | { 88 | return $this->notificationConfiguration; 89 | } 90 | 91 | public function getSkipDestinationValidation(): ?bool 92 | { 93 | return $this->skipDestinationValidation; 94 | } 95 | 96 | /** 97 | * @internal 98 | */ 99 | public function request(): Request 100 | { 101 | // Prepare headers 102 | $headers = ['content-type' => 'application/xml']; 103 | if (null !== $this->expectedBucketOwner) { 104 | $headers['x-amz-expected-bucket-owner'] = $this->expectedBucketOwner; 105 | } 106 | if (null !== $this->skipDestinationValidation) { 107 | $headers['x-amz-skip-destination-validation'] = $this->skipDestinationValidation ? 'true' : 'false'; 108 | } 109 | 110 | // Prepare query 111 | $query = []; 112 | 113 | // Prepare URI 114 | $uri = []; 115 | if (null === $v = $this->bucket) { 116 | throw new InvalidArgument(\sprintf('Missing parameter "Bucket" for "%s". The value cannot be null.', __CLASS__)); 117 | } 118 | $uri['Bucket'] = $v; 119 | $uriString = '/' . rawurlencode($uri['Bucket']) . '?notification'; 120 | 121 | // Prepare Body 122 | 123 | $document = new \DOMDocument('1.0', 'UTF-8'); 124 | $document->formatOutput = false; 125 | $this->requestBody($document, $document); 126 | $body = $document->hasChildNodes() ? $document->saveXML() : ''; 127 | 128 | // Return the Request 129 | return new Request('PUT', $uriString, $query, $headers, StreamFactory::create($body)); 130 | } 131 | 132 | public function setBucket(?string $value): self 133 | { 134 | $this->bucket = $value; 135 | 136 | return $this; 137 | } 138 | 139 | public function setExpectedBucketOwner(?string $value): self 140 | { 141 | $this->expectedBucketOwner = $value; 142 | 143 | return $this; 144 | } 145 | 146 | public function setNotificationConfiguration(?NotificationConfiguration $value): self 147 | { 148 | $this->notificationConfiguration = $value; 149 | 150 | return $this; 151 | } 152 | 153 | public function setSkipDestinationValidation(?bool $value): self 154 | { 155 | $this->skipDestinationValidation = $value; 156 | 157 | return $this; 158 | } 159 | 160 | private function requestBody(\DOMNode $node, \DOMDocument $document): void 161 | { 162 | if (null === $v = $this->notificationConfiguration) { 163 | throw new InvalidArgument(\sprintf('Missing parameter "NotificationConfiguration" for "%s". The value cannot be null.', __CLASS__)); 164 | } 165 | 166 | $node->appendChild($child = $document->createElement('NotificationConfiguration')); 167 | $child->setAttribute('xmlns', 'http://s3.amazonaws.com/doc/2006-03-01/'); 168 | $v->requestBody($child, $document); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/Result/AbortMultipartUploadOutput.php: -------------------------------------------------------------------------------- 1 | initialize(); 22 | 23 | return $this->requestCharged; 24 | } 25 | 26 | protected function populateResult(Response $response): void 27 | { 28 | $headers = $response->getHeaders(); 29 | 30 | $this->requestCharged = $headers['x-amz-request-charged'][0] ?? null; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Result/BucketExistsWaiter.php: -------------------------------------------------------------------------------- 1 | getStatusCode()) { 20 | return self::STATE_SUCCESS; 21 | } 22 | 23 | if (301 === $response->getStatusCode()) { 24 | return self::STATE_SUCCESS; 25 | } 26 | 27 | if (403 === $response->getStatusCode()) { 28 | return self::STATE_SUCCESS; 29 | } 30 | 31 | if (404 === $response->getStatusCode()) { 32 | return self::STATE_PENDING; 33 | } 34 | 35 | return null === $exception ? self::STATE_PENDING : self::STATE_FAILURE; 36 | } 37 | 38 | protected function refreshState(): Waiter 39 | { 40 | if (!$this->awsClient instanceof S3Client) { 41 | throw new InvalidArgument('missing client injected in waiter result'); 42 | } 43 | if (!$this->input instanceof HeadBucketRequest) { 44 | throw new InvalidArgument('missing last request injected in waiter result'); 45 | } 46 | 47 | return $this->awsClient->bucketExists($this->input); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Result/BucketNotExistsWaiter.php: -------------------------------------------------------------------------------- 1 | getStatusCode()) { 20 | return self::STATE_SUCCESS; 21 | } 22 | 23 | return null === $exception ? self::STATE_PENDING : self::STATE_FAILURE; 24 | } 25 | 26 | protected function refreshState(): Waiter 27 | { 28 | if (!$this->awsClient instanceof S3Client) { 29 | throw new InvalidArgument('missing client injected in waiter result'); 30 | } 31 | if (!$this->input instanceof HeadBucketRequest) { 32 | throw new InvalidArgument('missing last request injected in waiter result'); 33 | } 34 | 35 | return $this->awsClient->bucketNotExists($this->input); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Result/CreateBucketOutput.php: -------------------------------------------------------------------------------- 1 | initialize(); 20 | 21 | return $this->location; 22 | } 23 | 24 | protected function populateResult(Response $response): void 25 | { 26 | $headers = $response->getHeaders(); 27 | 28 | $this->location = $headers['location'][0] ?? null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Result/DeleteObjectOutput.php: -------------------------------------------------------------------------------- 1 | This functionality is not supported for directory buckets. 17 | * 18 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/DeleteMarker.html 19 | * 20 | * @var bool|null 21 | */ 22 | private $deleteMarker; 23 | 24 | /** 25 | * Returns the version ID of the delete marker created as a result of the DELETE operation. 26 | * 27 | * > This functionality is not supported for directory buckets. 28 | * 29 | * @var string|null 30 | */ 31 | private $versionId; 32 | 33 | /** 34 | * @var RequestCharged::*|null 35 | */ 36 | private $requestCharged; 37 | 38 | public function getDeleteMarker(): ?bool 39 | { 40 | $this->initialize(); 41 | 42 | return $this->deleteMarker; 43 | } 44 | 45 | /** 46 | * @return RequestCharged::*|null 47 | */ 48 | public function getRequestCharged(): ?string 49 | { 50 | $this->initialize(); 51 | 52 | return $this->requestCharged; 53 | } 54 | 55 | public function getVersionId(): ?string 56 | { 57 | $this->initialize(); 58 | 59 | return $this->versionId; 60 | } 61 | 62 | protected function populateResult(Response $response): void 63 | { 64 | $headers = $response->getHeaders(); 65 | 66 | $this->deleteMarker = isset($headers['x-amz-delete-marker'][0]) ? filter_var($headers['x-amz-delete-marker'][0], \FILTER_VALIDATE_BOOLEAN) : null; 67 | $this->versionId = $headers['x-amz-version-id'][0] ?? null; 68 | $this->requestCharged = $headers['x-amz-request-charged'][0] ?? null; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Result/DeleteObjectTaggingOutput.php: -------------------------------------------------------------------------------- 1 | initialize(); 20 | 21 | return $this->versionId; 22 | } 23 | 24 | protected function populateResult(Response $response): void 25 | { 26 | $headers = $response->getHeaders(); 27 | 28 | $this->versionId = $headers['x-amz-version-id'][0] ?? null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Result/DeleteObjectsOutput.php: -------------------------------------------------------------------------------- 1 | initialize(); 39 | 40 | return $this->deleted; 41 | } 42 | 43 | /** 44 | * @return Error[] 45 | */ 46 | public function getErrors(): array 47 | { 48 | $this->initialize(); 49 | 50 | return $this->errors; 51 | } 52 | 53 | /** 54 | * @return RequestCharged::*|null 55 | */ 56 | public function getRequestCharged(): ?string 57 | { 58 | $this->initialize(); 59 | 60 | return $this->requestCharged; 61 | } 62 | 63 | protected function populateResult(Response $response): void 64 | { 65 | $headers = $response->getHeaders(); 66 | 67 | $this->requestCharged = $headers['x-amz-request-charged'][0] ?? null; 68 | 69 | $data = new \SimpleXMLElement($response->getContent()); 70 | $this->deleted = (0 === ($v = $data->Deleted)->count()) ? [] : $this->populateResultDeletedObjects($v); 71 | $this->errors = (0 === ($v = $data->Error)->count()) ? [] : $this->populateResultErrors($v); 72 | } 73 | 74 | private function populateResultDeletedObject(\SimpleXMLElement $xml): DeletedObject 75 | { 76 | return new DeletedObject([ 77 | 'Key' => (null !== $v = $xml->Key[0]) ? (string) $v : null, 78 | 'VersionId' => (null !== $v = $xml->VersionId[0]) ? (string) $v : null, 79 | 'DeleteMarker' => (null !== $v = $xml->DeleteMarker[0]) ? filter_var((string) $v, \FILTER_VALIDATE_BOOLEAN) : null, 80 | 'DeleteMarkerVersionId' => (null !== $v = $xml->DeleteMarkerVersionId[0]) ? (string) $v : null, 81 | ]); 82 | } 83 | 84 | /** 85 | * @return DeletedObject[] 86 | */ 87 | private function populateResultDeletedObjects(\SimpleXMLElement $xml): array 88 | { 89 | $items = []; 90 | foreach ($xml as $item) { 91 | $items[] = $this->populateResultDeletedObject($item); 92 | } 93 | 94 | return $items; 95 | } 96 | 97 | private function populateResultError(\SimpleXMLElement $xml): Error 98 | { 99 | return new Error([ 100 | 'Key' => (null !== $v = $xml->Key[0]) ? (string) $v : null, 101 | 'VersionId' => (null !== $v = $xml->VersionId[0]) ? (string) $v : null, 102 | 'Code' => (null !== $v = $xml->Code[0]) ? (string) $v : null, 103 | 'Message' => (null !== $v = $xml->Message[0]) ? (string) $v : null, 104 | ]); 105 | } 106 | 107 | /** 108 | * @return Error[] 109 | */ 110 | private function populateResultErrors(\SimpleXMLElement $xml): array 111 | { 112 | $items = []; 113 | foreach ($xml as $item) { 114 | $items[] = $this->populateResultError($item); 115 | } 116 | 117 | return $items; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/Result/GetBucketCorsOutput.php: -------------------------------------------------------------------------------- 1 | initialize(); 25 | 26 | return $this->corsRules; 27 | } 28 | 29 | protected function populateResult(Response $response): void 30 | { 31 | $data = new \SimpleXMLElement($response->getContent()); 32 | $this->corsRules = (0 === ($v = $data->CORSRule)->count()) ? [] : $this->populateResultCORSRules($v); 33 | } 34 | 35 | /** 36 | * @return string[] 37 | */ 38 | private function populateResultAllowedHeaders(\SimpleXMLElement $xml): array 39 | { 40 | $items = []; 41 | foreach ($xml as $item) { 42 | $items[] = (string) $item; 43 | } 44 | 45 | return $items; 46 | } 47 | 48 | /** 49 | * @return string[] 50 | */ 51 | private function populateResultAllowedMethods(\SimpleXMLElement $xml): array 52 | { 53 | $items = []; 54 | foreach ($xml as $item) { 55 | $items[] = (string) $item; 56 | } 57 | 58 | return $items; 59 | } 60 | 61 | /** 62 | * @return string[] 63 | */ 64 | private function populateResultAllowedOrigins(\SimpleXMLElement $xml): array 65 | { 66 | $items = []; 67 | foreach ($xml as $item) { 68 | $items[] = (string) $item; 69 | } 70 | 71 | return $items; 72 | } 73 | 74 | private function populateResultCORSRule(\SimpleXMLElement $xml): CORSRule 75 | { 76 | return new CORSRule([ 77 | 'ID' => (null !== $v = $xml->ID[0]) ? (string) $v : null, 78 | 'AllowedHeaders' => (0 === ($v = $xml->AllowedHeader)->count()) ? null : $this->populateResultAllowedHeaders($v), 79 | 'AllowedMethods' => $this->populateResultAllowedMethods($xml->AllowedMethod), 80 | 'AllowedOrigins' => $this->populateResultAllowedOrigins($xml->AllowedOrigin), 81 | 'ExposeHeaders' => (0 === ($v = $xml->ExposeHeader)->count()) ? null : $this->populateResultExposeHeaders($v), 82 | 'MaxAgeSeconds' => (null !== $v = $xml->MaxAgeSeconds[0]) ? (int) (string) $v : null, 83 | ]); 84 | } 85 | 86 | /** 87 | * @return CORSRule[] 88 | */ 89 | private function populateResultCORSRules(\SimpleXMLElement $xml): array 90 | { 91 | $items = []; 92 | foreach ($xml as $item) { 93 | $items[] = $this->populateResultCORSRule($item); 94 | } 95 | 96 | return $items; 97 | } 98 | 99 | /** 100 | * @return string[] 101 | */ 102 | private function populateResultExposeHeaders(\SimpleXMLElement $xml): array 103 | { 104 | $items = []; 105 | foreach ($xml as $item) { 106 | $items[] = (string) $item; 107 | } 108 | 109 | return $items; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Result/GetBucketEncryptionOutput.php: -------------------------------------------------------------------------------- 1 | initialize(); 21 | 22 | return $this->serverSideEncryptionConfiguration; 23 | } 24 | 25 | protected function populateResult(Response $response): void 26 | { 27 | $data = new \SimpleXMLElement($response->getContent()); 28 | $this->serverSideEncryptionConfiguration = $this->populateResultServerSideEncryptionConfiguration($data); 29 | } 30 | 31 | private function populateResultServerSideEncryptionByDefault(\SimpleXMLElement $xml): ServerSideEncryptionByDefault 32 | { 33 | return new ServerSideEncryptionByDefault([ 34 | 'SSEAlgorithm' => (string) $xml->SSEAlgorithm, 35 | 'KMSMasterKeyID' => (null !== $v = $xml->KMSMasterKeyID[0]) ? (string) $v : null, 36 | ]); 37 | } 38 | 39 | private function populateResultServerSideEncryptionConfiguration(\SimpleXMLElement $xml): ServerSideEncryptionConfiguration 40 | { 41 | return new ServerSideEncryptionConfiguration([ 42 | 'Rules' => $this->populateResultServerSideEncryptionRules($xml->Rule), 43 | ]); 44 | } 45 | 46 | private function populateResultServerSideEncryptionRule(\SimpleXMLElement $xml): ServerSideEncryptionRule 47 | { 48 | return new ServerSideEncryptionRule([ 49 | 'ApplyServerSideEncryptionByDefault' => 0 === $xml->ApplyServerSideEncryptionByDefault->count() ? null : $this->populateResultServerSideEncryptionByDefault($xml->ApplyServerSideEncryptionByDefault), 50 | 'BucketKeyEnabled' => (null !== $v = $xml->BucketKeyEnabled[0]) ? filter_var((string) $v, \FILTER_VALIDATE_BOOLEAN) : null, 51 | ]); 52 | } 53 | 54 | /** 55 | * @return ServerSideEncryptionRule[] 56 | */ 57 | private function populateResultServerSideEncryptionRules(\SimpleXMLElement $xml): array 58 | { 59 | $items = []; 60 | foreach ($xml as $item) { 61 | $items[] = $this->populateResultServerSideEncryptionRule($item); 62 | } 63 | 64 | return $items; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Result/GetObjectAclOutput.php: -------------------------------------------------------------------------------- 1 | initialize(); 39 | 40 | return $this->grants; 41 | } 42 | 43 | public function getOwner(): ?Owner 44 | { 45 | $this->initialize(); 46 | 47 | return $this->owner; 48 | } 49 | 50 | /** 51 | * @return RequestCharged::*|null 52 | */ 53 | public function getRequestCharged(): ?string 54 | { 55 | $this->initialize(); 56 | 57 | return $this->requestCharged; 58 | } 59 | 60 | protected function populateResult(Response $response): void 61 | { 62 | $headers = $response->getHeaders(); 63 | 64 | $this->requestCharged = $headers['x-amz-request-charged'][0] ?? null; 65 | 66 | $data = new \SimpleXMLElement($response->getContent()); 67 | $this->owner = 0 === $data->Owner->count() ? null : $this->populateResultOwner($data->Owner); 68 | $this->grants = (0 === ($v = $data->AccessControlList)->count()) ? [] : $this->populateResultGrants($v); 69 | } 70 | 71 | private function populateResultGrant(\SimpleXMLElement $xml): Grant 72 | { 73 | return new Grant([ 74 | 'Grantee' => 0 === $xml->Grantee->count() ? null : $this->populateResultGrantee($xml->Grantee), 75 | 'Permission' => (null !== $v = $xml->Permission[0]) ? (string) $v : null, 76 | ]); 77 | } 78 | 79 | private function populateResultGrantee(\SimpleXMLElement $xml): Grantee 80 | { 81 | return new Grantee([ 82 | 'DisplayName' => (null !== $v = $xml->DisplayName[0]) ? (string) $v : null, 83 | 'EmailAddress' => (null !== $v = $xml->EmailAddress[0]) ? (string) $v : null, 84 | 'ID' => (null !== $v = $xml->ID[0]) ? (string) $v : null, 85 | 'Type' => (string) ($xml->attributes('xsi', true)['type'][0] ?? null), 86 | 'URI' => (null !== $v = $xml->URI[0]) ? (string) $v : null, 87 | ]); 88 | } 89 | 90 | /** 91 | * @return Grant[] 92 | */ 93 | private function populateResultGrants(\SimpleXMLElement $xml): array 94 | { 95 | $items = []; 96 | foreach ($xml->Grant as $item) { 97 | $items[] = $this->populateResultGrant($item); 98 | } 99 | 100 | return $items; 101 | } 102 | 103 | private function populateResultOwner(\SimpleXMLElement $xml): Owner 104 | { 105 | return new Owner([ 106 | 'DisplayName' => (null !== $v = $xml->DisplayName[0]) ? (string) $v : null, 107 | 'ID' => (null !== $v = $xml->ID[0]) ? (string) $v : null, 108 | ]); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/Result/GetObjectTaggingOutput.php: -------------------------------------------------------------------------------- 1 | initialize(); 31 | 32 | return $this->tagSet; 33 | } 34 | 35 | public function getVersionId(): ?string 36 | { 37 | $this->initialize(); 38 | 39 | return $this->versionId; 40 | } 41 | 42 | protected function populateResult(Response $response): void 43 | { 44 | $headers = $response->getHeaders(); 45 | 46 | $this->versionId = $headers['x-amz-version-id'][0] ?? null; 47 | 48 | $data = new \SimpleXMLElement($response->getContent()); 49 | $this->tagSet = $this->populateResultTagSet($data->TagSet); 50 | } 51 | 52 | private function populateResultTag(\SimpleXMLElement $xml): Tag 53 | { 54 | return new Tag([ 55 | 'Key' => (string) $xml->Key, 56 | 'Value' => (string) $xml->Value, 57 | ]); 58 | } 59 | 60 | /** 61 | * @return Tag[] 62 | */ 63 | private function populateResultTagSet(\SimpleXMLElement $xml): array 64 | { 65 | $items = []; 66 | foreach ($xml->Tag as $item) { 67 | $items[] = $this->populateResultTag($item); 68 | } 69 | 70 | return $items; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Result/ListBucketsOutput.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class ListBucketsOutput extends Result implements \IteratorAggregate 17 | { 18 | /** 19 | * The list of buckets owned by the requester. 20 | * 21 | * @var Bucket[] 22 | */ 23 | private $buckets; 24 | 25 | /** 26 | * The owner of the buckets listed. 27 | * 28 | * @var Owner|null 29 | */ 30 | private $owner; 31 | 32 | /** 33 | * `ContinuationToken` is included in the response when there are more buckets that can be listed with pagination. The 34 | * next `ListBuckets` request to Amazon S3 can be continued with this `ContinuationToken`. `ContinuationToken` is 35 | * obfuscated and is not a real bucket. 36 | * 37 | * @var string|null 38 | */ 39 | private $continuationToken; 40 | 41 | /** 42 | * If `Prefix` was sent with the request, it is included in the response. 43 | * 44 | * All bucket names in the response begin with the specified bucket name prefix. 45 | * 46 | * @var string|null 47 | */ 48 | private $prefix; 49 | 50 | /** 51 | * @param bool $currentPageOnly When true, iterates over items of the current page. Otherwise also fetch items in the next pages. 52 | * 53 | * @return iterable 54 | */ 55 | public function getBuckets(bool $currentPageOnly = false): iterable 56 | { 57 | if ($currentPageOnly) { 58 | $this->initialize(); 59 | yield from $this->buckets; 60 | 61 | return; 62 | } 63 | 64 | $client = $this->awsClient; 65 | if (!$client instanceof S3Client) { 66 | throw new InvalidArgument('missing client injected in paginated result'); 67 | } 68 | if (!$this->input instanceof ListBucketsRequest) { 69 | throw new InvalidArgument('missing last request injected in paginated result'); 70 | } 71 | $input = clone $this->input; 72 | $page = $this; 73 | while (true) { 74 | $page->initialize(); 75 | if (null !== $page->continuationToken) { 76 | $input->setContinuationToken($page->continuationToken); 77 | 78 | $this->registerPrefetch($nextPage = $client->listBuckets($input)); 79 | } else { 80 | $nextPage = null; 81 | } 82 | 83 | yield from $page->buckets; 84 | 85 | if (null === $nextPage) { 86 | break; 87 | } 88 | 89 | $this->unregisterPrefetch($nextPage); 90 | $page = $nextPage; 91 | } 92 | } 93 | 94 | public function getContinuationToken(): ?string 95 | { 96 | $this->initialize(); 97 | 98 | return $this->continuationToken; 99 | } 100 | 101 | /** 102 | * Iterates over Buckets. 103 | * 104 | * @return \Traversable 105 | */ 106 | public function getIterator(): \Traversable 107 | { 108 | yield from $this->getBuckets(); 109 | } 110 | 111 | public function getOwner(): ?Owner 112 | { 113 | $this->initialize(); 114 | 115 | return $this->owner; 116 | } 117 | 118 | public function getPrefix(): ?string 119 | { 120 | $this->initialize(); 121 | 122 | return $this->prefix; 123 | } 124 | 125 | protected function populateResult(Response $response): void 126 | { 127 | $data = new \SimpleXMLElement($response->getContent()); 128 | $this->buckets = (0 === ($v = $data->Buckets)->count()) ? [] : $this->populateResultBuckets($v); 129 | $this->owner = 0 === $data->Owner->count() ? null : $this->populateResultOwner($data->Owner); 130 | $this->continuationToken = (null !== $v = $data->ContinuationToken[0]) ? (string) $v : null; 131 | $this->prefix = (null !== $v = $data->Prefix[0]) ? (string) $v : null; 132 | } 133 | 134 | private function populateResultBucket(\SimpleXMLElement $xml): Bucket 135 | { 136 | return new Bucket([ 137 | 'Name' => (null !== $v = $xml->Name[0]) ? (string) $v : null, 138 | 'CreationDate' => (null !== $v = $xml->CreationDate[0]) ? new \DateTimeImmutable((string) $v) : null, 139 | 'BucketRegion' => (null !== $v = $xml->BucketRegion[0]) ? (string) $v : null, 140 | ]); 141 | } 142 | 143 | /** 144 | * @return Bucket[] 145 | */ 146 | private function populateResultBuckets(\SimpleXMLElement $xml): array 147 | { 148 | $items = []; 149 | foreach ($xml->Bucket as $item) { 150 | $items[] = $this->populateResultBucket($item); 151 | } 152 | 153 | return $items; 154 | } 155 | 156 | private function populateResultOwner(\SimpleXMLElement $xml): Owner 157 | { 158 | return new Owner([ 159 | 'DisplayName' => (null !== $v = $xml->DisplayName[0]) ? (string) $v : null, 160 | 'ID' => (null !== $v = $xml->ID[0]) ? (string) $v : null, 161 | ]); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/Result/ObjectExistsWaiter.php: -------------------------------------------------------------------------------- 1 | getStatusCode()) { 20 | return self::STATE_SUCCESS; 21 | } 22 | 23 | if (404 === $response->getStatusCode()) { 24 | return self::STATE_PENDING; 25 | } 26 | 27 | return null === $exception ? self::STATE_PENDING : self::STATE_FAILURE; 28 | } 29 | 30 | protected function refreshState(): Waiter 31 | { 32 | if (!$this->awsClient instanceof S3Client) { 33 | throw new InvalidArgument('missing client injected in waiter result'); 34 | } 35 | if (!$this->input instanceof HeadObjectRequest) { 36 | throw new InvalidArgument('missing last request injected in waiter result'); 37 | } 38 | 39 | return $this->awsClient->objectExists($this->input); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Result/ObjectNotExistsWaiter.php: -------------------------------------------------------------------------------- 1 | getStatusCode()) { 20 | return self::STATE_SUCCESS; 21 | } 22 | 23 | return null === $exception ? self::STATE_PENDING : self::STATE_FAILURE; 24 | } 25 | 26 | protected function refreshState(): Waiter 27 | { 28 | if (!$this->awsClient instanceof S3Client) { 29 | throw new InvalidArgument('missing client injected in waiter result'); 30 | } 31 | if (!$this->input instanceof HeadObjectRequest) { 32 | throw new InvalidArgument('missing last request injected in waiter result'); 33 | } 34 | 35 | return $this->awsClient->objectNotExists($this->input); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Result/PutObjectAclOutput.php: -------------------------------------------------------------------------------- 1 | initialize(); 22 | 23 | return $this->requestCharged; 24 | } 25 | 26 | protected function populateResult(Response $response): void 27 | { 28 | $headers = $response->getHeaders(); 29 | 30 | $this->requestCharged = $headers['x-amz-request-charged'][0] ?? null; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Result/PutObjectTaggingOutput.php: -------------------------------------------------------------------------------- 1 | initialize(); 20 | 21 | return $this->versionId; 22 | } 23 | 24 | protected function populateResult(Response $response): void 25 | { 26 | $headers = $response->getHeaders(); 27 | 28 | $this->versionId = $headers['x-amz-version-id'][0] ?? null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Result/UploadPartCopyOutput.php: -------------------------------------------------------------------------------- 1 | This functionality is not supported when the source object is in a directory bucket. 17 | * 18 | * @var string|null 19 | */ 20 | private $copySourceVersionId; 21 | 22 | /** 23 | * Container for all response elements. 24 | * 25 | * @var CopyPartResult|null 26 | */ 27 | private $copyPartResult; 28 | 29 | /** 30 | * The server-side encryption algorithm used when you store this object in Amazon S3 (for example, `AES256`, `aws:kms`). 31 | * 32 | * @var ServerSideEncryption::*|null 33 | */ 34 | private $serverSideEncryption; 35 | 36 | /** 37 | * If server-side encryption with a customer-provided encryption key was requested, the response will include this 38 | * header to confirm the encryption algorithm that's used. 39 | * 40 | * > This functionality is not supported for directory buckets. 41 | * 42 | * @var string|null 43 | */ 44 | private $sseCustomerAlgorithm; 45 | 46 | /** 47 | * If server-side encryption with a customer-provided encryption key was requested, the response will include this 48 | * header to provide the round-trip message integrity verification of the customer-provided encryption key. 49 | * 50 | * > This functionality is not supported for directory buckets. 51 | * 52 | * @var string|null 53 | */ 54 | private $sseCustomerKeyMd5; 55 | 56 | /** 57 | * If present, indicates the ID of the KMS key that was used for object encryption. 58 | * 59 | * @var string|null 60 | */ 61 | private $sseKmsKeyId; 62 | 63 | /** 64 | * Indicates whether the multipart upload uses an S3 Bucket Key for server-side encryption with Key Management Service 65 | * (KMS) keys (SSE-KMS). 66 | * 67 | * @var bool|null 68 | */ 69 | private $bucketKeyEnabled; 70 | 71 | /** 72 | * @var RequestCharged::*|null 73 | */ 74 | private $requestCharged; 75 | 76 | public function getBucketKeyEnabled(): ?bool 77 | { 78 | $this->initialize(); 79 | 80 | return $this->bucketKeyEnabled; 81 | } 82 | 83 | public function getCopyPartResult(): ?CopyPartResult 84 | { 85 | $this->initialize(); 86 | 87 | return $this->copyPartResult; 88 | } 89 | 90 | public function getCopySourceVersionId(): ?string 91 | { 92 | $this->initialize(); 93 | 94 | return $this->copySourceVersionId; 95 | } 96 | 97 | /** 98 | * @return RequestCharged::*|null 99 | */ 100 | public function getRequestCharged(): ?string 101 | { 102 | $this->initialize(); 103 | 104 | return $this->requestCharged; 105 | } 106 | 107 | /** 108 | * @return ServerSideEncryption::*|null 109 | */ 110 | public function getServerSideEncryption(): ?string 111 | { 112 | $this->initialize(); 113 | 114 | return $this->serverSideEncryption; 115 | } 116 | 117 | public function getSseCustomerAlgorithm(): ?string 118 | { 119 | $this->initialize(); 120 | 121 | return $this->sseCustomerAlgorithm; 122 | } 123 | 124 | public function getSseCustomerKeyMd5(): ?string 125 | { 126 | $this->initialize(); 127 | 128 | return $this->sseCustomerKeyMd5; 129 | } 130 | 131 | public function getSseKmsKeyId(): ?string 132 | { 133 | $this->initialize(); 134 | 135 | return $this->sseKmsKeyId; 136 | } 137 | 138 | protected function populateResult(Response $response): void 139 | { 140 | $headers = $response->getHeaders(); 141 | 142 | $this->copySourceVersionId = $headers['x-amz-copy-source-version-id'][0] ?? null; 143 | $this->serverSideEncryption = $headers['x-amz-server-side-encryption'][0] ?? null; 144 | $this->sseCustomerAlgorithm = $headers['x-amz-server-side-encryption-customer-algorithm'][0] ?? null; 145 | $this->sseCustomerKeyMd5 = $headers['x-amz-server-side-encryption-customer-key-md5'][0] ?? null; 146 | $this->sseKmsKeyId = $headers['x-amz-server-side-encryption-aws-kms-key-id'][0] ?? null; 147 | $this->bucketKeyEnabled = isset($headers['x-amz-server-side-encryption-bucket-key-enabled'][0]) ? filter_var($headers['x-amz-server-side-encryption-bucket-key-enabled'][0], \FILTER_VALIDATE_BOOLEAN) : null; 148 | $this->requestCharged = $headers['x-amz-request-charged'][0] ?? null; 149 | 150 | $data = new \SimpleXMLElement($response->getContent()); 151 | $this->copyPartResult = $this->populateResultCopyPartResult($data); 152 | } 153 | 154 | private function populateResultCopyPartResult(\SimpleXMLElement $xml): CopyPartResult 155 | { 156 | return new CopyPartResult([ 157 | 'ETag' => (null !== $v = $xml->ETag[0]) ? (string) $v : null, 158 | 'LastModified' => (null !== $v = $xml->LastModified[0]) ? new \DateTimeImmutable((string) $v) : null, 159 | 'ChecksumCRC32' => (null !== $v = $xml->ChecksumCRC32[0]) ? (string) $v : null, 160 | 'ChecksumCRC32C' => (null !== $v = $xml->ChecksumCRC32C[0]) ? (string) $v : null, 161 | 'ChecksumCRC64NVME' => (null !== $v = $xml->ChecksumCRC64NVME[0]) ? (string) $v : null, 162 | 'ChecksumSHA1' => (null !== $v = $xml->ChecksumSHA1[0]) ? (string) $v : null, 163 | 'ChecksumSHA256' => (null !== $v = $xml->ChecksumSHA256[0]) ? (string) $v : null, 164 | ]); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/ValueObject/AccessControlPolicy.php: -------------------------------------------------------------------------------- 1 | , 27 | * Owner?: null|Owner|array, 28 | * } $input 29 | */ 30 | public function __construct(array $input) 31 | { 32 | $this->grants = isset($input['Grants']) ? array_map([Grant::class, 'create'], $input['Grants']) : null; 33 | $this->owner = isset($input['Owner']) ? Owner::create($input['Owner']) : null; 34 | } 35 | 36 | /** 37 | * @param array{ 38 | * Grants?: null|array, 39 | * Owner?: null|Owner|array, 40 | * }|AccessControlPolicy $input 41 | */ 42 | public static function create($input): self 43 | { 44 | return $input instanceof self ? $input : new self($input); 45 | } 46 | 47 | /** 48 | * @return Grant[] 49 | */ 50 | public function getGrants(): array 51 | { 52 | return $this->grants ?? []; 53 | } 54 | 55 | public function getOwner(): ?Owner 56 | { 57 | return $this->owner; 58 | } 59 | 60 | /** 61 | * @internal 62 | */ 63 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 64 | { 65 | if (null !== $v = $this->grants) { 66 | $node->appendChild($nodeList = $document->createElement('AccessControlList')); 67 | foreach ($v as $item) { 68 | $nodeList->appendChild($child = $document->createElement('Grant')); 69 | 70 | $item->requestBody($child, $document); 71 | } 72 | } 73 | if (null !== $v = $this->owner) { 74 | $node->appendChild($child = $document->createElement('Owner')); 75 | 76 | $v->requestBody($child, $document); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/ValueObject/Bucket.php: -------------------------------------------------------------------------------- 1 | name = $input['Name'] ?? null; 43 | $this->creationDate = $input['CreationDate'] ?? null; 44 | $this->bucketRegion = $input['BucketRegion'] ?? null; 45 | } 46 | 47 | /** 48 | * @param array{ 49 | * Name?: null|string, 50 | * CreationDate?: null|\DateTimeImmutable, 51 | * BucketRegion?: null|string, 52 | * }|Bucket $input 53 | */ 54 | public static function create($input): self 55 | { 56 | return $input instanceof self ? $input : new self($input); 57 | } 58 | 59 | public function getBucketRegion(): ?string 60 | { 61 | return $this->bucketRegion; 62 | } 63 | 64 | public function getCreationDate(): ?\DateTimeImmutable 65 | { 66 | return $this->creationDate; 67 | } 68 | 69 | public function getName(): ?string 70 | { 71 | return $this->name; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/ValueObject/BucketInfo.php: -------------------------------------------------------------------------------- 1 | This functionality is only supported by directory buckets. 14 | * 15 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-overview.html 16 | */ 17 | final class BucketInfo 18 | { 19 | /** 20 | * The number of Zone (Availability Zone or Local Zone) that's used for redundancy for the bucket. 21 | * 22 | * @var DataRedundancy::*|null 23 | */ 24 | private $dataRedundancy; 25 | 26 | /** 27 | * The type of bucket. 28 | * 29 | * @var BucketType::*|null 30 | */ 31 | private $type; 32 | 33 | /** 34 | * @param array{ 35 | * DataRedundancy?: null|DataRedundancy::*, 36 | * Type?: null|BucketType::*, 37 | * } $input 38 | */ 39 | public function __construct(array $input) 40 | { 41 | $this->dataRedundancy = $input['DataRedundancy'] ?? null; 42 | $this->type = $input['Type'] ?? null; 43 | } 44 | 45 | /** 46 | * @param array{ 47 | * DataRedundancy?: null|DataRedundancy::*, 48 | * Type?: null|BucketType::*, 49 | * }|BucketInfo $input 50 | */ 51 | public static function create($input): self 52 | { 53 | return $input instanceof self ? $input : new self($input); 54 | } 55 | 56 | /** 57 | * @return DataRedundancy::*|null 58 | */ 59 | public function getDataRedundancy(): ?string 60 | { 61 | return $this->dataRedundancy; 62 | } 63 | 64 | /** 65 | * @return BucketType::*|null 66 | */ 67 | public function getType(): ?string 68 | { 69 | return $this->type; 70 | } 71 | 72 | /** 73 | * @internal 74 | */ 75 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 76 | { 77 | if (null !== $v = $this->dataRedundancy) { 78 | if (!DataRedundancy::exists($v)) { 79 | throw new InvalidArgument(\sprintf('Invalid parameter "DataRedundancy" for "%s". The value "%s" is not a valid "DataRedundancy".', __CLASS__, $v)); 80 | } 81 | $node->appendChild($document->createElement('DataRedundancy', $v)); 82 | } 83 | if (null !== $v = $this->type) { 84 | if (!BucketType::exists($v)) { 85 | throw new InvalidArgument(\sprintf('Invalid parameter "Type" for "%s". The value "%s" is not a valid "BucketType".', __CLASS__, $v)); 86 | } 87 | $node->appendChild($document->createElement('Type', $v)); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/ValueObject/CORSConfiguration.php: -------------------------------------------------------------------------------- 1 | , 26 | * } $input 27 | */ 28 | public function __construct(array $input) 29 | { 30 | $this->corsRules = isset($input['CORSRules']) ? array_map([CORSRule::class, 'create'], $input['CORSRules']) : $this->throwException(new InvalidArgument('Missing required field "CORSRules".')); 31 | } 32 | 33 | /** 34 | * @param array{ 35 | * CORSRules: array, 36 | * }|CORSConfiguration $input 37 | */ 38 | public static function create($input): self 39 | { 40 | return $input instanceof self ? $input : new self($input); 41 | } 42 | 43 | /** 44 | * @return CORSRule[] 45 | */ 46 | public function getCorsRules(): array 47 | { 48 | return $this->corsRules; 49 | } 50 | 51 | /** 52 | * @internal 53 | */ 54 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 55 | { 56 | $v = $this->corsRules; 57 | foreach ($v as $item) { 58 | $node->appendChild($child = $document->createElement('CORSRule')); 59 | 60 | $item->requestBody($child, $document); 61 | } 62 | } 63 | 64 | /** 65 | * @return never 66 | */ 67 | private function throwException(\Throwable $exception) 68 | { 69 | throw $exception; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/ValueObject/CORSRule.php: -------------------------------------------------------------------------------- 1 | id = $input['ID'] ?? null; 70 | $this->allowedHeaders = $input['AllowedHeaders'] ?? null; 71 | $this->allowedMethods = $input['AllowedMethods'] ?? $this->throwException(new InvalidArgument('Missing required field "AllowedMethods".')); 72 | $this->allowedOrigins = $input['AllowedOrigins'] ?? $this->throwException(new InvalidArgument('Missing required field "AllowedOrigins".')); 73 | $this->exposeHeaders = $input['ExposeHeaders'] ?? null; 74 | $this->maxAgeSeconds = $input['MaxAgeSeconds'] ?? null; 75 | } 76 | 77 | /** 78 | * @param array{ 79 | * ID?: null|string, 80 | * AllowedHeaders?: null|string[], 81 | * AllowedMethods: string[], 82 | * AllowedOrigins: string[], 83 | * ExposeHeaders?: null|string[], 84 | * MaxAgeSeconds?: null|int, 85 | * }|CORSRule $input 86 | */ 87 | public static function create($input): self 88 | { 89 | return $input instanceof self ? $input : new self($input); 90 | } 91 | 92 | /** 93 | * @return string[] 94 | */ 95 | public function getAllowedHeaders(): array 96 | { 97 | return $this->allowedHeaders ?? []; 98 | } 99 | 100 | /** 101 | * @return string[] 102 | */ 103 | public function getAllowedMethods(): array 104 | { 105 | return $this->allowedMethods; 106 | } 107 | 108 | /** 109 | * @return string[] 110 | */ 111 | public function getAllowedOrigins(): array 112 | { 113 | return $this->allowedOrigins; 114 | } 115 | 116 | /** 117 | * @return string[] 118 | */ 119 | public function getExposeHeaders(): array 120 | { 121 | return $this->exposeHeaders ?? []; 122 | } 123 | 124 | public function getId(): ?string 125 | { 126 | return $this->id; 127 | } 128 | 129 | public function getMaxAgeSeconds(): ?int 130 | { 131 | return $this->maxAgeSeconds; 132 | } 133 | 134 | /** 135 | * @internal 136 | */ 137 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 138 | { 139 | if (null !== $v = $this->id) { 140 | $node->appendChild($document->createElement('ID', $v)); 141 | } 142 | if (null !== $v = $this->allowedHeaders) { 143 | foreach ($v as $item) { 144 | $node->appendChild($document->createElement('AllowedHeader', $item)); 145 | } 146 | } 147 | $v = $this->allowedMethods; 148 | foreach ($v as $item) { 149 | $node->appendChild($document->createElement('AllowedMethod', $item)); 150 | } 151 | 152 | $v = $this->allowedOrigins; 153 | foreach ($v as $item) { 154 | $node->appendChild($document->createElement('AllowedOrigin', $item)); 155 | } 156 | 157 | if (null !== $v = $this->exposeHeaders) { 158 | foreach ($v as $item) { 159 | $node->appendChild($document->createElement('ExposeHeader', $item)); 160 | } 161 | } 162 | if (null !== $v = $this->maxAgeSeconds) { 163 | $node->appendChild($document->createElement('MaxAgeSeconds', (string) $v)); 164 | } 165 | } 166 | 167 | /** 168 | * @return never 169 | */ 170 | private function throwException(\Throwable $exception) 171 | { 172 | throw $exception; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/ValueObject/CommonPrefix.php: -------------------------------------------------------------------------------- 1 | prefix = $input['Prefix'] ?? null; 27 | } 28 | 29 | /** 30 | * @param array{ 31 | * Prefix?: null|string, 32 | * }|CommonPrefix $input 33 | */ 34 | public static function create($input): self 35 | { 36 | return $input instanceof self ? $input : new self($input); 37 | } 38 | 39 | public function getPrefix(): ?string 40 | { 41 | return $this->prefix; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/ValueObject/CompletedMultipartUpload.php: -------------------------------------------------------------------------------- 1 | , 22 | * } $input 23 | */ 24 | public function __construct(array $input) 25 | { 26 | $this->parts = isset($input['Parts']) ? array_map([CompletedPart::class, 'create'], $input['Parts']) : null; 27 | } 28 | 29 | /** 30 | * @param array{ 31 | * Parts?: null|array, 32 | * }|CompletedMultipartUpload $input 33 | */ 34 | public static function create($input): self 35 | { 36 | return $input instanceof self ? $input : new self($input); 37 | } 38 | 39 | /** 40 | * @return CompletedPart[] 41 | */ 42 | public function getParts(): array 43 | { 44 | return $this->parts ?? []; 45 | } 46 | 47 | /** 48 | * @internal 49 | */ 50 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 51 | { 52 | if (null !== $v = $this->parts) { 53 | foreach ($v as $item) { 54 | $node->appendChild($child = $document->createElement('Part')); 55 | 56 | $item->requestBody($child, $document); 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/ValueObject/CopyObjectResult.php: -------------------------------------------------------------------------------- 1 | etag = $input['ETag'] ?? null; 103 | $this->lastModified = $input['LastModified'] ?? null; 104 | $this->checksumType = $input['ChecksumType'] ?? null; 105 | $this->checksumCrc32 = $input['ChecksumCRC32'] ?? null; 106 | $this->checksumCrc32C = $input['ChecksumCRC32C'] ?? null; 107 | $this->checksumCrc64Nvme = $input['ChecksumCRC64NVME'] ?? null; 108 | $this->checksumSha1 = $input['ChecksumSHA1'] ?? null; 109 | $this->checksumSha256 = $input['ChecksumSHA256'] ?? null; 110 | } 111 | 112 | /** 113 | * @param array{ 114 | * ETag?: null|string, 115 | * LastModified?: null|\DateTimeImmutable, 116 | * ChecksumType?: null|ChecksumType::*, 117 | * ChecksumCRC32?: null|string, 118 | * ChecksumCRC32C?: null|string, 119 | * ChecksumCRC64NVME?: null|string, 120 | * ChecksumSHA1?: null|string, 121 | * ChecksumSHA256?: null|string, 122 | * }|CopyObjectResult $input 123 | */ 124 | public static function create($input): self 125 | { 126 | return $input instanceof self ? $input : new self($input); 127 | } 128 | 129 | public function getChecksumCrc32(): ?string 130 | { 131 | return $this->checksumCrc32; 132 | } 133 | 134 | public function getChecksumCrc32C(): ?string 135 | { 136 | return $this->checksumCrc32C; 137 | } 138 | 139 | public function getChecksumCrc64Nvme(): ?string 140 | { 141 | return $this->checksumCrc64Nvme; 142 | } 143 | 144 | public function getChecksumSha1(): ?string 145 | { 146 | return $this->checksumSha1; 147 | } 148 | 149 | public function getChecksumSha256(): ?string 150 | { 151 | return $this->checksumSha256; 152 | } 153 | 154 | /** 155 | * @return ChecksumType::*|null 156 | */ 157 | public function getChecksumType(): ?string 158 | { 159 | return $this->checksumType; 160 | } 161 | 162 | public function getEtag(): ?string 163 | { 164 | return $this->etag; 165 | } 166 | 167 | public function getLastModified(): ?\DateTimeImmutable 168 | { 169 | return $this->lastModified; 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/ValueObject/CopyPartResult.php: -------------------------------------------------------------------------------- 1 | etag = $input['ETag'] ?? null; 93 | $this->lastModified = $input['LastModified'] ?? null; 94 | $this->checksumCrc32 = $input['ChecksumCRC32'] ?? null; 95 | $this->checksumCrc32C = $input['ChecksumCRC32C'] ?? null; 96 | $this->checksumCrc64Nvme = $input['ChecksumCRC64NVME'] ?? null; 97 | $this->checksumSha1 = $input['ChecksumSHA1'] ?? null; 98 | $this->checksumSha256 = $input['ChecksumSHA256'] ?? null; 99 | } 100 | 101 | /** 102 | * @param array{ 103 | * ETag?: null|string, 104 | * LastModified?: null|\DateTimeImmutable, 105 | * ChecksumCRC32?: null|string, 106 | * ChecksumCRC32C?: null|string, 107 | * ChecksumCRC64NVME?: null|string, 108 | * ChecksumSHA1?: null|string, 109 | * ChecksumSHA256?: null|string, 110 | * }|CopyPartResult $input 111 | */ 112 | public static function create($input): self 113 | { 114 | return $input instanceof self ? $input : new self($input); 115 | } 116 | 117 | public function getChecksumCrc32(): ?string 118 | { 119 | return $this->checksumCrc32; 120 | } 121 | 122 | public function getChecksumCrc32C(): ?string 123 | { 124 | return $this->checksumCrc32C; 125 | } 126 | 127 | public function getChecksumCrc64Nvme(): ?string 128 | { 129 | return $this->checksumCrc64Nvme; 130 | } 131 | 132 | public function getChecksumSha1(): ?string 133 | { 134 | return $this->checksumSha1; 135 | } 136 | 137 | public function getChecksumSha256(): ?string 138 | { 139 | return $this->checksumSha256; 140 | } 141 | 142 | public function getEtag(): ?string 143 | { 144 | return $this->etag; 145 | } 146 | 147 | public function getLastModified(): ?\DateTimeImmutable 148 | { 149 | return $this->lastModified; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/ValueObject/CreateBucketConfiguration.php: -------------------------------------------------------------------------------- 1 | This functionality is not supported for directory buckets. 24 | * 25 | * [^1]: https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region 26 | * 27 | * @var BucketLocationConstraint::*|null 28 | */ 29 | private $locationConstraint; 30 | 31 | /** 32 | * Specifies the location where the bucket will be created. 33 | * 34 | * **Directory buckets ** - The location type is Availability Zone or Local Zone. To use the Local Zone location type, 35 | * your account must be enabled for Local Zones. Otherwise, you get an HTTP `403 Forbidden` error with the error code 36 | * `AccessDenied`. To learn more, see Enable accounts for Local Zones [^1] in the *Amazon S3 User Guide*. 37 | * 38 | * > This functionality is only supported by directory buckets. 39 | * 40 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/opt-in-directory-bucket-lz.html 41 | * 42 | * @var LocationInfo|null 43 | */ 44 | private $location; 45 | 46 | /** 47 | * Specifies the information about the bucket that will be created. 48 | * 49 | * > This functionality is only supported by directory buckets. 50 | * 51 | * @var BucketInfo|null 52 | */ 53 | private $bucket; 54 | 55 | /** 56 | * @param array{ 57 | * LocationConstraint?: null|BucketLocationConstraint::*, 58 | * Location?: null|LocationInfo|array, 59 | * Bucket?: null|BucketInfo|array, 60 | * } $input 61 | */ 62 | public function __construct(array $input) 63 | { 64 | $this->locationConstraint = $input['LocationConstraint'] ?? null; 65 | $this->location = isset($input['Location']) ? LocationInfo::create($input['Location']) : null; 66 | $this->bucket = isset($input['Bucket']) ? BucketInfo::create($input['Bucket']) : null; 67 | } 68 | 69 | /** 70 | * @param array{ 71 | * LocationConstraint?: null|BucketLocationConstraint::*, 72 | * Location?: null|LocationInfo|array, 73 | * Bucket?: null|BucketInfo|array, 74 | * }|CreateBucketConfiguration $input 75 | */ 76 | public static function create($input): self 77 | { 78 | return $input instanceof self ? $input : new self($input); 79 | } 80 | 81 | public function getBucket(): ?BucketInfo 82 | { 83 | return $this->bucket; 84 | } 85 | 86 | public function getLocation(): ?LocationInfo 87 | { 88 | return $this->location; 89 | } 90 | 91 | /** 92 | * @return BucketLocationConstraint::*|null 93 | */ 94 | public function getLocationConstraint(): ?string 95 | { 96 | return $this->locationConstraint; 97 | } 98 | 99 | /** 100 | * @internal 101 | */ 102 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 103 | { 104 | if (null !== $v = $this->locationConstraint) { 105 | if (!BucketLocationConstraint::exists($v)) { 106 | throw new InvalidArgument(\sprintf('Invalid parameter "LocationConstraint" for "%s". The value "%s" is not a valid "BucketLocationConstraint".', __CLASS__, $v)); 107 | } 108 | $node->appendChild($document->createElement('LocationConstraint', $v)); 109 | } 110 | if (null !== $v = $this->location) { 111 | $node->appendChild($child = $document->createElement('Location')); 112 | 113 | $v->requestBody($child, $document); 114 | } 115 | if (null !== $v = $this->bucket) { 116 | $node->appendChild($child = $document->createElement('Bucket')); 117 | 118 | $v->requestBody($child, $document); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/ValueObject/Delete.php: -------------------------------------------------------------------------------- 1 | **Directory buckets** - For directory buckets, an object that's composed entirely of whitespace characters is not 16 | * > supported by the `DeleteObjects` API operation. The request will receive a `400 Bad Request` error and none of the 17 | * > objects in the request will be deleted. 18 | * 19 | * @var ObjectIdentifier[] 20 | */ 21 | private $objects; 22 | 23 | /** 24 | * Element to enable quiet mode for the request. When you add this element, you must set its value to `true`. 25 | * 26 | * @var bool|null 27 | */ 28 | private $quiet; 29 | 30 | /** 31 | * @param array{ 32 | * Objects: array, 33 | * Quiet?: null|bool, 34 | * } $input 35 | */ 36 | public function __construct(array $input) 37 | { 38 | $this->objects = isset($input['Objects']) ? array_map([ObjectIdentifier::class, 'create'], $input['Objects']) : $this->throwException(new InvalidArgument('Missing required field "Objects".')); 39 | $this->quiet = $input['Quiet'] ?? null; 40 | } 41 | 42 | /** 43 | * @param array{ 44 | * Objects: array, 45 | * Quiet?: null|bool, 46 | * }|Delete $input 47 | */ 48 | public static function create($input): self 49 | { 50 | return $input instanceof self ? $input : new self($input); 51 | } 52 | 53 | /** 54 | * @return ObjectIdentifier[] 55 | */ 56 | public function getObjects(): array 57 | { 58 | return $this->objects; 59 | } 60 | 61 | public function getQuiet(): ?bool 62 | { 63 | return $this->quiet; 64 | } 65 | 66 | /** 67 | * @internal 68 | */ 69 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 70 | { 71 | $v = $this->objects; 72 | foreach ($v as $item) { 73 | $node->appendChild($child = $document->createElement('Object')); 74 | 75 | $item->requestBody($child, $document); 76 | } 77 | 78 | if (null !== $v = $this->quiet) { 79 | $node->appendChild($document->createElement('Quiet', $v ? 'true' : 'false')); 80 | } 81 | } 82 | 83 | /** 84 | * @return never 85 | */ 86 | private function throwException(\Throwable $exception) 87 | { 88 | throw $exception; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/ValueObject/DeleteMarkerEntry.php: -------------------------------------------------------------------------------- 1 | owner = isset($input['Owner']) ? Owner::create($input['Owner']) : null; 57 | $this->key = $input['Key'] ?? null; 58 | $this->versionId = $input['VersionId'] ?? null; 59 | $this->isLatest = $input['IsLatest'] ?? null; 60 | $this->lastModified = $input['LastModified'] ?? null; 61 | } 62 | 63 | /** 64 | * @param array{ 65 | * Owner?: null|Owner|array, 66 | * Key?: null|string, 67 | * VersionId?: null|string, 68 | * IsLatest?: null|bool, 69 | * LastModified?: null|\DateTimeImmutable, 70 | * }|DeleteMarkerEntry $input 71 | */ 72 | public static function create($input): self 73 | { 74 | return $input instanceof self ? $input : new self($input); 75 | } 76 | 77 | public function getIsLatest(): ?bool 78 | { 79 | return $this->isLatest; 80 | } 81 | 82 | public function getKey(): ?string 83 | { 84 | return $this->key; 85 | } 86 | 87 | public function getLastModified(): ?\DateTimeImmutable 88 | { 89 | return $this->lastModified; 90 | } 91 | 92 | public function getOwner(): ?Owner 93 | { 94 | return $this->owner; 95 | } 96 | 97 | public function getVersionId(): ?string 98 | { 99 | return $this->versionId; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/ValueObject/DeletedObject.php: -------------------------------------------------------------------------------- 1 | This functionality is not supported for directory buckets. 21 | * 22 | * @var string|null 23 | */ 24 | private $versionId; 25 | 26 | /** 27 | * Indicates whether the specified object version that was permanently deleted was (true) or was not (false) a delete 28 | * marker before deletion. In a simple DELETE, this header indicates whether (true) or not (false) the current version 29 | * of the object is a delete marker. To learn more about delete markers, see Working with delete markers [^1]. 30 | * 31 | * > This functionality is not supported for directory buckets. 32 | * 33 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/DeleteMarker.html 34 | * 35 | * @var bool|null 36 | */ 37 | private $deleteMarker; 38 | 39 | /** 40 | * The version ID of the delete marker created as a result of the DELETE operation. If you delete a specific object 41 | * version, the value returned by this header is the version ID of the object version deleted. 42 | * 43 | * > This functionality is not supported for directory buckets. 44 | * 45 | * @var string|null 46 | */ 47 | private $deleteMarkerVersionId; 48 | 49 | /** 50 | * @param array{ 51 | * Key?: null|string, 52 | * VersionId?: null|string, 53 | * DeleteMarker?: null|bool, 54 | * DeleteMarkerVersionId?: null|string, 55 | * } $input 56 | */ 57 | public function __construct(array $input) 58 | { 59 | $this->key = $input['Key'] ?? null; 60 | $this->versionId = $input['VersionId'] ?? null; 61 | $this->deleteMarker = $input['DeleteMarker'] ?? null; 62 | $this->deleteMarkerVersionId = $input['DeleteMarkerVersionId'] ?? null; 63 | } 64 | 65 | /** 66 | * @param array{ 67 | * Key?: null|string, 68 | * VersionId?: null|string, 69 | * DeleteMarker?: null|bool, 70 | * DeleteMarkerVersionId?: null|string, 71 | * }|DeletedObject $input 72 | */ 73 | public static function create($input): self 74 | { 75 | return $input instanceof self ? $input : new self($input); 76 | } 77 | 78 | public function getDeleteMarker(): ?bool 79 | { 80 | return $this->deleteMarker; 81 | } 82 | 83 | public function getDeleteMarkerVersionId(): ?string 84 | { 85 | return $this->deleteMarkerVersionId; 86 | } 87 | 88 | public function getKey(): ?string 89 | { 90 | return $this->key; 91 | } 92 | 93 | public function getVersionId(): ?string 94 | { 95 | return $this->versionId; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/ValueObject/EventBridgeConfiguration.php: -------------------------------------------------------------------------------- 1 | name = $input['Name'] ?? null; 45 | $this->value = $input['Value'] ?? null; 46 | } 47 | 48 | /** 49 | * @param array{ 50 | * Name?: null|FilterRuleName::*, 51 | * Value?: null|string, 52 | * }|FilterRule $input 53 | */ 54 | public static function create($input): self 55 | { 56 | return $input instanceof self ? $input : new self($input); 57 | } 58 | 59 | /** 60 | * @return FilterRuleName::*|null 61 | */ 62 | public function getName(): ?string 63 | { 64 | return $this->name; 65 | } 66 | 67 | public function getValue(): ?string 68 | { 69 | return $this->value; 70 | } 71 | 72 | /** 73 | * @internal 74 | */ 75 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 76 | { 77 | if (null !== $v = $this->name) { 78 | if (!FilterRuleName::exists($v)) { 79 | throw new InvalidArgument(\sprintf('Invalid parameter "Name" for "%s". The value "%s" is not a valid "FilterRuleName".', __CLASS__, $v)); 80 | } 81 | $node->appendChild($document->createElement('Name', $v)); 82 | } 83 | if (null !== $v = $this->value) { 84 | $node->appendChild($document->createElement('Value', $v)); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/ValueObject/Grant.php: -------------------------------------------------------------------------------- 1 | grantee = isset($input['Grantee']) ? Grantee::create($input['Grantee']) : null; 36 | $this->permission = $input['Permission'] ?? null; 37 | } 38 | 39 | /** 40 | * @param array{ 41 | * Grantee?: null|Grantee|array, 42 | * Permission?: null|Permission::*, 43 | * }|Grant $input 44 | */ 45 | public static function create($input): self 46 | { 47 | return $input instanceof self ? $input : new self($input); 48 | } 49 | 50 | public function getGrantee(): ?Grantee 51 | { 52 | return $this->grantee; 53 | } 54 | 55 | /** 56 | * @return Permission::*|null 57 | */ 58 | public function getPermission(): ?string 59 | { 60 | return $this->permission; 61 | } 62 | 63 | /** 64 | * @internal 65 | */ 66 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 67 | { 68 | if (null !== $v = $this->grantee) { 69 | $node->appendChild($child = $document->createElement('Grantee')); 70 | $child->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); 71 | $v->requestBody($child, $document); 72 | } 73 | if (null !== $v = $this->permission) { 74 | if (!Permission::exists($v)) { 75 | throw new InvalidArgument(\sprintf('Invalid parameter "Permission" for "%s". The value "%s" is not a valid "Permission".', __CLASS__, $v)); 76 | } 77 | $node->appendChild($document->createElement('Permission', $v)); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/ValueObject/Grantee.php: -------------------------------------------------------------------------------- 1 | Using email addresses to specify a grantee is only supported in the following Amazon Web Services Regions: 24 | * > 25 | * > - US East (N. Virginia) 26 | * > - US West (N. California) 27 | * > - US West (Oregon) 28 | * > - Asia Pacific (Singapore) 29 | * > - Asia Pacific (Sydney) 30 | * > - Asia Pacific (Tokyo) 31 | * > - Europe (Ireland) 32 | * > - South America (São Paulo) 33 | * > 34 | * > For a list of all the Amazon S3 supported Regions and endpoints, see Regions and Endpoints [^1] in the Amazon Web 35 | * > Services General Reference. 36 | * 37 | * [^1]: https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region 38 | * 39 | * @var string|null 40 | */ 41 | private $emailAddress; 42 | 43 | /** 44 | * The canonical user ID of the grantee. 45 | * 46 | * @var string|null 47 | */ 48 | private $id; 49 | 50 | /** 51 | * Type of grantee. 52 | * 53 | * @var Type::* 54 | */ 55 | private $type; 56 | 57 | /** 58 | * URI of the grantee group. 59 | * 60 | * @var string|null 61 | */ 62 | private $uri; 63 | 64 | /** 65 | * @param array{ 66 | * DisplayName?: null|string, 67 | * EmailAddress?: null|string, 68 | * ID?: null|string, 69 | * Type: Type::*, 70 | * URI?: null|string, 71 | * } $input 72 | */ 73 | public function __construct(array $input) 74 | { 75 | $this->displayName = $input['DisplayName'] ?? null; 76 | $this->emailAddress = $input['EmailAddress'] ?? null; 77 | $this->id = $input['ID'] ?? null; 78 | $this->type = $input['Type'] ?? $this->throwException(new InvalidArgument('Missing required field "Type".')); 79 | $this->uri = $input['URI'] ?? null; 80 | } 81 | 82 | /** 83 | * @param array{ 84 | * DisplayName?: null|string, 85 | * EmailAddress?: null|string, 86 | * ID?: null|string, 87 | * Type: Type::*, 88 | * URI?: null|string, 89 | * }|Grantee $input 90 | */ 91 | public static function create($input): self 92 | { 93 | return $input instanceof self ? $input : new self($input); 94 | } 95 | 96 | public function getDisplayName(): ?string 97 | { 98 | return $this->displayName; 99 | } 100 | 101 | public function getEmailAddress(): ?string 102 | { 103 | return $this->emailAddress; 104 | } 105 | 106 | public function getId(): ?string 107 | { 108 | return $this->id; 109 | } 110 | 111 | /** 112 | * @return Type::* 113 | */ 114 | public function getType(): string 115 | { 116 | return $this->type; 117 | } 118 | 119 | public function getUri(): ?string 120 | { 121 | return $this->uri; 122 | } 123 | 124 | /** 125 | * @internal 126 | */ 127 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 128 | { 129 | if (null !== $v = $this->displayName) { 130 | $node->appendChild($document->createElement('DisplayName', $v)); 131 | } 132 | if (null !== $v = $this->emailAddress) { 133 | $node->appendChild($document->createElement('EmailAddress', $v)); 134 | } 135 | if (null !== $v = $this->id) { 136 | $node->appendChild($document->createElement('ID', $v)); 137 | } 138 | $v = $this->type; 139 | if (!Type::exists($v)) { 140 | throw new InvalidArgument(\sprintf('Invalid parameter "xsi:type" for "%s". The value "%s" is not a valid "Type".', __CLASS__, $v)); 141 | } 142 | $node->setAttribute('xsi:type', $v); 143 | if (null !== $v = $this->uri) { 144 | $node->appendChild($document->createElement('URI', $v)); 145 | } 146 | } 147 | 148 | /** 149 | * @return never 150 | */ 151 | private function throwException(\Throwable $exception) 152 | { 153 | throw $exception; 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/ValueObject/Initiator.php: -------------------------------------------------------------------------------- 1 | **Directory buckets** - If the principal is an Amazon Web Services account, it provides the Amazon Web Services 15 | * > account ID. If the principal is an IAM User, it provides a user ARN value. 16 | * 17 | * @var string|null 18 | */ 19 | private $id; 20 | 21 | /** 22 | * Name of the Principal. 23 | * 24 | * > This functionality is not supported for directory buckets. 25 | * 26 | * @var string|null 27 | */ 28 | private $displayName; 29 | 30 | /** 31 | * @param array{ 32 | * ID?: null|string, 33 | * DisplayName?: null|string, 34 | * } $input 35 | */ 36 | public function __construct(array $input) 37 | { 38 | $this->id = $input['ID'] ?? null; 39 | $this->displayName = $input['DisplayName'] ?? null; 40 | } 41 | 42 | /** 43 | * @param array{ 44 | * ID?: null|string, 45 | * DisplayName?: null|string, 46 | * }|Initiator $input 47 | */ 48 | public static function create($input): self 49 | { 50 | return $input instanceof self ? $input : new self($input); 51 | } 52 | 53 | public function getDisplayName(): ?string 54 | { 55 | return $this->displayName; 56 | } 57 | 58 | public function getId(): ?string 59 | { 60 | return $this->id; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/ValueObject/LambdaFunctionConfiguration.php: -------------------------------------------------------------------------------- 1 | 32 | */ 33 | private $events; 34 | 35 | /** 36 | * @var NotificationConfigurationFilter|null 37 | */ 38 | private $filter; 39 | 40 | /** 41 | * @param array{ 42 | * Id?: null|string, 43 | * LambdaFunctionArn: string, 44 | * Events: array, 45 | * Filter?: null|NotificationConfigurationFilter|array, 46 | * } $input 47 | */ 48 | public function __construct(array $input) 49 | { 50 | $this->id = $input['Id'] ?? null; 51 | $this->lambdaFunctionArn = $input['LambdaFunctionArn'] ?? $this->throwException(new InvalidArgument('Missing required field "LambdaFunctionArn".')); 52 | $this->events = $input['Events'] ?? $this->throwException(new InvalidArgument('Missing required field "Events".')); 53 | $this->filter = isset($input['Filter']) ? NotificationConfigurationFilter::create($input['Filter']) : null; 54 | } 55 | 56 | /** 57 | * @param array{ 58 | * Id?: null|string, 59 | * LambdaFunctionArn: string, 60 | * Events: array, 61 | * Filter?: null|NotificationConfigurationFilter|array, 62 | * }|LambdaFunctionConfiguration $input 63 | */ 64 | public static function create($input): self 65 | { 66 | return $input instanceof self ? $input : new self($input); 67 | } 68 | 69 | /** 70 | * @return list 71 | */ 72 | public function getEvents(): array 73 | { 74 | return $this->events; 75 | } 76 | 77 | public function getFilter(): ?NotificationConfigurationFilter 78 | { 79 | return $this->filter; 80 | } 81 | 82 | public function getId(): ?string 83 | { 84 | return $this->id; 85 | } 86 | 87 | public function getLambdaFunctionArn(): string 88 | { 89 | return $this->lambdaFunctionArn; 90 | } 91 | 92 | /** 93 | * @internal 94 | */ 95 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 96 | { 97 | if (null !== $v = $this->id) { 98 | $node->appendChild($document->createElement('Id', $v)); 99 | } 100 | $v = $this->lambdaFunctionArn; 101 | $node->appendChild($document->createElement('CloudFunction', $v)); 102 | $v = $this->events; 103 | foreach ($v as $item) { 104 | if (!Event::exists($item)) { 105 | throw new InvalidArgument(\sprintf('Invalid parameter "Event" for "%s". The value "%s" is not a valid "Event".', __CLASS__, $item)); 106 | } 107 | $node->appendChild($document->createElement('Event', $item)); 108 | } 109 | 110 | if (null !== $v = $this->filter) { 111 | $node->appendChild($child = $document->createElement('Filter')); 112 | 113 | $v->requestBody($child, $document); 114 | } 115 | } 116 | 117 | /** 118 | * @return never 119 | */ 120 | private function throwException(\Throwable $exception) 121 | { 122 | throw $exception; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/ValueObject/LocationInfo.php: -------------------------------------------------------------------------------- 1 | This functionality is only supported by directory buckets. 15 | * 16 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-overview.html 17 | */ 18 | final class LocationInfo 19 | { 20 | /** 21 | * The type of location where the bucket will be created. 22 | * 23 | * @var LocationType::*|null 24 | */ 25 | private $type; 26 | 27 | /** 28 | * The name of the location where the bucket will be created. 29 | * 30 | * For directory buckets, the name of the location is the Zone ID of the Availability Zone (AZ) or Local Zone (LZ) where 31 | * the bucket will be created. An example AZ ID value is `usw2-az1`. 32 | * 33 | * @var string|null 34 | */ 35 | private $name; 36 | 37 | /** 38 | * @param array{ 39 | * Type?: null|LocationType::*, 40 | * Name?: null|string, 41 | * } $input 42 | */ 43 | public function __construct(array $input) 44 | { 45 | $this->type = $input['Type'] ?? null; 46 | $this->name = $input['Name'] ?? null; 47 | } 48 | 49 | /** 50 | * @param array{ 51 | * Type?: null|LocationType::*, 52 | * Name?: null|string, 53 | * }|LocationInfo $input 54 | */ 55 | public static function create($input): self 56 | { 57 | return $input instanceof self ? $input : new self($input); 58 | } 59 | 60 | public function getName(): ?string 61 | { 62 | return $this->name; 63 | } 64 | 65 | /** 66 | * @return LocationType::*|null 67 | */ 68 | public function getType(): ?string 69 | { 70 | return $this->type; 71 | } 72 | 73 | /** 74 | * @internal 75 | */ 76 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 77 | { 78 | if (null !== $v = $this->type) { 79 | if (!LocationType::exists($v)) { 80 | throw new InvalidArgument(\sprintf('Invalid parameter "Type" for "%s". The value "%s" is not a valid "LocationType".', __CLASS__, $v)); 81 | } 82 | $node->appendChild($document->createElement('Type', $v)); 83 | } 84 | if (null !== $v = $this->name) { 85 | $node->appendChild($document->createElement('Name', $v)); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/ValueObject/MultipartUpload.php: -------------------------------------------------------------------------------- 1 | **Directory buckets** - Directory buckets only support `EXPRESS_ONEZONE` (the S3 Express One Zone storage class) in 39 | * > Availability Zones and `ONEZONE_IA` (the S3 One Zone-Infrequent Access storage class) in Dedicated Local Zones. 40 | * 41 | * @var StorageClass::*|null 42 | */ 43 | private $storageClass; 44 | 45 | /** 46 | * Specifies the owner of the object that is part of the multipart upload. 47 | * 48 | * > **Directory buckets** - The bucket owner is returned as the object owner for all the objects. 49 | * 50 | * @var Owner|null 51 | */ 52 | private $owner; 53 | 54 | /** 55 | * Identifies who initiated the multipart upload. 56 | * 57 | * @var Initiator|null 58 | */ 59 | private $initiator; 60 | 61 | /** 62 | * The algorithm that was used to create a checksum of the object. 63 | * 64 | * @var ChecksumAlgorithm::*|null 65 | */ 66 | private $checksumAlgorithm; 67 | 68 | /** 69 | * The checksum type that is used to calculate the object’s checksum value. For more information, see Checking object 70 | * integrity [^1] in the *Amazon S3 User Guide*. 71 | * 72 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html 73 | * 74 | * @var ChecksumType::*|null 75 | */ 76 | private $checksumType; 77 | 78 | /** 79 | * @param array{ 80 | * UploadId?: null|string, 81 | * Key?: null|string, 82 | * Initiated?: null|\DateTimeImmutable, 83 | * StorageClass?: null|StorageClass::*, 84 | * Owner?: null|Owner|array, 85 | * Initiator?: null|Initiator|array, 86 | * ChecksumAlgorithm?: null|ChecksumAlgorithm::*, 87 | * ChecksumType?: null|ChecksumType::*, 88 | * } $input 89 | */ 90 | public function __construct(array $input) 91 | { 92 | $this->uploadId = $input['UploadId'] ?? null; 93 | $this->key = $input['Key'] ?? null; 94 | $this->initiated = $input['Initiated'] ?? null; 95 | $this->storageClass = $input['StorageClass'] ?? null; 96 | $this->owner = isset($input['Owner']) ? Owner::create($input['Owner']) : null; 97 | $this->initiator = isset($input['Initiator']) ? Initiator::create($input['Initiator']) : null; 98 | $this->checksumAlgorithm = $input['ChecksumAlgorithm'] ?? null; 99 | $this->checksumType = $input['ChecksumType'] ?? null; 100 | } 101 | 102 | /** 103 | * @param array{ 104 | * UploadId?: null|string, 105 | * Key?: null|string, 106 | * Initiated?: null|\DateTimeImmutable, 107 | * StorageClass?: null|StorageClass::*, 108 | * Owner?: null|Owner|array, 109 | * Initiator?: null|Initiator|array, 110 | * ChecksumAlgorithm?: null|ChecksumAlgorithm::*, 111 | * ChecksumType?: null|ChecksumType::*, 112 | * }|MultipartUpload $input 113 | */ 114 | public static function create($input): self 115 | { 116 | return $input instanceof self ? $input : new self($input); 117 | } 118 | 119 | /** 120 | * @return ChecksumAlgorithm::*|null 121 | */ 122 | public function getChecksumAlgorithm(): ?string 123 | { 124 | return $this->checksumAlgorithm; 125 | } 126 | 127 | /** 128 | * @return ChecksumType::*|null 129 | */ 130 | public function getChecksumType(): ?string 131 | { 132 | return $this->checksumType; 133 | } 134 | 135 | public function getInitiated(): ?\DateTimeImmutable 136 | { 137 | return $this->initiated; 138 | } 139 | 140 | public function getInitiator(): ?Initiator 141 | { 142 | return $this->initiator; 143 | } 144 | 145 | public function getKey(): ?string 146 | { 147 | return $this->key; 148 | } 149 | 150 | public function getOwner(): ?Owner 151 | { 152 | return $this->owner; 153 | } 154 | 155 | /** 156 | * @return StorageClass::*|null 157 | */ 158 | public function getStorageClass(): ?string 159 | { 160 | return $this->storageClass; 161 | } 162 | 163 | public function getUploadId(): ?string 164 | { 165 | return $this->uploadId; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/ValueObject/NotificationConfiguration.php: -------------------------------------------------------------------------------- 1 | , 42 | * QueueConfigurations?: null|array, 43 | * LambdaFunctionConfigurations?: null|array, 44 | * EventBridgeConfiguration?: null|EventBridgeConfiguration|array, 45 | * } $input 46 | */ 47 | public function __construct(array $input) 48 | { 49 | $this->topicConfigurations = isset($input['TopicConfigurations']) ? array_map([TopicConfiguration::class, 'create'], $input['TopicConfigurations']) : null; 50 | $this->queueConfigurations = isset($input['QueueConfigurations']) ? array_map([QueueConfiguration::class, 'create'], $input['QueueConfigurations']) : null; 51 | $this->lambdaFunctionConfigurations = isset($input['LambdaFunctionConfigurations']) ? array_map([LambdaFunctionConfiguration::class, 'create'], $input['LambdaFunctionConfigurations']) : null; 52 | $this->eventBridgeConfiguration = isset($input['EventBridgeConfiguration']) ? EventBridgeConfiguration::create($input['EventBridgeConfiguration']) : null; 53 | } 54 | 55 | /** 56 | * @param array{ 57 | * TopicConfigurations?: null|array, 58 | * QueueConfigurations?: null|array, 59 | * LambdaFunctionConfigurations?: null|array, 60 | * EventBridgeConfiguration?: null|EventBridgeConfiguration|array, 61 | * }|NotificationConfiguration $input 62 | */ 63 | public static function create($input): self 64 | { 65 | return $input instanceof self ? $input : new self($input); 66 | } 67 | 68 | public function getEventBridgeConfiguration(): ?EventBridgeConfiguration 69 | { 70 | return $this->eventBridgeConfiguration; 71 | } 72 | 73 | /** 74 | * @return LambdaFunctionConfiguration[] 75 | */ 76 | public function getLambdaFunctionConfigurations(): array 77 | { 78 | return $this->lambdaFunctionConfigurations ?? []; 79 | } 80 | 81 | /** 82 | * @return QueueConfiguration[] 83 | */ 84 | public function getQueueConfigurations(): array 85 | { 86 | return $this->queueConfigurations ?? []; 87 | } 88 | 89 | /** 90 | * @return TopicConfiguration[] 91 | */ 92 | public function getTopicConfigurations(): array 93 | { 94 | return $this->topicConfigurations ?? []; 95 | } 96 | 97 | /** 98 | * @internal 99 | */ 100 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 101 | { 102 | if (null !== $v = $this->topicConfigurations) { 103 | foreach ($v as $item) { 104 | $node->appendChild($child = $document->createElement('TopicConfiguration')); 105 | 106 | $item->requestBody($child, $document); 107 | } 108 | } 109 | if (null !== $v = $this->queueConfigurations) { 110 | foreach ($v as $item) { 111 | $node->appendChild($child = $document->createElement('QueueConfiguration')); 112 | 113 | $item->requestBody($child, $document); 114 | } 115 | } 116 | if (null !== $v = $this->lambdaFunctionConfigurations) { 117 | foreach ($v as $item) { 118 | $node->appendChild($child = $document->createElement('CloudFunctionConfiguration')); 119 | 120 | $item->requestBody($child, $document); 121 | } 122 | } 123 | if (null !== $v = $this->eventBridgeConfiguration) { 124 | $node->appendChild($child = $document->createElement('EventBridgeConfiguration')); 125 | 126 | $v->requestBody($child, $document); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/ValueObject/NotificationConfigurationFilter.php: -------------------------------------------------------------------------------- 1 | key = isset($input['Key']) ? S3KeyFilter::create($input['Key']) : null; 26 | } 27 | 28 | /** 29 | * @param array{ 30 | * Key?: null|S3KeyFilter|array, 31 | * }|NotificationConfigurationFilter $input 32 | */ 33 | public static function create($input): self 34 | { 35 | return $input instanceof self ? $input : new self($input); 36 | } 37 | 38 | public function getKey(): ?S3KeyFilter 39 | { 40 | return $this->key; 41 | } 42 | 43 | /** 44 | * @internal 45 | */ 46 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 47 | { 48 | if (null !== $v = $this->key) { 49 | $node->appendChild($child = $document->createElement('S3Key')); 50 | 51 | $v->requestBody($child, $document); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/ValueObject/ObjectIdentifier.php: -------------------------------------------------------------------------------- 1 | This functionality is not supported for directory buckets. 28 | * 29 | * @var string|null 30 | */ 31 | private $versionId; 32 | 33 | /** 34 | * An entity tag (ETag) is an identifier assigned by a web server to a specific version of a resource found at a URL. 35 | * This header field makes the request method conditional on `ETags`. 36 | * 37 | * > Entity tags (ETags) for S3 Express One Zone are random alphanumeric strings unique to the object. 38 | * 39 | * @var string|null 40 | */ 41 | private $etag; 42 | 43 | /** 44 | * If present, the objects are deleted only if its modification times matches the provided `Timestamp`. 45 | * 46 | * > This functionality is only supported for directory buckets. 47 | * 48 | * @var \DateTimeImmutable|null 49 | */ 50 | private $lastModifiedTime; 51 | 52 | /** 53 | * If present, the objects are deleted only if its size matches the provided size in bytes. 54 | * 55 | * > This functionality is only supported for directory buckets. 56 | * 57 | * @var int|null 58 | */ 59 | private $size; 60 | 61 | /** 62 | * @param array{ 63 | * Key: string, 64 | * VersionId?: null|string, 65 | * ETag?: null|string, 66 | * LastModifiedTime?: null|\DateTimeImmutable, 67 | * Size?: null|int, 68 | * } $input 69 | */ 70 | public function __construct(array $input) 71 | { 72 | $this->key = $input['Key'] ?? $this->throwException(new InvalidArgument('Missing required field "Key".')); 73 | $this->versionId = $input['VersionId'] ?? null; 74 | $this->etag = $input['ETag'] ?? null; 75 | $this->lastModifiedTime = $input['LastModifiedTime'] ?? null; 76 | $this->size = $input['Size'] ?? null; 77 | } 78 | 79 | /** 80 | * @param array{ 81 | * Key: string, 82 | * VersionId?: null|string, 83 | * ETag?: null|string, 84 | * LastModifiedTime?: null|\DateTimeImmutable, 85 | * Size?: null|int, 86 | * }|ObjectIdentifier $input 87 | */ 88 | public static function create($input): self 89 | { 90 | return $input instanceof self ? $input : new self($input); 91 | } 92 | 93 | public function getEtag(): ?string 94 | { 95 | return $this->etag; 96 | } 97 | 98 | public function getKey(): string 99 | { 100 | return $this->key; 101 | } 102 | 103 | public function getLastModifiedTime(): ?\DateTimeImmutable 104 | { 105 | return $this->lastModifiedTime; 106 | } 107 | 108 | public function getSize(): ?int 109 | { 110 | return $this->size; 111 | } 112 | 113 | public function getVersionId(): ?string 114 | { 115 | return $this->versionId; 116 | } 117 | 118 | /** 119 | * @internal 120 | */ 121 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 122 | { 123 | $v = $this->key; 124 | $node->appendChild($document->createElement('Key', $v)); 125 | if (null !== $v = $this->versionId) { 126 | $node->appendChild($document->createElement('VersionId', $v)); 127 | } 128 | if (null !== $v = $this->etag) { 129 | $node->appendChild($document->createElement('ETag', $v)); 130 | } 131 | if (null !== $v = $this->lastModifiedTime) { 132 | $node->appendChild($document->createElement('LastModifiedTime', $v->format(\DateTimeInterface::RFC822))); 133 | } 134 | if (null !== $v = $this->size) { 135 | $node->appendChild($document->createElement('Size', (string) $v)); 136 | } 137 | } 138 | 139 | /** 140 | * @return never 141 | */ 142 | private function throwException(\Throwable $exception) 143 | { 144 | throw $exception; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/ValueObject/Owner.php: -------------------------------------------------------------------------------- 1 | This functionality is not supported for directory buckets. 24 | * 25 | * @var string|null 26 | */ 27 | private $displayName; 28 | 29 | /** 30 | * Container for the ID of the owner. 31 | * 32 | * @var string|null 33 | */ 34 | private $id; 35 | 36 | /** 37 | * @param array{ 38 | * DisplayName?: null|string, 39 | * ID?: null|string, 40 | * } $input 41 | */ 42 | public function __construct(array $input) 43 | { 44 | $this->displayName = $input['DisplayName'] ?? null; 45 | $this->id = $input['ID'] ?? null; 46 | } 47 | 48 | /** 49 | * @param array{ 50 | * DisplayName?: null|string, 51 | * ID?: null|string, 52 | * }|Owner $input 53 | */ 54 | public static function create($input): self 55 | { 56 | return $input instanceof self ? $input : new self($input); 57 | } 58 | 59 | public function getDisplayName(): ?string 60 | { 61 | return $this->displayName; 62 | } 63 | 64 | public function getId(): ?string 65 | { 66 | return $this->id; 67 | } 68 | 69 | /** 70 | * @internal 71 | */ 72 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 73 | { 74 | if (null !== $v = $this->displayName) { 75 | $node->appendChild($document->createElement('DisplayName', $v)); 76 | } 77 | if (null !== $v = $this->id) { 78 | $node->appendChild($document->createElement('ID', $v)); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/ValueObject/Part.php: -------------------------------------------------------------------------------- 1 | partNumber = $input['PartNumber'] ?? null; 108 | $this->lastModified = $input['LastModified'] ?? null; 109 | $this->etag = $input['ETag'] ?? null; 110 | $this->size = $input['Size'] ?? null; 111 | $this->checksumCrc32 = $input['ChecksumCRC32'] ?? null; 112 | $this->checksumCrc32C = $input['ChecksumCRC32C'] ?? null; 113 | $this->checksumCrc64Nvme = $input['ChecksumCRC64NVME'] ?? null; 114 | $this->checksumSha1 = $input['ChecksumSHA1'] ?? null; 115 | $this->checksumSha256 = $input['ChecksumSHA256'] ?? null; 116 | } 117 | 118 | /** 119 | * @param array{ 120 | * PartNumber?: null|int, 121 | * LastModified?: null|\DateTimeImmutable, 122 | * ETag?: null|string, 123 | * Size?: null|int, 124 | * ChecksumCRC32?: null|string, 125 | * ChecksumCRC32C?: null|string, 126 | * ChecksumCRC64NVME?: null|string, 127 | * ChecksumSHA1?: null|string, 128 | * ChecksumSHA256?: null|string, 129 | * }|Part $input 130 | */ 131 | public static function create($input): self 132 | { 133 | return $input instanceof self ? $input : new self($input); 134 | } 135 | 136 | public function getChecksumCrc32(): ?string 137 | { 138 | return $this->checksumCrc32; 139 | } 140 | 141 | public function getChecksumCrc32C(): ?string 142 | { 143 | return $this->checksumCrc32C; 144 | } 145 | 146 | public function getChecksumCrc64Nvme(): ?string 147 | { 148 | return $this->checksumCrc64Nvme; 149 | } 150 | 151 | public function getChecksumSha1(): ?string 152 | { 153 | return $this->checksumSha1; 154 | } 155 | 156 | public function getChecksumSha256(): ?string 157 | { 158 | return $this->checksumSha256; 159 | } 160 | 161 | public function getEtag(): ?string 162 | { 163 | return $this->etag; 164 | } 165 | 166 | public function getLastModified(): ?\DateTimeImmutable 167 | { 168 | return $this->lastModified; 169 | } 170 | 171 | public function getPartNumber(): ?int 172 | { 173 | return $this->partNumber; 174 | } 175 | 176 | public function getSize(): ?int 177 | { 178 | return $this->size; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/ValueObject/QueueConfiguration.php: -------------------------------------------------------------------------------- 1 | 31 | */ 32 | private $events; 33 | 34 | /** 35 | * @var NotificationConfigurationFilter|null 36 | */ 37 | private $filter; 38 | 39 | /** 40 | * @param array{ 41 | * Id?: null|string, 42 | * QueueArn: string, 43 | * Events: array, 44 | * Filter?: null|NotificationConfigurationFilter|array, 45 | * } $input 46 | */ 47 | public function __construct(array $input) 48 | { 49 | $this->id = $input['Id'] ?? null; 50 | $this->queueArn = $input['QueueArn'] ?? $this->throwException(new InvalidArgument('Missing required field "QueueArn".')); 51 | $this->events = $input['Events'] ?? $this->throwException(new InvalidArgument('Missing required field "Events".')); 52 | $this->filter = isset($input['Filter']) ? NotificationConfigurationFilter::create($input['Filter']) : null; 53 | } 54 | 55 | /** 56 | * @param array{ 57 | * Id?: null|string, 58 | * QueueArn: string, 59 | * Events: array, 60 | * Filter?: null|NotificationConfigurationFilter|array, 61 | * }|QueueConfiguration $input 62 | */ 63 | public static function create($input): self 64 | { 65 | return $input instanceof self ? $input : new self($input); 66 | } 67 | 68 | /** 69 | * @return list 70 | */ 71 | public function getEvents(): array 72 | { 73 | return $this->events; 74 | } 75 | 76 | public function getFilter(): ?NotificationConfigurationFilter 77 | { 78 | return $this->filter; 79 | } 80 | 81 | public function getId(): ?string 82 | { 83 | return $this->id; 84 | } 85 | 86 | public function getQueueArn(): string 87 | { 88 | return $this->queueArn; 89 | } 90 | 91 | /** 92 | * @internal 93 | */ 94 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 95 | { 96 | if (null !== $v = $this->id) { 97 | $node->appendChild($document->createElement('Id', $v)); 98 | } 99 | $v = $this->queueArn; 100 | $node->appendChild($document->createElement('Queue', $v)); 101 | $v = $this->events; 102 | foreach ($v as $item) { 103 | if (!Event::exists($item)) { 104 | throw new InvalidArgument(\sprintf('Invalid parameter "Event" for "%s". The value "%s" is not a valid "Event".', __CLASS__, $item)); 105 | } 106 | $node->appendChild($document->createElement('Event', $item)); 107 | } 108 | 109 | if (null !== $v = $this->filter) { 110 | $node->appendChild($child = $document->createElement('Filter')); 111 | 112 | $v->requestBody($child, $document); 113 | } 114 | } 115 | 116 | /** 117 | * @return never 118 | */ 119 | private function throwException(\Throwable $exception) 120 | { 121 | throw $exception; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/ValueObject/RestoreStatus.php: -------------------------------------------------------------------------------- 1 | This functionality is not supported for directory buckets. Directory buckets only support `EXPRESS_ONEZONE` (the S3 11 | * > Express One Zone storage class) in Availability Zones and `ONEZONE_IA` (the S3 One Zone-Infrequent Access storage 12 | * > class) in Dedicated Local Zones. 13 | * 14 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/archived-objects.html 15 | */ 16 | final class RestoreStatus 17 | { 18 | /** 19 | * Specifies whether the object is currently being restored. If the object restoration is in progress, the header 20 | * returns the value `TRUE`. For example: 21 | * 22 | * `x-amz-optional-object-attributes: IsRestoreInProgress="true"` 23 | * 24 | * If the object restoration has completed, the header returns the value `FALSE`. For example: 25 | * 26 | * `x-amz-optional-object-attributes: IsRestoreInProgress="false", RestoreExpiryDate="2012-12-21T00:00:00.000Z"` 27 | * 28 | * If the object hasn't been restored, there is no header response. 29 | * 30 | * @var bool|null 31 | */ 32 | private $isRestoreInProgress; 33 | 34 | /** 35 | * Indicates when the restored copy will expire. This value is populated only if the object has already been restored. 36 | * For example: 37 | * 38 | * `x-amz-optional-object-attributes: IsRestoreInProgress="false", RestoreExpiryDate="2012-12-21T00:00:00.000Z"` 39 | * 40 | * @var \DateTimeImmutable|null 41 | */ 42 | private $restoreExpiryDate; 43 | 44 | /** 45 | * @param array{ 46 | * IsRestoreInProgress?: null|bool, 47 | * RestoreExpiryDate?: null|\DateTimeImmutable, 48 | * } $input 49 | */ 50 | public function __construct(array $input) 51 | { 52 | $this->isRestoreInProgress = $input['IsRestoreInProgress'] ?? null; 53 | $this->restoreExpiryDate = $input['RestoreExpiryDate'] ?? null; 54 | } 55 | 56 | /** 57 | * @param array{ 58 | * IsRestoreInProgress?: null|bool, 59 | * RestoreExpiryDate?: null|\DateTimeImmutable, 60 | * }|RestoreStatus $input 61 | */ 62 | public static function create($input): self 63 | { 64 | return $input instanceof self ? $input : new self($input); 65 | } 66 | 67 | public function getIsRestoreInProgress(): ?bool 68 | { 69 | return $this->isRestoreInProgress; 70 | } 71 | 72 | public function getRestoreExpiryDate(): ?\DateTimeImmutable 73 | { 74 | return $this->restoreExpiryDate; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/ValueObject/S3KeyFilter.php: -------------------------------------------------------------------------------- 1 | , 18 | * } $input 19 | */ 20 | public function __construct(array $input) 21 | { 22 | $this->filterRules = isset($input['FilterRules']) ? array_map([FilterRule::class, 'create'], $input['FilterRules']) : null; 23 | } 24 | 25 | /** 26 | * @param array{ 27 | * FilterRules?: null|array, 28 | * }|S3KeyFilter $input 29 | */ 30 | public static function create($input): self 31 | { 32 | return $input instanceof self ? $input : new self($input); 33 | } 34 | 35 | /** 36 | * @return FilterRule[] 37 | */ 38 | public function getFilterRules(): array 39 | { 40 | return $this->filterRules ?? []; 41 | } 42 | 43 | /** 44 | * @internal 45 | */ 46 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 47 | { 48 | if (null !== $v = $this->filterRules) { 49 | foreach ($v as $item) { 50 | $node->appendChild($child = $document->createElement('FilterRule')); 51 | 52 | $item->requestBody($child, $document); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/ValueObject/ServerSideEncryptionByDefault.php: -------------------------------------------------------------------------------- 1 | - **General purpose buckets** - If you don't specify a customer managed key at configuration, Amazon S3 14 | * > automatically creates an Amazon Web Services KMS key (`aws/s3`) in your Amazon Web Services account the first 15 | * > time that you add an object encrypted with SSE-KMS to a bucket. By default, Amazon S3 uses this KMS key for 16 | * > SSE-KMS. 17 | * > - **Directory buckets** - Your SSE-KMS configuration can only support 1 customer managed key [^2] per directory 18 | * > bucket's lifetime. The Amazon Web Services managed key [^3] (`aws/s3`) isn't supported. 19 | * > - **Directory buckets** - For directory buckets, there are only two supported options for server-side encryption: 20 | * > SSE-S3 and SSE-KMS. 21 | * > 22 | * 23 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTencryption.html 24 | * [^2]: https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk 25 | * [^3]: https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk 26 | */ 27 | final class ServerSideEncryptionByDefault 28 | { 29 | /** 30 | * Server-side encryption algorithm to use for the default encryption. 31 | * 32 | * > For directory buckets, there are only two supported values for server-side encryption: `AES256` and `aws:kms`. 33 | * 34 | * @var ServerSideEncryption::* 35 | */ 36 | private $sseAlgorithm; 37 | 38 | /** 39 | * Amazon Web Services Key Management Service (KMS) customer managed key ID to use for the default encryption. 40 | * 41 | * > - **General purpose buckets** - This parameter is allowed if and only if `SSEAlgorithm` is set to `aws:kms` or 42 | * > `aws:kms:dsse`. 43 | * > - **Directory buckets** - This parameter is allowed if and only if `SSEAlgorithm` is set to `aws:kms`. 44 | * > 45 | * 46 | * You can specify the key ID, key alias, or the Amazon Resource Name (ARN) of the KMS key. 47 | * 48 | * - Key ID: `1234abcd-12ab-34cd-56ef-1234567890ab` 49 | * - Key ARN: `arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab` 50 | * - Key Alias: `alias/alias-name` 51 | * 52 | * If you are using encryption with cross-account or Amazon Web Services service operations, you must use a fully 53 | * qualified KMS key ARN. For more information, see Using encryption for cross-account operations [^1]. 54 | * 55 | * > - **General purpose buckets** - If you're specifying a customer managed KMS key, we recommend using a fully 56 | * > qualified KMS key ARN. If you use a KMS key alias instead, then KMS resolves the key within the requester’s 57 | * > account. This behavior can result in data that's encrypted with a KMS key that belongs to the requester, and not 58 | * > the bucket owner. Also, if you use a key ID, you can run into a LogDestination undeliverable error when creating 59 | * > a VPC flow log. 60 | * > - **Directory buckets** - When you specify an KMS customer managed key [^2] for encryption in your directory 61 | * > bucket, only use the key ID or key ARN. The key alias format of the KMS key isn't supported. 62 | * > 63 | * 64 | * ! Amazon S3 only supports symmetric encryption KMS keys. For more information, see Asymmetric keys in Amazon Web 65 | * ! Services KMS [^3] in the *Amazon Web Services Key Management Service Developer Guide*. 66 | * 67 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html#bucket-encryption-update-bucket-policy 68 | * [^2]: https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk 69 | * [^3]: https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html 70 | * 71 | * @var string|null 72 | */ 73 | private $kmsMasterKeyId; 74 | 75 | /** 76 | * @param array{ 77 | * SSEAlgorithm: ServerSideEncryption::*, 78 | * KMSMasterKeyID?: null|string, 79 | * } $input 80 | */ 81 | public function __construct(array $input) 82 | { 83 | $this->sseAlgorithm = $input['SSEAlgorithm'] ?? $this->throwException(new InvalidArgument('Missing required field "SSEAlgorithm".')); 84 | $this->kmsMasterKeyId = $input['KMSMasterKeyID'] ?? null; 85 | } 86 | 87 | /** 88 | * @param array{ 89 | * SSEAlgorithm: ServerSideEncryption::*, 90 | * KMSMasterKeyID?: null|string, 91 | * }|ServerSideEncryptionByDefault $input 92 | */ 93 | public static function create($input): self 94 | { 95 | return $input instanceof self ? $input : new self($input); 96 | } 97 | 98 | public function getKmsMasterKeyId(): ?string 99 | { 100 | return $this->kmsMasterKeyId; 101 | } 102 | 103 | /** 104 | * @return ServerSideEncryption::* 105 | */ 106 | public function getSseAlgorithm(): string 107 | { 108 | return $this->sseAlgorithm; 109 | } 110 | 111 | /** 112 | * @return never 113 | */ 114 | private function throwException(\Throwable $exception) 115 | { 116 | throw $exception; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/ValueObject/ServerSideEncryptionConfiguration.php: -------------------------------------------------------------------------------- 1 | , 22 | * } $input 23 | */ 24 | public function __construct(array $input) 25 | { 26 | $this->rules = isset($input['Rules']) ? array_map([ServerSideEncryptionRule::class, 'create'], $input['Rules']) : $this->throwException(new InvalidArgument('Missing required field "Rules".')); 27 | } 28 | 29 | /** 30 | * @param array{ 31 | * Rules: array, 32 | * }|ServerSideEncryptionConfiguration $input 33 | */ 34 | public static function create($input): self 35 | { 36 | return $input instanceof self ? $input : new self($input); 37 | } 38 | 39 | /** 40 | * @return ServerSideEncryptionRule[] 41 | */ 42 | public function getRules(): array 43 | { 44 | return $this->rules; 45 | } 46 | 47 | /** 48 | * @return never 49 | */ 50 | private function throwException(\Throwable $exception) 51 | { 52 | throw $exception; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/ValueObject/ServerSideEncryptionRule.php: -------------------------------------------------------------------------------- 1 | - **General purpose buckets** - If you're specifying a customer managed KMS key, we recommend using a fully 9 | * > qualified KMS key ARN. If you use a KMS key alias instead, then KMS resolves the key within the requester’s 10 | * > account. This behavior can result in data that's encrypted with a KMS key that belongs to the requester, and not 11 | * > the bucket owner. 12 | * > - **Directory buckets** - When you specify an KMS customer managed key [^1] for encryption in your directory 13 | * > bucket, only use the key ID or key ARN. The key alias format of the KMS key isn't supported. 14 | * > 15 | * 16 | * [^1]: https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk 17 | */ 18 | final class ServerSideEncryptionRule 19 | { 20 | /** 21 | * Specifies the default server-side encryption to apply to new objects in the bucket. If a PUT Object request doesn't 22 | * specify any server-side encryption, this default encryption will be applied. 23 | * 24 | * @var ServerSideEncryptionByDefault|null 25 | */ 26 | private $applyServerSideEncryptionByDefault; 27 | 28 | /** 29 | * Specifies whether Amazon S3 should use an S3 Bucket Key with server-side encryption using KMS (SSE-KMS) for new 30 | * objects in the bucket. Existing objects are not affected. Setting the `BucketKeyEnabled` element to `true` causes 31 | * Amazon S3 to use an S3 Bucket Key. 32 | * 33 | * > - **General purpose buckets** - By default, S3 Bucket Key is not enabled. For more information, see Amazon S3 34 | * > Bucket Keys [^1] in the *Amazon S3 User Guide*. 35 | * > - **Directory buckets** - S3 Bucket Keys are always enabled for `GET` and `PUT` operations in a directory bucket 36 | * > and can’t be disabled. S3 Bucket Keys aren't supported, when you copy SSE-KMS encrypted objects from general 37 | * > purpose buckets to directory buckets, from directory buckets to general purpose buckets, or between directory 38 | * > buckets, through CopyObject [^2], UploadPartCopy [^3], the Copy operation in Batch Operations [^4], or the import 39 | * > jobs [^5]. In this case, Amazon S3 makes a call to KMS every time a copy request is made for a KMS-encrypted 40 | * > object. 41 | * > 42 | * 43 | * [^1]: https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-key.html 44 | * [^2]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html 45 | * [^3]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html 46 | * [^4]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-objects-Batch-Ops 47 | * [^5]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-import-job 48 | * 49 | * @var bool|null 50 | */ 51 | private $bucketKeyEnabled; 52 | 53 | /** 54 | * @param array{ 55 | * ApplyServerSideEncryptionByDefault?: null|ServerSideEncryptionByDefault|array, 56 | * BucketKeyEnabled?: null|bool, 57 | * } $input 58 | */ 59 | public function __construct(array $input) 60 | { 61 | $this->applyServerSideEncryptionByDefault = isset($input['ApplyServerSideEncryptionByDefault']) ? ServerSideEncryptionByDefault::create($input['ApplyServerSideEncryptionByDefault']) : null; 62 | $this->bucketKeyEnabled = $input['BucketKeyEnabled'] ?? null; 63 | } 64 | 65 | /** 66 | * @param array{ 67 | * ApplyServerSideEncryptionByDefault?: null|ServerSideEncryptionByDefault|array, 68 | * BucketKeyEnabled?: null|bool, 69 | * }|ServerSideEncryptionRule $input 70 | */ 71 | public static function create($input): self 72 | { 73 | return $input instanceof self ? $input : new self($input); 74 | } 75 | 76 | public function getApplyServerSideEncryptionByDefault(): ?ServerSideEncryptionByDefault 77 | { 78 | return $this->applyServerSideEncryptionByDefault; 79 | } 80 | 81 | public function getBucketKeyEnabled(): ?bool 82 | { 83 | return $this->bucketKeyEnabled; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/ValueObject/Tag.php: -------------------------------------------------------------------------------- 1 | key = $input['Key'] ?? $this->throwException(new InvalidArgument('Missing required field "Key".')); 35 | $this->value = $input['Value'] ?? $this->throwException(new InvalidArgument('Missing required field "Value".')); 36 | } 37 | 38 | /** 39 | * @param array{ 40 | * Key: string, 41 | * Value: string, 42 | * }|Tag $input 43 | */ 44 | public static function create($input): self 45 | { 46 | return $input instanceof self ? $input : new self($input); 47 | } 48 | 49 | public function getKey(): string 50 | { 51 | return $this->key; 52 | } 53 | 54 | public function getValue(): string 55 | { 56 | return $this->value; 57 | } 58 | 59 | /** 60 | * @internal 61 | */ 62 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 63 | { 64 | $v = $this->key; 65 | $node->appendChild($document->createElement('Key', $v)); 66 | $v = $this->value; 67 | $node->appendChild($document->createElement('Value', $v)); 68 | } 69 | 70 | /** 71 | * @return never 72 | */ 73 | private function throwException(\Throwable $exception) 74 | { 75 | throw $exception; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/ValueObject/Tagging.php: -------------------------------------------------------------------------------- 1 | , 22 | * } $input 23 | */ 24 | public function __construct(array $input) 25 | { 26 | $this->tagSet = isset($input['TagSet']) ? array_map([Tag::class, 'create'], $input['TagSet']) : $this->throwException(new InvalidArgument('Missing required field "TagSet".')); 27 | } 28 | 29 | /** 30 | * @param array{ 31 | * TagSet: array, 32 | * }|Tagging $input 33 | */ 34 | public static function create($input): self 35 | { 36 | return $input instanceof self ? $input : new self($input); 37 | } 38 | 39 | /** 40 | * @return Tag[] 41 | */ 42 | public function getTagSet(): array 43 | { 44 | return $this->tagSet; 45 | } 46 | 47 | /** 48 | * @internal 49 | */ 50 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 51 | { 52 | $v = $this->tagSet; 53 | 54 | $node->appendChild($nodeList = $document->createElement('TagSet')); 55 | foreach ($v as $item) { 56 | $nodeList->appendChild($child = $document->createElement('Tag')); 57 | 58 | $item->requestBody($child, $document); 59 | } 60 | } 61 | 62 | /** 63 | * @return never 64 | */ 65 | private function throwException(\Throwable $exception) 66 | { 67 | throw $exception; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/ValueObject/TopicConfiguration.php: -------------------------------------------------------------------------------- 1 | 34 | */ 35 | private $events; 36 | 37 | /** 38 | * @var NotificationConfigurationFilter|null 39 | */ 40 | private $filter; 41 | 42 | /** 43 | * @param array{ 44 | * Id?: null|string, 45 | * TopicArn: string, 46 | * Events: array, 47 | * Filter?: null|NotificationConfigurationFilter|array, 48 | * } $input 49 | */ 50 | public function __construct(array $input) 51 | { 52 | $this->id = $input['Id'] ?? null; 53 | $this->topicArn = $input['TopicArn'] ?? $this->throwException(new InvalidArgument('Missing required field "TopicArn".')); 54 | $this->events = $input['Events'] ?? $this->throwException(new InvalidArgument('Missing required field "Events".')); 55 | $this->filter = isset($input['Filter']) ? NotificationConfigurationFilter::create($input['Filter']) : null; 56 | } 57 | 58 | /** 59 | * @param array{ 60 | * Id?: null|string, 61 | * TopicArn: string, 62 | * Events: array, 63 | * Filter?: null|NotificationConfigurationFilter|array, 64 | * }|TopicConfiguration $input 65 | */ 66 | public static function create($input): self 67 | { 68 | return $input instanceof self ? $input : new self($input); 69 | } 70 | 71 | /** 72 | * @return list 73 | */ 74 | public function getEvents(): array 75 | { 76 | return $this->events; 77 | } 78 | 79 | public function getFilter(): ?NotificationConfigurationFilter 80 | { 81 | return $this->filter; 82 | } 83 | 84 | public function getId(): ?string 85 | { 86 | return $this->id; 87 | } 88 | 89 | public function getTopicArn(): string 90 | { 91 | return $this->topicArn; 92 | } 93 | 94 | /** 95 | * @internal 96 | */ 97 | public function requestBody(\DOMElement $node, \DOMDocument $document): void 98 | { 99 | if (null !== $v = $this->id) { 100 | $node->appendChild($document->createElement('Id', $v)); 101 | } 102 | $v = $this->topicArn; 103 | $node->appendChild($document->createElement('Topic', $v)); 104 | $v = $this->events; 105 | foreach ($v as $item) { 106 | if (!Event::exists($item)) { 107 | throw new InvalidArgument(\sprintf('Invalid parameter "Event" for "%s". The value "%s" is not a valid "Event".', __CLASS__, $item)); 108 | } 109 | $node->appendChild($document->createElement('Event', $item)); 110 | } 111 | 112 | if (null !== $v = $this->filter) { 113 | $node->appendChild($child = $document->createElement('Filter')); 114 | 115 | $v->requestBody($child, $document); 116 | } 117 | } 118 | 119 | /** 120 | * @return never 121 | */ 122 | private function throwException(\Throwable $exception) 123 | { 124 | throw $exception; 125 | } 126 | } 127 | --------------------------------------------------------------------------------