Version Description
= 2.3 = This is a major upgrade that switches to using a custom table for storing data about offloaded Media Library items. Once upgraded you will not be able to downgrade without restoring data from a backup.
= 2.0 = This is a major upgrade that introduces support for DigitalOcean Spaces, renames the plugin to WP Offload Media Lite, and coincidentally upgrades some of its database settings. You may not be able to downgrade to WP Offload S3 Lite 1.x after upgrading to WP Offload Media Lite 2.0+.
= 1.1 = This is a major change, which ensures S3 URLs are no longer saved in post content. Instead, local URLs are filtered on page generation and replaced with the S3 version. If you depend on the S3 URLs being stored in post content you will need to make modifications to support this version.
= 0.6 = This version requires PHP 5.3.3+ and the Amazon Web Services plugin
Release Info
Developer | deliciousbrains |
Plugin | WP Offload S3 Lite |
Version | 2.4 |
Comparing to | |
See all releases |
Code changes from version 2.3.2 to 2.4
- README.md +31 -3
- assets/css/delivery-provider.css +1 -0
- assets/css/media.css +1 -1
- assets/css/styles.css +1 -1
- assets/js/delivery-provider.js +89 -0
- assets/js/delivery-provider.min.js +1 -0
- assets/js/script.js +174 -14
- assets/js/script.min.js +1 -1
- assets/sass/delivery-provider.scss +28 -0
- assets/sass/media.scss +93 -1
- assets/sass/styles.scss +209 -14
- classes/amazon-s3-and-cloudfront.php +1031 -444
- classes/as3cf-filter.php +6 -6
- classes/as3cf-notices.php +1 -2
- classes/as3cf-plugin-base.php +38 -0
- classes/as3cf-plugin-compatibility.php +20 -17
- classes/as3cf-utils.php +140 -6
- classes/filters/as3cf-local-to-s3.php +64 -29
- classes/filters/as3cf-s3-to-local.php +21 -1
- classes/items/item.php +33 -8
- classes/items/media-library-item.php +96 -27
- classes/providers/delivery/another-cdn.php +49 -0
- classes/providers/delivery/aws-cloudfront.php +112 -0
- classes/providers/delivery/cloudflare.php +62 -0
- classes/providers/delivery/delivery-provider.php +428 -0
- classes/providers/delivery/digitalocean-spaces-cdn.php +85 -0
- classes/providers/delivery/gcp-cdn.php +75 -0
- classes/providers/delivery/keycdn.php +62 -0
- classes/providers/delivery/other.php +61 -0
- classes/providers/delivery/stackpath.php +62 -0
- classes/providers/delivery/storage.php +103 -0
- classes/providers/provider.php +38 -865
- classes/providers/{aws-provider.php → storage/aws-provider.php} +178 -79
- classes/providers/{digitalocean-provider.php → storage/digitalocean-provider.php} +17 -1
- classes/providers/{gcp-provider.php → storage/gcp-provider.php} +91 -50
- classes/providers/{null-provider.php → storage/null-provider.php} +1 -1
- classes/providers/storage/storage-provider.php +958 -0
- classes/providers/{streams → storage/streams}/aws-s3-stream-wrapper.php +30 -12
- classes/providers/{streams → storage/streams}/gcp-gcs-stream-wrapper.php +1 -2
- classes/upgrades/upgrade-filter-post.php +4 -4
- classes/upgrades/upgrade-items-table.php +2 -2
- classes/upgrades/upgrade.php +25 -0
- include/functions.php +34 -10
- languages/amazon-s3-and-cloudfront-en.pot +436 -183
- readme.txt +31 -3
- vendor/Aws3/Aws/AbstractConfigurationProvider.php +133 -0
- vendor/Aws3/Aws/Api/ApiProvider.php +1 -1
- vendor/Aws3/Aws/Api/DocModel.php +1 -1
- vendor/Aws3/Aws/Api/ErrorParser/AbstractErrorParser.php +69 -0
- vendor/Aws3/Aws/Api/ErrorParser/JsonParserTrait.php +8 -0
- vendor/Aws3/Aws/Api/ErrorParser/JsonRpcErrorParser.php +12 -2
- vendor/Aws3/Aws/Api/ErrorParser/RestJsonErrorParser.php +15 -2
- vendor/Aws3/Aws/Api/ErrorParser/XmlErrorParser.php +34 -14
- vendor/Aws3/Aws/Api/Parser/AbstractRestParser.php +13 -3
- vendor/Aws3/Aws/Api/Parser/DecodingEventStreamIterator.php +1 -1
- vendor/Aws3/Aws/Api/Parser/Exception/ParserException.php +23 -0
- vendor/Aws3/Aws/Api/Parser/MetadataParserTrait.php +74 -0
- vendor/Aws3/Aws/Api/Parser/PayloadParserTrait.php +1 -1
- vendor/Aws3/Aws/Api/Parser/XmlParser.php +16 -0
- vendor/Aws3/Aws/Api/Serializer/RestJsonSerializer.php +1 -1
- vendor/Aws3/Aws/Api/Serializer/RestSerializer.php +5 -0
- vendor/Aws3/Aws/Api/Serializer/XmlBody.php +1 -1
- vendor/Aws3/Aws/Api/Service.php +20 -2
- vendor/Aws3/Aws/Api/ShapeMap.php +3 -1
- vendor/Aws3/Aws/Api/Validator.php +11 -1
- vendor/Aws3/Aws/Arn/AccessPointArn.php +67 -0
- vendor/Aws3/Aws/Arn/Arn.php +112 -0
- vendor/Aws3/Aws/Arn/ArnInterface.php +30 -0
- vendor/Aws3/Aws/Arn/ArnParser.php +39 -0
- vendor/Aws3/Aws/Arn/Exception/InvalidArnException.php +10 -0
- vendor/Aws3/Aws/Arn/ResourceTypeAndIdTrait.php +32 -0
- vendor/Aws3/Aws/Arn/S3/AccessPointArn.php +25 -0
- vendor/Aws3/Aws/AwsClient.php +63 -6
- vendor/Aws3/Aws/AwsClientTrait.php +9 -2
- vendor/Aws3/Aws/ClientResolver.php +49 -4
- vendor/Aws3/Aws/ClientSideMonitoring/AbstractMonitoringMiddleware.php +12 -3
- vendor/Aws3/Aws/ClientSideMonitoring/Configuration.php +12 -2
- vendor/Aws3/Aws/ClientSideMonitoring/ConfigurationInterface.php +7 -1
- vendor/Aws3/Aws/ClientSideMonitoring/ConfigurationProvider.php +33 -124
- vendor/Aws3/Aws/CloudFront/CloudFrontClient.php +171 -0
- vendor/Aws3/Aws/CloudFront/CookieSigner.php +57 -0
- vendor/Aws3/Aws/CloudFront/Exception/CloudFrontException.php +11 -0
- vendor/Aws3/Aws/CloudFront/Signer.php +99 -0
- vendor/Aws3/Aws/CloudFront/UrlSigner.php +95 -0
- vendor/Aws3/Aws/Command.php +3 -0
- vendor/Aws3/Aws/ConfigurationProviderInterface.php +14 -0
- vendor/Aws3/Aws/Credentials/AssumeRoleWithWebIdentityCredentialProvider.php +100 -0
- vendor/Aws3/Aws/Credentials/CredentialProvider.php +218 -35
- vendor/Aws3/Aws/Credentials/EcsCredentialProvider.php +4 -1
- vendor/Aws3/Aws/Credentials/InstanceProfileProvider.php +109 -10
- vendor/Aws3/Aws/Crypto/DecryptionTrait.php +4 -3
- vendor/Aws3/Aws/Crypto/EncryptionTrait.php +1 -1
- vendor/Aws3/Aws/Endpoint/Partition.php +43 -5
- vendor/Aws3/Aws/Endpoint/PartitionEndpointProvider.php +22 -3
- vendor/Aws3/Aws/EndpointDiscovery/Configuration.php +39 -0
- vendor/Aws3/Aws/EndpointDiscovery/ConfigurationInterface.php +29 -0
- vendor/Aws3/Aws/EndpointDiscovery/ConfigurationProvider.php +170 -0
- vendor/Aws3/Aws/EndpointDiscovery/EndpointDiscoveryMiddleware.php +240 -0
- vendor/Aws3/Aws/EndpointDiscovery/EndpointList.php +80 -0
- vendor/Aws3/Aws/EndpointDiscovery/Exception/ConfigurationException.php +13 -0
- vendor/Aws3/Aws/EndpointParameterMiddleware.php +4 -0
- vendor/Aws3/Aws/Exception/AwsException.php +19 -3
- vendor/Aws3/Aws/Exception/IncalculablePayloadException.php +10 -0
- vendor/Aws3/Aws/Exception/InvalidJsonException.php +10 -0
- vendor/Aws3/Aws/Exception/InvalidRegionException.php +10 -0
- vendor/Aws3/Aws/Handler/GuzzleV5/GuzzleHandler.php +4 -4
- vendor/Aws3/Aws/MultiRegionClient.php +2 -0
- vendor/Aws3/Aws/Multipart/AbstractUploadManager.php +21 -7
- vendor/Aws3/Aws/Psr16CacheAdapter.php +26 -0
- vendor/Aws3/Aws/ResponseContainerInterface.php +1 -0
- vendor/Aws3/Aws/RetryMiddleware.php +6 -0
- vendor/Aws3/Aws/S3/BucketEndpointArnMiddleware.php +200 -0
- vendor/Aws3/Aws/S3/MultipartCopy.php +7 -1
- vendor/Aws3/Aws/S3/MultipartUploader.php +1 -1
- vendor/Aws3/Aws/S3/ObjectCopier.php +9 -0
- vendor/Aws3/Aws/S3/ObjectUploader.php +3 -2
- vendor/Aws3/Aws/S3/PutObjectUrlMiddleware.php +1 -1
- vendor/Aws3/Aws/S3/RegionalEndpoint/Configuration.php +29 -0
- vendor/Aws3/Aws/S3/RegionalEndpoint/ConfigurationInterface.php +22 -0
- vendor/Aws3/Aws/S3/RegionalEndpoint/ConfigurationProvider.php +158 -0
- vendor/Aws3/Aws/S3/RegionalEndpoint/Exception/ConfigurationException.php +13 -0
- vendor/Aws3/Aws/S3/S3Client.php +85 -4
- vendor/Aws3/Aws/S3/S3ClientInterface.php +2 -2
- vendor/Aws3/Aws/S3/S3EndpointMiddleware.php +1 -1
- vendor/Aws3/Aws/S3/S3MultiRegionClient.php +1 -1
- vendor/Aws3/Aws/S3/S3UriParser.php +20 -1
- vendor/Aws3/Aws/S3/StreamWrapper.php +13 -6
- vendor/Aws3/Aws/S3/Transfer.php +5 -2
- vendor/Aws3/Aws/S3/UseArnRegion/Configuration.php +31 -0
- vendor/Aws3/Aws/S3/UseArnRegion/ConfigurationInterface.php +19 -0
- vendor/Aws3/Aws/S3/UseArnRegion/ConfigurationProvider.php +141 -0
- vendor/Aws3/Aws/S3/UseArnRegion/Exception/ConfigurationException.php +13 -0
- vendor/Aws3/Aws/Sdk.php +113 -1
- vendor/Aws3/Aws/Signature/AnonymousSignature.php +1 -1
- vendor/Aws3/Aws/Signature/SignatureInterface.php +1 -1
- vendor/Aws3/Aws/StreamRequestPayloadMiddleware.php +67 -0
- vendor/Aws3/Aws/WrappedHttpHandler.php +1 -1
- vendor/Aws3/Aws/data/accessanalyzer/2019-11-01/api-2.json.php +4 -0
- vendor/Aws3/Aws/data/accessanalyzer/2019-11-01/paginators-1.json.php +4 -0
- vendor/Aws3/Aws/data/acm-pca/2017-08-22/api-2.json.php +1 -1
- vendor/Aws3/Aws/data/acm-pca/2017-08-22/paginators-1.json.php +1 -1
- vendor/Aws3/Aws/data/acm-pca/2017-08-22/waiters-2.json.php +1 -1
- vendor/Aws3/Aws/data/acm/2015-12-08/api-2.json.php +1 -1
- vendor/Aws3/Aws/data/alexaforbusiness/2017-11-09/api-2.json.php +1 -1
- vendor/Aws3/Aws/data/alexaforbusiness/2017-11-09/paginators-1.json.php +1 -1
- vendor/Aws3/Aws/data/aliases.json.php +4 -0
- vendor/Aws3/Aws/data/amplify/2017-07-25/api-2.json.php +1 -1
@@ -2,9 +2,9 @@
|
|
2 |
**Contributors:** bradt, deliciousbrains, ianmjones
|
3 |
**Tags:** uploads, amazon, s3, amazon s3, digitalocean, digitalocean spaces, google cloud storage, gcs, mirror, admin, media, cdn, cloudfront
|
4 |
**Requires at least:** 4.9
|
5 |
-
**Tested up to:** 5.
|
6 |
**Requires PHP:** 5.5
|
7 |
-
**Stable tag:** 2.
|
8 |
**License:** GPLv3
|
9 |
|
10 |
Copies files to Amazon S3, DigitalOcean Spaces or Google Cloud Storage as they are uploaded to the Media Library. Optionally configure Amazon CloudFront or another CDN for faster delivery.
|
@@ -32,7 +32,7 @@ Although WP Offload Media doesn't include image optimization features, we work c
|
|
32 |
* [Assets Pull addon](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=assets%2Baddon#addons) - Serve your CSS, JS and fonts via CloudFront or another CDN
|
33 |
* [WooCommerce integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=woocommerce%2Baddon#integrations)
|
34 |
* [Easy Digital Downloads integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=edd%2Baddon#integrations)
|
35 |
-
*
|
36 |
|
37 |
[Compare pro vs free →](https://deliciousbrains.com/wp-offload-media/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
|
38 |
|
@@ -89,6 +89,34 @@ This version requires PHP 5.3.3+ and the Amazon Web Services plugin
|
|
89 |
|
90 |
## Changelog ##
|
91 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
### WP Offload Media Lite 2.3.2 - 2019-12-09 ###
|
93 |
* Improvement: Reduced database queries when external object cache available
|
94 |
* Bug fix: Uncaught Error: Call to undefined function DeliciousBrains\WP_Offload_Media\Gcp\GuzzleHttp\choose_handler()
|
2 |
**Contributors:** bradt, deliciousbrains, ianmjones
|
3 |
**Tags:** uploads, amazon, s3, amazon s3, digitalocean, digitalocean spaces, google cloud storage, gcs, mirror, admin, media, cdn, cloudfront
|
4 |
**Requires at least:** 4.9
|
5 |
+
**Tested up to:** 5.5
|
6 |
**Requires PHP:** 5.5
|
7 |
+
**Stable tag:** 2.4
|
8 |
**License:** GPLv3
|
9 |
|
10 |
Copies files to Amazon S3, DigitalOcean Spaces or Google Cloud Storage as they are uploaded to the Media Library. Optionally configure Amazon CloudFront or another CDN for faster delivery.
|
32 |
* [Assets Pull addon](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=assets%2Baddon#addons) - Serve your CSS, JS and fonts via CloudFront or another CDN
|
33 |
* [WooCommerce integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=woocommerce%2Baddon#integrations)
|
34 |
* [Easy Digital Downloads integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=edd%2Baddon#integrations)
|
35 |
+
* Priority email support
|
36 |
|
37 |
[Compare pro vs free →](https://deliciousbrains.com/wp-offload-media/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
|
38 |
|
89 |
|
90 |
## Changelog ##
|
91 |
|
92 |
+
### WP Offload Media Lite 2.4 - 2020-07-14 ###
|
93 |
+
* [Release Summary Blog Post](https://deliciousbrains.com/wp-offload-media-2-4-released/?utm_campaign=changelogs&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
|
94 |
+
* New: Setting to choose a Delivery Provider (i.e. S3, CloudFront, another CDN)
|
95 |
+
* New: Support for Block All Public Access setting on S3 buckets
|
96 |
+
* New: Raw S3 URLs use bucket in domain rather than path where possible as per changes required by AWS
|
97 |
+
* New: Raw S3 URLs use dot rather than dash between s3 and region name as per changes required by AWS
|
98 |
+
* New: Added S3 regions for Africa (Cape Town), Asia Pacific (Hong Kong), EU (Milan), EU (Stockholm), and Middle East (Bahrain)
|
99 |
+
* New: Added GCS regions for Salt Lake City, Las Vegas, Zürich, Osaka, Seoul, EUR4 (dual-region), and NAM4 (dual-region)
|
100 |
+
* Improvement: Updated AWS PHP SDK to v3.133.40
|
101 |
+
* Improvement: Updated Google Cloud Storage SDK to v1.18.0
|
102 |
+
* Improvement: S3 regions for China no longer hidden (configuration via AWS Console still required)
|
103 |
+
* Bug fix: Private images not showing in grid mode Media page overlay
|
104 |
+
* Bug fix: Public image thumbnails not showing in grid mode Media page when original is private
|
105 |
+
* Bug fix: URL rewriting sometimes fails for sites hosted on Windows
|
106 |
+
* Bug fix: URL rewrite fails for image when original upload has size in file name
|
107 |
+
* Bug fix: External URLs rewritten to local URLs when they shouldn't
|
108 |
+
* Bug fix: StreamWrappers don't work with private buckets
|
109 |
+
* Bug fix: Database error when inserting media library item and using HyperDB
|
110 |
+
* Bug fix: S3 bucket link in settings no longer goes direct to bucket contents
|
111 |
+
* Bug fix: New uploads slow with very large Media Library
|
112 |
+
* Bug fix: Migration to custom table very slow with large postmeta tables
|
113 |
+
* Bug fix: Signed GCS URLs have incorrect expires value
|
114 |
+
* Bug fix: The use-server-roles AS3CF_SETTINGS value is not properly reflected in Diagnostic Info
|
115 |
+
* Bug fix: Unknown column '2019/12/some-file-name.pdf' in 'where clause' when using managed MySQL on DigitalOcean
|
116 |
+
* Bug fix: WordPress database error Expression #1 of ORDER BY clause is not in SELECT list when using MySQL8
|
117 |
+
* Bug fix: WordPress forces HTTP in Edit Media page if site is not HTTPS, breaking remote URLs that require HTTPS
|
118 |
+
* Tested: WordPress 5.5
|
119 |
+
|
120 |
### WP Offload Media Lite 2.3.2 - 2019-12-09 ###
|
121 |
* Improvement: Reduced database queries when external object cache available
|
122 |
* Bug fix: Uncaught Error: Call to undefined function DeliciousBrains\WP_Offload_Media\Gcp\GuzzleHttp\choose_handler()
|
@@ -0,0 +1 @@
|
|
|
1 |
+
.as3cf-delivery-provider-select .as3cf-delivery-provider-select-options{margin-bottom:30px}.as3cf-delivery-provider-select .as3cf-delivery-provider-select-options .as3cf-delivery-provider-sub-option{margin-left:25px}.as3cf-delivery-provider-select .as3cf-delivery-provider-select-options .as3cf-delivery-provider-sub-option .as3cf-setting{display:none;margin-left:25px}.as3cf-delivery-provider-select .as3cf-delivery-provider-select-options .as3cf-delivery-provider-sub-option.selected .as3cf-setting{display:block}.as3cf-delivery-provider-select .as3cf-delivery-provider-select-options .as3cf-delivery-provider-sub-option-container>.as3cf-delivery-provider-sub-option{display:none}.as3cf-delivery-provider-select .as3cf-delivery-provider-select-options .as3cf-delivery-provider-sub-option-container.selected>.as3cf-delivery-provider-sub-option{display:block}
|
@@ -1 +1 @@
|
|
1 |
-
body.as3cf-pro .attachments-browser .media-toolbar-secondary{max-width:100%}.as3cfpro_remove a.local-warning{color:#a00}.as3cfpro_remove a.local-warning:hover{color:#f00;text-decoration:none;border:none}.media-modal a.local-warning{color:#bc0b0b}.media-modal a.local-warning:hover{color:red}.attachment-info .attachment-s3-details{font-weight:bold;margin-bottom:5px}
|
1 |
+
body.as3cf-pro .media-toolbar-mode-select{overflow:visible}body.as3cf-pro .attachments-browser .media-toolbar-secondary{max-width:100%}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons{margin-right:10px;position:relative;display:none !important}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons.visible{display:inline-block !important}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons .button{margin:0;text-align:left}@media screen and (max-width: 782px){body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons .button{min-height:40px}}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__action-default{width:-webkit-calc(100% - 32px);width:calc(100% - 32px);position:relative;z-index:2}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__toggle{width:32px;position:relative;border-left:1px solid rgba(255,255,255,0.2);z-index:2}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__toggle:focus{-webkit-box-shadow:none;box-shadow:none}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__toggle::after{content:'';display:inline-block;width:0;height:0;vertical-align:0.255em;border-top:0.3em solid;border-right:0.3em solid transparent;border-bottom:0;border-left:0.3em solid transparent;-webkit-transition:0.2s all ease;transition:0.2s all ease}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__toggle.opened::after{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__submenu{position:absolute;left:0;top:0;z-index:1;-webkit-transform:translateY(33px);-ms-transform:translateY(33px);transform:translateY(33px);border-radius:3px;overflow:hidden;-webkit-box-shadow:0 2px 5px 2px rgba(0,0,0,0.3);box-shadow:0 2px 5px 2px rgba(0,0,0,0.3)}@media screen and (max-width: 782px){body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__submenu{-webkit-transform:translateY(41px);-ms-transform:translateY(41px);transform:translateY(41px)}}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__action{display:block;width:100%;margin:0;border-radius:0;-moz-text-align-last:left;text-align-last:left;border:none;border-bottom:1px solid rgba(255,255,255,0.2)}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__action:last-child{border:none}body.as3cf-pro .attachments-browser .media-toolbar-secondary .offload-buttons__action:focus{-webkit-box-shadow:none;box-shadow:none}.as3cfpro_remove a.local-warning{color:#a00}.as3cfpro_remove a.local-warning:hover{color:#f00;text-decoration:none;border:none}.media-modal a.local-warning{color:#bc0b0b}.media-modal a.local-warning:hover{color:red}.attachment-info .attachment-s3-details{font-weight:bold;margin-bottom:5px}
|
@@ -1 +1 @@
|
|
1 |
-
.as3cf-content,.as3cf-updated,.as3cf-compatibility-notice{-webkit-box-sizing:border-box;box-sizing:border-box;max-width:650px}.settings_page_amazon-s3-and-cloudfront .error,.settings_page_amazon-s3-and-cloudfront .notice,.settings_page_amazon-s3-and-cloudfront .updated{-webkit-box-sizing:border-box;box-sizing:border-box;max-width:650px}.as3cf-main.wrap{position:relative}.as3cf-main.wrap>h1{float:left}.as3cf-main.wrap .as3cf-notice,.as3cf-main.wrap .as3cf-updated,.as3cf-main.wrap .as3cf-error{-webkit-box-sizing:border-box;box-sizing:border-box}.as3cf-main.wrap .as3cf-error.fatal{clear:both}.as3cf-main.wrap h2.nav-tab-wrapper{float:none;margin-bottom:15px;width:650px;margin-top:10px;padding:9px 0 0 5px}.as3cf-main.wrap h2.nav-tab-wrapper .nav-tab-container{float:right}.as3cf-main.wrap h2.nav-tab-wrapper .nav-tab-container :last-child{margin-right:5px}.as3cf-main.wrap h2.nav-tab-wrapper a.nav-tab-active{color:#464646;cursor:default}.as3cf-main.wrap h2.nav-tab-wrapper a:focus{-webkit-box-shadow:none;box-shadow:none}.as3cf-main.wrap .more-info{white-space:nowrap}.as3cf-main.wrap .error pre{background:#eaeaea;background:rgba(0,0,0,0.07);display:block;padding:10px 15px}.as3cf-main.wrap .error pre code{padding:0;background:none}.as3cf-main.wrap[data-tab="support"] .as3cf-notice,.as3cf-main.wrap[data-tab="support"] .error,.as3cf-main.wrap[data-tab="support"] .updated,.as3cf-main.wrap[data-tab="support"] .updated.show{display:none}.as3cf-main.wrap[data-tab="support"] .fatal .error,.as3cf-main.wrap[data-tab="support"] .as3cf-notice.important,.as3cf-main.wrap[data-tab="support"] .dbrains-api-down{display:block}.as3cf-main.wrap .as3cf-notice,.as3cf-main.wrap .error,.as3cf-main.wrap .updated{max-width:650px;margin-top:15px;-webkit-box-sizing:border-box;box-sizing:border-box}.as3cf-main.wrap .as3cf-updated{display:none}.as3cf-main.wrap .as3cf-updated.as3cf-notice,.as3cf-main.wrap .as3cf-updated.show{display:block}.as3cf-main.wrap .alignleft{margin-right:20px;margin-bottom:20px}.as3cf-main.wrap .spinner{min-width:20px}.as3cf-tab .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab .as3cf-main-settings .as3cf-bucket-container a.as3cf-change-provider{display:none}.as3cf-tab .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-can-write-error,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-can-write-error{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-provider-select,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-provider-select{display:block}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-bucket-container,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-media-settings,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-can-write-error,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-can-write-error{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-provider-select,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-bucket-container,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-bucket-container{display:block}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-media-settings,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket) .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket) .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket) .as3cf-main-settings .as3cf-media-settings{display:block}.as3cf-content>section{margin-bottom:20px}.as3cf-content>section+section.as3cf-access-keys{padding-top:20px;border-top:1px solid #d3d3d3}.as3cf-content>section+section.as3cf-access-keys .as3cf-section-heading{margin-top:0}.as3cf-tab{display:none;position:relative;width:650px}.as3cf-tab .as3cf-main-settings p{font-size:13px}.as3cf-tab .as3cf-main-settings p a{color:#444}.as3cf-tab .object-prefix-desc em{white-space:nowrap}.as3cf-tab .as3cf-url-preview-wrap{background:#fff;text-align:center;padding:20px 0 0;max-width:650px;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.as3cf-tab .as3cf-url-preview-wrap .as3cf-url-preview{margin-top:10px;padding:0 20px 10px;overflow-x:scroll}.as3cf-tab .as3cf-url-preview-wrap span{color:#aaa;text-transform:uppercase;font-weight:bold}.as3cf-tab .as3cf-radio-group label{display:block;margin-bottom:10px}.as3cf-tab .as3cf-radio-group label.disabled,.as3cf-tab .as3cf-radio-group label.disabled p{color:#bbb;cursor:default}.as3cf-tab .as3cf-radio-group p{padding-left:25px;color:#6b6b6b;margin:0;font-size:12px}.as3cf-tab .as3cf-radio-group p.as3cf-setting{margin-top:5px}.as3cf-tab .as3cf-switch{position:relative;display:inline-block;padding:2px;overflow:hidden;border-radius:2px;background-color:#d4d3d3;cursor:pointer}.as3cf-tab .as3cf-switch.on{background-color:#ade7b5}.as3cf-tab .as3cf-switch span{visibility:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;float:left;display:inline-block;height:100%;font-size:12px;line-height:20px;border-radius:2px;font-weight:bold;padding:4px 8px;background:#fff;color:#8d8d8d;z-index:1}.as3cf-tab .as3cf-switch span.on{color:#82d78b}.as3cf-tab .as3cf-switch span.checked{visibility:visible}.as3cf-tab .as3cf-switch.disabled{cursor:default;background:#e6e6e6}.as3cf-tab .as3cf-switch.disabled span{background:#f1f1f1;color:#d6d6d6}.as3cf-tab .as3cf-switch input[type="checkbox"]{position:absolute !important;top:0;left:0;opacity:0;filter:alpha(opacity=0);z-index:-1}.as3cf-tab .as3cf-setting.hide{display:none}.as3cf-tab div.as3cf-setting{margin-top:4px}.as3cf-tab h3{font-weight:normal;text-transform:uppercase}.as3cf-tab .form-table{margin:0}.as3cf-tab .form-table tr.as3cf-border-bottom td{border-bottom:1px solid #ddd;padding:20px 0px}.as3cf-tab .form-table tr.as3cf-setting-title td{padding-bottom:0}.as3cf-tab .form-table tr.as3cf-setting-title:first-child td{padding-top:20px}.as3cf-tab .form-table tr.configure-url:first-child td{padding-top:5px;padding-bottom:0}.as3cf-tab .form-table tr td{padding:15px 0}.as3cf-tab .form-table tr td:first-child{vertical-align:top;min-width:120px;padding-top:20px}.as3cf-tab .form-table tr td .as3cf-notice:last-child{margin-bottom:0}.as3cf-tab .form-table tr td>p:first-child{margin-top:0}.as3cf-tab .form-table h3{padding:0;margin:0}.as3cf-tab .form-table h4{margin:0}.as3cf-tab .as3cf-active-region{font-style:italic}.as3cf-tab .as3cf-view-bucket{color:#444;text-decoration:none;margin-right:10px}.as3cf-tab .as3cf-view-bucket:hover,.as3cf-tab .as3cf-view-bucket:active{color:#00a0d2}.as3cf-tab .as3cf-view-bucket:focus{-webkit-box-shadow:none;box-shadow:none}.as3cf-tab .as3cf-view-bucket .dashicons-external{margin-top:-2px}.as3cf-tab .tooltip{position:relative;z-index:2;cursor:pointer}.as3cf-tab .tooltip:before,.as3cf-tab .tooltip:after{visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0;pointer-events:none}.as3cf-tab .tooltip:before{position:absolute;bottom:150%;left:50%;margin-bottom:5px;margin-left:-250px;padding:10px;width:500px;border-radius:3px;background-color:#000;background-color:rgba(51,51,51,0.9);color:#fff;content:attr(data-tooltip);text-align:center;font-size:14px;line-height:1.3}.as3cf-tab .tooltip:after{position:absolute;bottom:150%;left:50%;margin-left:-5px;width:0;border-top:5px solid #000;border-top:5px solid rgba(51,51,51,0.9);border-right:5px solid transparent;border-left:5px solid transparent;content:" ";font-size:0;line-height:0}.as3cf-tab .tooltip:hover:before,.as3cf-tab .tooltip:hover:after{visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}.as3cf-tab .as3cf-defined-in-config{background:#ccc;color:#fff;padding:2px 5px;margin:0 0 5px 5px;float:right;white-space:nowrap}.as3cf-tab .as3cf-defined-setting{color:#bbb}.as3cf-tab .as3cf-defined-setting label{cursor:default}.as3cf-tab .as3cf-defined-setting p .more-info a{color:#bbb}.as3cf-tab .as3cf-defined-setting .as3cf-radio-group p{color:#bbb}.as3cf-tab .as3cf-defined-setting .as3cf-notice{display:none !important}.as3cf-tab p.actions{margin:20px -30px -30px;padding:20px 30px;border-top:none;overflow:hidden}.as3cf-tab p.actions .right{margin-left:15px}.as3cf-tab p.actions .right:last-of-type{margin-left:0}.as3cf-tab p.actions button{min-width:90px}#tab-media{display:block}#tab-media .as3cf-provider-setting td{padding-top:20px;padding-bottom:5px}#tab-media .as3cf-bucket-setting td{padding:5px 0}.as3cf-bucket-container h3{line-height:1.3;text-transform:none}.as3cf-bucket-container a:focus{-webkit-box-shadow:none;box-shadow:none;outline:none}.as3cf-bucket-container input[type=text]{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.as3cf-bucket-container select{-webkit-box-sizing:border-box;box-sizing:border-box;width:50%}.as3cf-bucket-container .form-table .as3cf-provider-setting h4{font-weight:inherit;margin:0}.as3cf-bucket-container .form-table .as3cf-bucket-list{margin:5px 0 0 0}.as3cf-bucket-container .form-table td{padding:5px 0}.as3cf-bucket-container .form-table td:first-child{width:100px;line-height:30px;vertical-align:top}.as3cf-bucket-container .bucket-actions{margin:15px 0;border-top:1px solid #ccc;padding-top:15px;overflow:hidden}.as3cf-bucket-container .bucket-actions button,.as3cf-bucket-container .bucket-actions .right{float:right;margin-right:0}.as3cf-bucket-container .bucket-actions span{display:inline-block;margin-right:20px;line-height:28px}.as3cf-bucket-container .as3cf-bucket-list{padding:15px;max-height:200px;overflow-x:hidden;overflow-y:auto;background-color:#fff;font-size:14px}.as3cf-bucket-container .as3cf-bucket-list li:last-of-type{margin-bottom:0}.as3cf-bucket-container .as3cf-bucket-list a{color:#444;text-decoration:none}.as3cf-bucket-container .as3cf-bucket-list a:hover{color:#0074a2}.as3cf-bucket-container .as3cf-bucket-list a.selected{font-weight:bold;color:#0074a2}.as3cf-bucket-container .as3cf-bucket-list a .dashicons{margin-right:5px}#tab-media{display:block}#tab-support{min-height:900px}#tab-support .as3cf-sidebar{top:11px}#tab-support .support-section{border-bottom:1px solid #ccc;padding-bottom:20px;margin-bottom:20px}#tab-support .support-section h3{font-size:20px}#tab-support .debug textarea{width:100%;min-height:200px;font-family:Consolas, Monaco, monospace;margin-bottom:5px}.as3cf-sidebar{position:absolute;top:9px;left:670px;width:292px}.as3cf-sidebar .block{padding:20px;border:1px solid #ccc}.as3cf-sidebar .subscribe{border-top:none}.as3cf-sidebar .subscribe h2{padding:0;margin:0;margin-bottom:0.5em;color:#666;font-size:20px;line-height:1.2em;float:none}.as3cf-sidebar .subscribe h3{font-size:16px;margin:0}.as3cf-sidebar .subscribe p{margin:0}.as3cf-sidebar .subscribe .intro{margin-bottom:1em;line-height:1.4}.as3cf-sidebar .subscribe li{line-height:1.4}.as3cf-sidebar .subscribe .links{margin-bottom:2em}.as3cf-sidebar .subscribe .links a{text-decoration:none}.as3cf-sidebar .subscribe .promise{color:#999;font-size:12px;line-height:1.4em}.as3cf-sidebar .subscribe .field{margin-bottom:0.5em}.as3cf-sidebar .subscribe .field p{margin-bottom:0.3em}.as3cf-sidebar .subscribe .field input[type=text],.as3cf-sidebar .subscribe .field input[type=email]{width:100%}.as3cf-sidebar .subscribe .field.submit-button{margin-bottom:1em}.as3cf-sidebar .credits{border-top:0}.as3cf-sidebar .credits h4{font-size:16px;margin-top:0;margin-bottom:10px}.as3cf-sidebar .credits ul{margin:0}.as3cf-sidebar .credits li{overflow:hidden}.as3cf-sidebar .credits li:last-child{margin-bottom:0}.as3cf-sidebar .credits img{float:left;margin-right:10px}.as3cf-sidebar .credits span{float:left;display:block;line-height:32px}.as3cf-sidebar .credits a{display:block;text-decoration:none;color:#444;font-size:16px;text-align:center}.as3cf-sidebar .credits a:hover{color:#888}@media screen and (max-width: 1052px){.as3cf-sidebar{position:relative;top:auto;right:auto}}.as3cf-active-provider,.as3cf-active-bucket{font-weight:bold;margin-right:10px}.as3cf-banner{margin-top:35px;width:292px;height:200px;display:block;background:#f8cfae url(../img/os3-banner.svg) left bottom/220px 220px no-repeat}.as3cf-banner:focus{-webkit-box-shadow:none;box-shadow:none}.wrap .as3cf-upgrade-details{background-color:#4e0d33;padding:10px 20px 20px 20px;color:#eee;font-size:13px;margin:0;display:block;text-decoration:none}.wrap .as3cf-upgrade-details h1{font-size:28px;color:#eee;margin:0 0 15px 0;padding:0;text-decoration:none;font-weight:200;line-height:1}.wrap .as3cf-upgrade-details p{margin:0}.wrap .as3cf-upgrade-details a{color:#eee;font-weight:bold;text-decoration:none;font-size:16px;-webkit-box-shadow:none;box-shadow:none}.wrap .as3cf-upgrade-details a:hover{color:#fff}.wrap .as3cf-upgrade-details ul{margin-top:0;margin-left:16px;list-style-type:disc}.as3cf-compatibility-notice.error{clear:both;margin:5px 20px 5px 0}.as3cf-bucket-error span.title{font-weight:bold}.as3cf-invalid-bucket-name,.as3cf-validation-error{display:block;margin-top:2px;font-size:12px;color:#a00}.as3cf-notice-toggle-content{max-height:100px;overflow-y:scroll}.as3cf-notice-toggle-content .as3cf-notice-toggle-list{margin-top:0;margin-left:0;padding-left:40px;color:#dc3232}.as3cf-need-help{background-color:white;font-size:16px;font-weight:bold;padding:1em}.as3cf-need-help a{text-decoration:none}.as3cf-settings h3{font-size:20px}.as3cf-settings p{font-size:14px}.as3cf-addons,.as3cf-tab .as3cf-compatibility-notice{max-width:cover}textarea.as3cf-access-key-constants-snippet.code{width:100%;white-space:pre;overflow:hidden;font-size:12px;padding:10px;height:53px}.as3cf-addons .as3cf-addons-list{margin:20px 0 200px;padding-top:5px}.as3cf-addons .as3cf-addon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:20px;font-size:14px}.as3cf-addons .as3cf-addon-info{min-height:100px}.as3cf-addons .as3cf-addon-links{float:right}.as3cf-addons .as3cf-addon-links span{padding:4px 6px}.as3cf-addons .as3cf-addon-icon{float:left;margin-right:20px}.as3cf-addons .as3cf-addon-details{white-space:nowrap}.as3cf-addons .as3cf-addon-title,.as3cf-addons .as3cf-addon-description{font-weight:100}.as3cf-addons .as3cf-addon+.as3cf-addon{margin-top:20px}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull{background-color:#0769ad;color:white}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .as3cf-addon-title,.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .as3cf-addon-description,.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull a{color:white}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .extra{background:white}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .extra a{color:#0769ad;text-decoration:none}
|
1 |
+
.as3cf-content,.as3cf-updated,.as3cf-compatibility-notice{-webkit-box-sizing:border-box;box-sizing:border-box;max-width:650px}.settings_page_amazon-s3-and-cloudfront .error,.settings_page_amazon-s3-and-cloudfront .notice,.settings_page_amazon-s3-and-cloudfront .updated{-webkit-box-sizing:border-box;box-sizing:border-box;max-width:650px}.as3cf-main.wrap{position:relative}.as3cf-main.wrap>h1{float:left}.as3cf-main.wrap .as3cf-notice,.as3cf-main.wrap .as3cf-updated,.as3cf-main.wrap .as3cf-error{-webkit-box-sizing:border-box;box-sizing:border-box}.as3cf-main.wrap .as3cf-error.fatal{clear:both}.as3cf-main.wrap h2.nav-tab-wrapper{float:none;margin-bottom:15px;width:650px;margin-top:10px;padding:9px 0 0 5px}.as3cf-main.wrap h2.nav-tab-wrapper .nav-tab-container{float:right}.as3cf-main.wrap h2.nav-tab-wrapper .nav-tab-container :last-child{margin-right:5px}.as3cf-main.wrap h2.nav-tab-wrapper a.nav-tab-active{color:#464646;cursor:default}.as3cf-main.wrap h2.nav-tab-wrapper a:focus{-webkit-box-shadow:none;box-shadow:none}.as3cf-main.wrap .more-info{white-space:nowrap}.as3cf-main.wrap .error pre{background:#eaeaea;background:rgba(0,0,0,0.07);display:block;padding:10px 15px}.as3cf-main.wrap .error pre code{padding:0;background:none}.as3cf-main.wrap[data-tab="support"] .as3cf-notice,.as3cf-main.wrap[data-tab="support"] .error,.as3cf-main.wrap[data-tab="support"] .updated,.as3cf-main.wrap[data-tab="support"] .updated.show{display:none}.as3cf-main.wrap[data-tab="support"] .fatal .error,.as3cf-main.wrap[data-tab="support"] .as3cf-notice.important,.as3cf-main.wrap[data-tab="support"] .dbrains-api-down{display:block}.as3cf-main.wrap .as3cf-notice,.as3cf-main.wrap .error,.as3cf-main.wrap .updated{max-width:650px;margin-top:15px;-webkit-box-sizing:border-box;box-sizing:border-box}.as3cf-main.wrap .as3cf-updated{display:none}.as3cf-main.wrap .as3cf-updated.as3cf-notice,.as3cf-main.wrap .as3cf-updated.show{display:block}.as3cf-main.wrap .alignleft{margin-right:20px;margin-bottom:20px}.as3cf-main.wrap .spinner{min-width:20px}.as3cf-tab .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab .as3cf-main-settings .as3cf-bucket-container,.as3cf-tab .as3cf-main-settings .as3cf-change-bucket-access-prompt{display:none}.as3cf-tab .as3cf-main-settings .as3cf-bucket-container h3,.as3cf-tab .as3cf-main-settings .as3cf-change-bucket-access-prompt h3{margin-bottom:-0.5em}.as3cf-tab .as3cf-main-settings a.as3cf-change-provider{display:none}.as3cf-tab .as3cf-main-settings .as3cf-delivery-provider-select{display:none}.as3cf-tab .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-can-write-error,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-can-write-error{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-provider-select,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-provider-select{display:block}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-bucket-container,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-change-bucket-access-prompt,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-change-bucket-access-prompt{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-delivery-provider-select,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-delivery-provider-select{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-main-settings .as3cf-media-settings,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-can-write-error,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-can-write-error{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-provider-select,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-bucket-container,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-bucket-container{display:block}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-change-bucket-access-prompt,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-change-bucket-access-prompt{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-delivery-provider-select,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-delivery-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-media-settings,.as3cf-tab.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access .as3cf-can-write-error{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access .as3cf-main-settings .as3cf-change-bucket-access-prompt{display:block}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access .as3cf-main-settings .as3cf-delivery-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider .as3cf-can-write-error{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider .as3cf-main-settings .as3cf-change-bucket-access-prompt{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider .as3cf-main-settings .as3cf-delivery-provider-select{display:block}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket):not(.as3cf-change-bucket-access):not(.as3cf-change-delivery-provider) .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket):not(.as3cf-change-bucket-access):not(.as3cf-change-delivery-provider) .as3cf-main-settings .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket):not(.as3cf-change-bucket-access):not(.as3cf-change-delivery-provider) .as3cf-main-settings .as3cf-change-bucket-access-prompt{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket):not(.as3cf-change-bucket-access):not(.as3cf-change-delivery-provider) .as3cf-main-settings .as3cf-delivery-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket):not(.as3cf-change-bucket-access):not(.as3cf-change-delivery-provider) .as3cf-main-settings .as3cf-media-settings{display:block}.as3cf-content>section{margin-bottom:20px}.as3cf-content>section+section.as3cf-access-keys{padding-top:20px;border-top:1px solid #d3d3d3}.as3cf-content>section+section.as3cf-access-keys .as3cf-section-heading{margin-top:0}.as3cf-tab{display:none;position:relative;width:650px}.as3cf-tab .as3cf-main-settings p{font-size:13px}.as3cf-tab .as3cf-main-settings p a{color:#444}.as3cf-tab .object-prefix-desc em{white-space:nowrap}.as3cf-tab .as3cf-url-preview-wrap{background:#fff;text-align:center;padding:20px 0 0;max-width:650px;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.as3cf-tab .as3cf-url-preview-wrap .as3cf-url-preview{margin-top:10px;padding:0 20px 10px;overflow-x:scroll}.as3cf-tab .as3cf-url-preview-wrap span{color:#aaa;text-transform:uppercase;font-weight:bold}.as3cf-tab .as3cf-radio-group label{display:block;margin-bottom:10px}.as3cf-tab .as3cf-radio-group label.disabled,.as3cf-tab .as3cf-radio-group label.disabled p{color:#bbb;cursor:default}.as3cf-tab .as3cf-radio-group p{padding-left:25px;color:#6b6b6b;margin:0;font-size:12px}.as3cf-tab .as3cf-radio-group p.as3cf-setting{margin-top:5px}.as3cf-tab .as3cf-switch{position:relative;display:inline-block;padding:2px;overflow:hidden;border-radius:2px;background-color:#d4d3d3;cursor:pointer}.as3cf-tab .as3cf-switch.on{background-color:#ade7b5}.as3cf-tab .as3cf-switch span{visibility:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;float:left;display:inline-block;height:100%;font-size:12px;line-height:20px;border-radius:2px;font-weight:bold;padding:4px 8px;background:#fff;color:#8d8d8d;z-index:1}.as3cf-tab .as3cf-switch span.on{color:#82d78b}.as3cf-tab .as3cf-switch span.checked{visibility:visible}.as3cf-tab .as3cf-switch.disabled{cursor:default;background:#e6e6e6}.as3cf-tab .as3cf-switch.disabled span{background:#f1f1f1;color:#d6d6d6}.as3cf-tab .as3cf-switch input[type="checkbox"]{position:absolute !important;top:0;left:0;opacity:0;filter:alpha(opacity=0);z-index:-1}.as3cf-tab .as3cf-setting.hide{display:none}.as3cf-tab .as3cf-setting .as3cf-sub-setting .as3cf-sub-setting-heading{padding-top:15px}.as3cf-tab .as3cf-setting .as3cf-sub-setting .as3cf-defined-in-config{margin-top:15px}.as3cf-tab div.as3cf-setting{margin-top:4px}.as3cf-tab h3{font-weight:normal;text-transform:uppercase}.as3cf-tab .form-table{margin:0}.as3cf-tab .form-table tr.as3cf-border-bottom td{border-bottom:1px solid #ddd;padding:20px 0px}.as3cf-tab .form-table tr.as3cf-setting-title td{padding-bottom:0}.as3cf-tab .form-table tr.as3cf-setting-title:first-child td{padding-top:20px}.as3cf-tab .form-table tr.configure-url:first-child td{padding-top:5px;padding-bottom:0}.as3cf-tab .form-table tr.hide{display:none}.as3cf-tab .form-table tr td{padding:15px 0}.as3cf-tab .form-table tr td:first-child{vertical-align:top;min-width:120px;padding-top:20px}.as3cf-tab .form-table tr td .as3cf-notice:last-child{margin-bottom:0}.as3cf-tab .form-table tr td>p:first-child{margin-top:0}.as3cf-tab .form-table h3{padding:0;margin:0}.as3cf-tab .form-table h4{margin:0}.as3cf-tab .as3cf-active-region{font-style:italic}.as3cf-tab .as3cf-view-bucket{color:#444;text-decoration:none;margin-right:10px}.as3cf-tab .as3cf-view-bucket:hover,.as3cf-tab .as3cf-view-bucket:active{color:#00a0d2}.as3cf-tab .as3cf-view-bucket:focus{-webkit-box-shadow:none;box-shadow:none}.as3cf-tab .as3cf-view-bucket .dashicons-external{margin-top:-2px}.as3cf-tab .tooltip{position:relative;z-index:2;cursor:pointer}.as3cf-tab .tooltip:before,.as3cf-tab .tooltip:after{visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0;pointer-events:none}.as3cf-tab .tooltip:before{position:absolute;bottom:150%;left:50%;margin-bottom:5px;margin-left:-250px;padding:10px;width:500px;border-radius:3px;background-color:#000;background-color:rgba(51,51,51,0.9);color:#fff;content:attr(data-tooltip);text-align:center;font-size:14px;line-height:1.3}.as3cf-tab .tooltip:after{position:absolute;bottom:150%;left:50%;margin-left:-5px;width:0;border-top:5px solid #000;border-top:5px solid rgba(51,51,51,0.9);border-right:5px solid transparent;border-left:5px solid transparent;content:" ";font-size:0;line-height:0}.as3cf-tab .tooltip:hover:before,.as3cf-tab .tooltip:hover:after{visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}.as3cf-tab .as3cf-defined-in-config{background:#ccc;color:#fff;padding:2px 5px;margin:0 0 3px 5px;float:right;white-space:nowrap;clear:right}.as3cf-tab .as3cf-defined-setting,.as3cf-tab .as3cf-locked-setting{color:#bbb}.as3cf-tab .as3cf-defined-setting label,.as3cf-tab .as3cf-locked-setting label{cursor:default}.as3cf-tab .as3cf-defined-setting p .more-info a,.as3cf-tab .as3cf-locked-setting p .more-info a{color:#bbb}.as3cf-tab .as3cf-defined-setting .as3cf-radio-group p,.as3cf-tab .as3cf-locked-setting .as3cf-radio-group p{color:#bbb}.as3cf-tab .as3cf-defined-setting .as3cf-notice,.as3cf-tab .as3cf-locked-setting .as3cf-notice{display:none !important}.as3cf-tab p.actions{margin:30px 0;border-top:1px solid #ccc;padding-top:15px;overflow:hidden}.as3cf-tab p.actions button,.as3cf-tab p.actions .right{float:right;margin-left:15px;margin-right:0;min-width:90px}.as3cf-tab p.actions button:last-of-type,.as3cf-tab p.actions .right:last-of-type{margin-left:0}.as3cf-tab p.actions span{display:inline-block;margin-right:20px;line-height:28px}.as3cf-tab .locked .as3cf-radio-group label,.as3cf-tab .locked .as3cf-radio-group label p{color:#bbb;cursor:default}.as3cf-tab .locked .as3cf-switch{cursor:default;background:#e6e6e6}.as3cf-tab .locked .as3cf-switch span{background:#f1f1f1;color:#d6d6d6}#tab-media{display:block}#tab-media .as3cf-provider-setting td{padding-top:20px;padding-bottom:5px}#tab-media .as3cf-bucket-setting td{padding:5px 0}.as3cf-bucket-container h3{line-height:1.3;text-transform:none}.as3cf-bucket-container a:focus{-webkit-box-shadow:none;box-shadow:none;outline:none}.as3cf-bucket-container input[type=text]{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.as3cf-bucket-container select{-webkit-box-sizing:border-box;box-sizing:border-box;width:50%}.as3cf-bucket-container .form-table .as3cf-provider-setting h4{font-weight:inherit;margin:0}.as3cf-bucket-container .form-table .as3cf-bucket-list{margin:5px 0 0 0}.as3cf-bucket-container .form-table td{padding:5px 0}.as3cf-bucket-container .form-table td:first-child{width:100px;line-height:30px;vertical-align:top}.as3cf-bucket-container .form-table td .as3cf-defined-in-config{margin-top:-1.75em}.as3cf-bucket-container .as3cf-bucket-list{padding:15px;max-height:200px;overflow-x:hidden;overflow-y:auto;background-color:#fff;font-size:14px}.as3cf-bucket-container .as3cf-bucket-list li:last-of-type{margin-bottom:0}.as3cf-bucket-container .as3cf-bucket-list a{color:#444;text-decoration:none}.as3cf-bucket-container .as3cf-bucket-list a:hover{color:#0074a2}.as3cf-bucket-container .as3cf-bucket-list a.selected{font-weight:bold;color:#0074a2}.as3cf-bucket-container .as3cf-bucket-list a .dashicons{margin-right:5px}.as3cf-change-bucket-access-prompt h3{line-height:1.3;text-transform:none}.as3cf-change-bucket-access-prompt .as3cf-radio-group{margin-bottom:25px}.as3cf-change-bucket-access-prompt .note{color:#999}.as3cf-delivery-provider-select h3{line-height:1.3;text-transform:none}.as3cf-delivery-provider-select .note{color:#999}#tab-media{display:block}#tab-support{min-height:900px}#tab-support .as3cf-sidebar{top:11px}#tab-support .support-section{border-bottom:1px solid #ccc;padding-bottom:20px;margin-bottom:20px}#tab-support .support-section h3{font-size:20px}#tab-support .debug textarea{width:100%;min-height:200px;font-family:Consolas, Monaco, monospace;margin-bottom:5px}.as3cf-sidebar{position:absolute;top:9px;left:670px;width:292px}.as3cf-sidebar .block{padding:20px;border:1px solid #ccc}.as3cf-sidebar .subscribe{border-top:none}.as3cf-sidebar .subscribe h2{padding:0;margin:0;margin-bottom:0.5em;color:#666;font-size:20px;line-height:1.2em;float:none}.as3cf-sidebar .subscribe h3{font-size:16px;margin:0}.as3cf-sidebar .subscribe p{margin:0}.as3cf-sidebar .subscribe .intro{margin-bottom:1em;line-height:1.4}.as3cf-sidebar .subscribe li{line-height:1.4}.as3cf-sidebar .subscribe .links{margin-bottom:2em}.as3cf-sidebar .subscribe .links a{text-decoration:none}.as3cf-sidebar .subscribe .promise{color:#999;font-size:12px;line-height:1.4em}.as3cf-sidebar .subscribe .field{margin-bottom:0.5em}.as3cf-sidebar .subscribe .field p{margin-bottom:0.3em}.as3cf-sidebar .subscribe .field input[type=text],.as3cf-sidebar .subscribe .field input[type=email]{width:100%}.as3cf-sidebar .subscribe .field.submit-button{margin-bottom:1em}.as3cf-sidebar .credits{border-top:0}.as3cf-sidebar .credits h4{font-size:16px;margin-top:0;margin-bottom:10px}.as3cf-sidebar .credits ul{margin:0}.as3cf-sidebar .credits li{overflow:hidden}.as3cf-sidebar .credits li:last-child{margin-bottom:0}.as3cf-sidebar .credits img{float:left;margin-right:10px}.as3cf-sidebar .credits span{float:left;display:block;line-height:32px}.as3cf-sidebar .credits a{display:block;text-decoration:none;color:#444;font-size:16px;text-align:center}.as3cf-sidebar .credits a:hover{color:#888}@media screen and (max-width: 1052px){.as3cf-sidebar{position:relative;top:auto;right:auto}}.as3cf-active-provider,.as3cf-active-bucket{font-weight:bold;margin-right:10px}.as3cf-banner{margin-top:35px;width:292px;height:200px;display:block;background:#f8cfae url(../img/os3-banner.svg) left bottom/220px 220px no-repeat}.as3cf-banner:focus{-webkit-box-shadow:none;box-shadow:none}.wrap .as3cf-upgrade-details{background-color:#4e0d33;padding:10px 20px 20px 20px;color:#eee;font-size:13px;margin:0;display:block;text-decoration:none}.wrap .as3cf-upgrade-details h1{font-size:28px;color:#eee;margin:0 0 15px 0;padding:0;text-decoration:none;font-weight:200;line-height:1}.wrap .as3cf-upgrade-details p{margin:0}.wrap .as3cf-upgrade-details a{color:#eee;font-weight:bold;text-decoration:none;font-size:16px;-webkit-box-shadow:none;box-shadow:none}.wrap .as3cf-upgrade-details a:hover{color:#fff}.wrap .as3cf-upgrade-details ul{margin-top:0;margin-left:16px;list-style-type:disc}.as3cf-compatibility-notice.error{clear:both;margin:5px 20px 5px 0}.as3cf-bucket-error span.title{font-weight:bold}.as3cf-invalid-bucket-name,.as3cf-validation-error{display:block;margin-top:2px;font-size:12px;color:#a00}.as3cf-notice-toggle-content{max-height:100px;overflow-y:scroll}.as3cf-notice-toggle-content .as3cf-notice-toggle-list{margin-top:0;margin-left:0;padding-left:40px;color:#dc3232}.as3cf-need-help{background-color:white;font-size:16px;font-weight:bold;padding:1em}.as3cf-need-help a{text-decoration:none}.as3cf-settings h3{font-size:20px}.as3cf-settings p{font-size:14px}.as3cf-addons,.as3cf-tab .as3cf-compatibility-notice{max-width:cover}textarea.as3cf-access-key-constants-snippet.code{width:100%;white-space:pre;overflow:hidden;font-size:12px;padding:10px;height:53px}.as3cf-addons .as3cf-addons-list{margin:20px 0 200px;padding-top:5px}.as3cf-addons .as3cf-addon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:20px;font-size:14px}.as3cf-addons .as3cf-addon-info{min-height:100px}.as3cf-addons .as3cf-addon-links{float:right}.as3cf-addons .as3cf-addon-links span{padding:4px 6px}.as3cf-addons .as3cf-addon-icon{float:left;margin-right:20px}.as3cf-addons .as3cf-addon-details{white-space:nowrap}.as3cf-addons .as3cf-addon-title,.as3cf-addons .as3cf-addon-description{font-weight:100}.as3cf-addons .as3cf-addon+.as3cf-addon{margin-top:20px}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull{background-color:#0769ad;color:white}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .as3cf-addon-title,.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .as3cf-addon-description,.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull a{color:white}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .extra{background:white}.as3cf-addons .as3cf-addon.amazon-s3-and-cloudfront-assets-pull .extra a{color:#0769ad;text-decoration:none}
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
(function( $ ) {
|
2 |
+
var $body = $( 'body' );
|
3 |
+
|
4 |
+
var as3cf = as3cf || {};
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Handle changes to the selected Delivery Provider.
|
8 |
+
*/
|
9 |
+
as3cf.deliveryProvider = {
|
10 |
+
changed: function() {
|
11 |
+
var provider = $( 'input[name="delivery-provider"]:checked' ).val();
|
12 |
+
var parent = $( 'input[name="delivery-provider"]:checked' ).attr( 'data-delivery-provider-parent' );
|
13 |
+
|
14 |
+
// De-select all providers.
|
15 |
+
$( '.as3cf-delivery-provider' ).each( function() {
|
16 |
+
$( this ).removeClass( 'selected' );
|
17 |
+
} );
|
18 |
+
|
19 |
+
// De-select all sub option containers.
|
20 |
+
$( '.as3cf-delivery-provider-sub-option-container' ).each( function() {
|
21 |
+
$( this ).removeClass( 'selected' );
|
22 |
+
} );
|
23 |
+
|
24 |
+
// Select chosen provider.
|
25 |
+
$( '.as3cf-delivery-provider[data-delivery-provider="' + provider + '"]' ).each( function() {
|
26 |
+
$( this ).addClass( 'selected' );
|
27 |
+
} );
|
28 |
+
|
29 |
+
if ( 0 < parent.length ) {
|
30 |
+
// If switching sub options, re-select container and parent too.
|
31 |
+
$( '.as3cf-delivery-provider-sub-option-container[data-delivery-provider="' + parent + '"]' ).each( function() {
|
32 |
+
$( this ).addClass( 'selected' );
|
33 |
+
} );
|
34 |
+
$( '.as3cf-delivery-provider[data-delivery-provider="' + parent + '"]' ).each( function() {
|
35 |
+
$( this ).addClass( 'selected' );
|
36 |
+
} );
|
37 |
+
} else {
|
38 |
+
// Switching top level provider, de-select any sub option container...
|
39 |
+
$( '.as3cf-delivery-provider-sub-option-container' ).each( function() {
|
40 |
+
$( this ).removeClass( 'selected' );
|
41 |
+
} );
|
42 |
+
|
43 |
+
// ... and select the dummy hidden radio button.
|
44 |
+
$( 'input#as3cf-delivery-provider-dummy-parent[name="delivery-provider-sub-option-parent"]' ).each( function() {
|
45 |
+
$( this ).prop( 'checked', true );
|
46 |
+
$( this ).trigger( 'change' );
|
47 |
+
} );
|
48 |
+
}
|
49 |
+
},
|
50 |
+
|
51 |
+
subOptionParentChanged: function() {
|
52 |
+
var parent = $( 'input[name="delivery-provider-sub-option-parent"]:checked' ).val();
|
53 |
+
|
54 |
+
// De-select all other top level options.
|
55 |
+
$( '.as3cf-delivery-provider-option' ).each( function() {
|
56 |
+
$( this ).removeClass( 'selected' );
|
57 |
+
} );
|
58 |
+
|
59 |
+
// Select chosen sub option container.
|
60 |
+
$( '.as3cf-delivery-provider-sub-option-container[data-delivery-provider="' + parent + '"]' ).each( function() {
|
61 |
+
$( this ).addClass( 'selected' );
|
62 |
+
} );
|
63 |
+
|
64 |
+
// Select chosen sub option parent.
|
65 |
+
$( '.as3cf-delivery-provider-option[data-delivery-provider="' + parent + '"]' ).each( function() {
|
66 |
+
$( this ).addClass( 'selected' );
|
67 |
+
} );
|
68 |
+
|
69 |
+
// Find default sub option to select.
|
70 |
+
$( 'input[data-delivery-provider-parent="' + parent + '"]' ).first().each( function() {
|
71 |
+
$( this ).prop( 'checked', true );
|
72 |
+
$( this ).trigger( 'change' );
|
73 |
+
} );
|
74 |
+
}
|
75 |
+
};
|
76 |
+
|
77 |
+
$( document ).ready( function() {
|
78 |
+
// Switch displayed delivery provider content.
|
79 |
+
$body.on( 'change', 'input[name="delivery-provider"]', function( e ) {
|
80 |
+
e.preventDefault();
|
81 |
+
as3cf.deliveryProvider.changed();
|
82 |
+
} );
|
83 |
+
$body.on( 'change', 'input[name="delivery-provider-sub-option-parent"]', function( e ) {
|
84 |
+
e.preventDefault();
|
85 |
+
as3cf.deliveryProvider.subOptionParentChanged();
|
86 |
+
} );
|
87 |
+
} );
|
88 |
+
|
89 |
+
})( jQuery );
|
@@ -0,0 +1 @@
|
|
|
1 |
+
!function(a){var b=a("body"),c=c||{};c.deliveryProvider={changed:function(){var b=a('input[name="delivery-provider"]:checked').val(),c=a('input[name="delivery-provider"]:checked').attr("data-delivery-provider-parent");a(".as3cf-delivery-provider").each(function(){a(this).removeClass("selected")}),a(".as3cf-delivery-provider-sub-option-container").each(function(){a(this).removeClass("selected")}),a('.as3cf-delivery-provider[data-delivery-provider="'+b+'"]').each(function(){a(this).addClass("selected")}),0<c.length?(a('.as3cf-delivery-provider-sub-option-container[data-delivery-provider="'+c+'"]').each(function(){a(this).addClass("selected")}),a('.as3cf-delivery-provider[data-delivery-provider="'+c+'"]').each(function(){a(this).addClass("selected")})):(a(".as3cf-delivery-provider-sub-option-container").each(function(){a(this).removeClass("selected")}),a('input#as3cf-delivery-provider-dummy-parent[name="delivery-provider-sub-option-parent"]').each(function(){a(this).prop("checked",!0),a(this).trigger("change")}))},subOptionParentChanged:function(){var b=a('input[name="delivery-provider-sub-option-parent"]:checked').val();a(".as3cf-delivery-provider-option").each(function(){a(this).removeClass("selected")}),a('.as3cf-delivery-provider-sub-option-container[data-delivery-provider="'+b+'"]').each(function(){a(this).addClass("selected")}),a('.as3cf-delivery-provider-option[data-delivery-provider="'+b+'"]').each(function(){a(this).addClass("selected")}),a('input[data-delivery-provider-parent="'+b+'"]').first().each(function(){a(this).prop("checked",!0),a(this).trigger("change")})}},a(document).ready(function(){b.on("change",'input[name="delivery-provider"]',function(a){a.preventDefault(),c.deliveryProvider.changed()}),b.on("change",'input[name="delivery-provider-sub-option-parent"]',function(a){a.preventDefault(),c.deliveryProvider.subOptionParentChanged()})})}(jQuery);
|
@@ -53,6 +53,63 @@
|
|
53 |
}
|
54 |
}
|
55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
as3cf.tabs = {
|
57 |
defaultTab: 'media',
|
58 |
/**
|
@@ -376,6 +433,40 @@
|
|
376 |
$( document ).trigger( 'wp-updates-notice-added' ); // Hack to run WP Core's makeNoticesDismissible() function.
|
377 |
};
|
378 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
379 |
/**
|
380 |
* Get the link to the bucket on the AWS Console and update the DOM
|
381 |
*
|
@@ -538,7 +629,7 @@
|
|
538 |
} );
|
539 |
|
540 |
$( '.as3cf-switch' ).on( 'click', function( e ) {
|
541 |
-
if ( ! $( this ).hasClass( 'disabled' ) ) {
|
542 |
setCheckbox( $( this ).attr( 'id' ) );
|
543 |
}
|
544 |
} );
|
@@ -548,14 +639,6 @@
|
|
548 |
$( '.as3cf-setting.' + setting ).toggleClass( 'hide' );
|
549 |
} );
|
550 |
|
551 |
-
$( '.as3cf-domain' ).on( 'change', 'input[type="radio"]', function( e ) {
|
552 |
-
var $selected = $( this ).closest( 'input:radio[name="domain"]:checked' );
|
553 |
-
var domain = $selected.val();
|
554 |
-
var $cloudfront = $( this ).parents( '.as3cf-domain' ).find( '.as3cf-setting.cloudfront' );
|
555 |
-
var cloudfrontSelected = ( 'cloudfront' === domain );
|
556 |
-
$cloudfront.toggleClass( 'hide', ! cloudfrontSelected );
|
557 |
-
} );
|
558 |
-
|
559 |
$( '.url-preview' ).on( 'change', 'input', function( e ) {
|
560 |
generateUrlPreview();
|
561 |
} );
|
@@ -579,20 +662,87 @@
|
|
579 |
}
|
580 |
} );
|
581 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
582 |
// Validate custom domain
|
583 |
-
$( 'input[name="
|
584 |
validateCustomDomain( $( this ) );
|
585 |
} );
|
586 |
|
587 |
-
//
|
588 |
-
$( '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
589 |
var $input = $( this );
|
590 |
var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
|
591 |
|
592 |
-
if ( '
|
593 |
$submit.prop( 'disabled', false );
|
594 |
} else {
|
595 |
-
|
596 |
}
|
597 |
} );
|
598 |
|
@@ -663,6 +813,16 @@
|
|
663 |
return false;
|
664 |
}
|
665 |
} );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
666 |
} );
|
667 |
|
668 |
} )( jQuery, as3cfModal );
|
53 |
}
|
54 |
}
|
55 |
|
56 |
+
/**
|
57 |
+
* Validate Signed URLs Key ID.
|
58 |
+
*
|
59 |
+
* @param {object} $input
|
60 |
+
*/
|
61 |
+
function validateSignedUrlsKeyID( $input ) {
|
62 |
+
var $error = $input.next( '.as3cf-validation-error' );
|
63 |
+
var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
|
64 |
+
var pattern = /[^a-zA-Z0-9]/; // Letters & Numbers only at present (CloudFront).
|
65 |
+
|
66 |
+
if ( pattern.test( $input.val() ) ) {
|
67 |
+
$error.show();
|
68 |
+
$submit.prop( 'disabled', true );
|
69 |
+
} else {
|
70 |
+
$error.hide();
|
71 |
+
$submit.prop( 'disabled', false );
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Validate Signed URLs Key File Path.
|
77 |
+
*
|
78 |
+
* @param {object} $input
|
79 |
+
*/
|
80 |
+
function validateSignedUrlsKeyFilePath( $input ) {
|
81 |
+
var $error = $input.next( '.as3cf-validation-error' );
|
82 |
+
var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
|
83 |
+
var pattern = /[^a-zA-Z0-9\.\-\\:\/ ]/;
|
84 |
+
|
85 |
+
if ( pattern.test( $input.val() ) ) {
|
86 |
+
$error.show();
|
87 |
+
$submit.prop( 'disabled', true );
|
88 |
+
} else {
|
89 |
+
$error.hide();
|
90 |
+
$submit.prop( 'disabled', false );
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Validate Signed URLs Object Prefix.
|
96 |
+
*
|
97 |
+
* @param {object} $input
|
98 |
+
*/
|
99 |
+
function validateSignedUrlsObjectPrefix( $input ) {
|
100 |
+
var $error = $input.next( '.as3cf-validation-error' );
|
101 |
+
var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
|
102 |
+
var pattern = /[^a-zA-Z0-9\-\/ ]/;
|
103 |
+
|
104 |
+
if ( pattern.test( $input.val() ) ) {
|
105 |
+
$error.show();
|
106 |
+
$submit.prop( 'disabled', true );
|
107 |
+
} else {
|
108 |
+
$error.hide();
|
109 |
+
$submit.prop( 'disabled', false );
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
as3cf.tabs = {
|
114 |
defaultTab: 'media',
|
115 |
/**
|
433 |
$( document ).trigger( 'wp-updates-notice-added' ); // Hack to run WP Core's makeNoticesDismissible() function.
|
434 |
};
|
435 |
|
436 |
+
as3cf.Settings = as3cf.Settings ? as3cf.Settings : {};
|
437 |
+
|
438 |
+
/**
|
439 |
+
* The object that handles locking and unlocking the Media settings.
|
440 |
+
*/
|
441 |
+
as3cf.Settings.Media = {
|
442 |
+
/**
|
443 |
+
* Lock settings.
|
444 |
+
*/
|
445 |
+
lock: function( key ) {
|
446 |
+
$( '#as3cf-media-settings-locked-' + key ).show();
|
447 |
+
$( '.as3cf-media-settings' ).addClass( 'locked locked-' + key );
|
448 |
+
$( '.as3cf-media-settings.locked-' + key ).each( function() {
|
449 |
+
$( this ).find( 'input,button' ).prop( 'disabled', true );
|
450 |
+
$( this ).find( '.as3cf-settings-container' ).addClass( 'as3cf-locked-setting' );
|
451 |
+
$( this ).find( 'a.as3cf-change-settings' ).hide();
|
452 |
+
} );
|
453 |
+
},
|
454 |
+
|
455 |
+
/**
|
456 |
+
* Unlock settings.
|
457 |
+
*/
|
458 |
+
unlock: function( key ) {
|
459 |
+
$( '.as3cf-media-settings.locked-' + key ).each( function() {
|
460 |
+
$( this ).find( 'input,button' ).filter( ':not(.disabled)' ).prop( 'disabled', false );
|
461 |
+
$( this ).find( '.as3cf-settings-container' ).removeClass( 'as3cf-locked-setting' );
|
462 |
+
$( this ).find( 'a.as3cf-change-settings' ).show();
|
463 |
+
$( this ).removeClass( 'locked locked-' + key );
|
464 |
+
} );
|
465 |
+
$( '#as3cf-media-settings-locked-' + key ).hide();
|
466 |
+
}
|
467 |
+
|
468 |
+
};
|
469 |
+
|
470 |
/**
|
471 |
* Get the link to the bucket on the AWS Console and update the DOM
|
472 |
*
|
629 |
} );
|
630 |
|
631 |
$( '.as3cf-switch' ).on( 'click', function( e ) {
|
632 |
+
if ( ! $( this ).hasClass( 'disabled' ) && ! $( this ).parents().hasClass( 'locked' ) ) {
|
633 |
setCheckbox( $( this ).attr( 'id' ) );
|
634 |
}
|
635 |
} );
|
639 |
$( '.as3cf-setting.' + setting ).toggleClass( 'hide' );
|
640 |
} );
|
641 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
642 |
$( '.url-preview' ).on( 'change', 'input', function( e ) {
|
643 |
generateUrlPreview();
|
644 |
} );
|
662 |
}
|
663 |
} );
|
664 |
|
665 |
+
// Show or hide Custom Domain input and Enable Signed URLs section based on custom domain toggle switch.
|
666 |
+
$( '.as3cf-enable-delivery-domain-container' ).on( 'change', 'input[type="checkbox"]', function( e ) {
|
667 |
+
var deliveryDomainEnabled = $( this ).is( ':checked' );
|
668 |
+
var $deliveryDomain = $( this ).parents( '.as3cf-enable-delivery-domain-container' ).find( '.as3cf-setting.as3cf-delivery-domain' );
|
669 |
+
$deliveryDomain.toggleClass( 'hide', ! deliveryDomainEnabled );
|
670 |
+
var $signedUrlsEnabled = $( this ).parents( '.as3cf-enable-delivery-domain-container' ).siblings( '.as3cf-enable-signed-urls-container' );
|
671 |
+
$signedUrlsEnabled.toggleClass( 'hide', ! deliveryDomainEnabled );
|
672 |
+
} );
|
673 |
+
|
674 |
+
// Re-enable submit button on domain change
|
675 |
+
$( 'input[name="enable-delivery-domain"]' ).on( 'change', function( e ) {
|
676 |
+
var $input = $( this );
|
677 |
+
var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
|
678 |
+
|
679 |
+
if ( '1' !== $input.val() ) {
|
680 |
+
$submit.prop( 'disabled', false );
|
681 |
+
} else {
|
682 |
+
validateCustomDomain( $input.next( '.as3cf-setting' ).find( 'input[name="delivery-domain"]' ) );
|
683 |
+
}
|
684 |
+
} );
|
685 |
+
|
686 |
// Validate custom domain
|
687 |
+
$( 'input[name="delivery-domain"]' ).on( 'keyup', function( e ) {
|
688 |
validateCustomDomain( $( this ) );
|
689 |
} );
|
690 |
|
691 |
+
// Show or hide Signed URLs fields based on Enable Signed URLs toggle switch.
|
692 |
+
$( '.as3cf-enable-signed-urls-container' ).on( 'change', 'input[type="checkbox"]', function( e ) {
|
693 |
+
var signedUrlsEnabled = $( this ).is( ':checked' );
|
694 |
+
var $signedUrls = $( this ).parents( '.as3cf-enable-signed-urls-container' ).find( '.as3cf-setting.as3cf-signed-urls' );
|
695 |
+
$signedUrls.toggleClass( 'hide', ! signedUrlsEnabled );
|
696 |
+
} );
|
697 |
+
|
698 |
+
// Validate Signed URLs Key ID.
|
699 |
+
$( 'input[name="signed-urls-key-id"]' ).on( 'keyup', function( e ) {
|
700 |
+
validateSignedUrlsKeyID( $( this ) );
|
701 |
+
} );
|
702 |
+
|
703 |
+
// Re-enable submit button on Signed URLs Key ID change
|
704 |
+
$( 'input[name="enable-signed-urls-key-id"]' ).on( 'change', function( e ) {
|
705 |
+
var $input = $( this );
|
706 |
+
var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
|
707 |
+
|
708 |
+
if ( '1' !== $input.val() ) {
|
709 |
+
$submit.prop( 'disabled', false );
|
710 |
+
} else {
|
711 |
+
validateSignedUrlsKeyID( $input.next( '.as3cf-setting' ).find( 'input[name="signed-urls-key-id"]' ) );
|
712 |
+
}
|
713 |
+
} );
|
714 |
+
|
715 |
+
// Validate Signed URLs Key File Path.
|
716 |
+
$( 'input[name="signed-urls-key-file-path"]' ).on( 'keyup', function( e ) {
|
717 |
+
validateSignedUrlsKeyFilePath( $( this ) );
|
718 |
+
} );
|
719 |
+
|
720 |
+
// Re-enable submit button on Signed URLs Key File Path change
|
721 |
+
$( 'input[name="enable-signed-urls-key-file-path"]' ).on( 'change', function( e ) {
|
722 |
+
var $input = $( this );
|
723 |
+
var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
|
724 |
+
|
725 |
+
if ( '1' !== $input.val() ) {
|
726 |
+
$submit.prop( 'disabled', false );
|
727 |
+
} else {
|
728 |
+
validateSignedUrlsKeyFilePath( $input.next( '.as3cf-setting' ).find( 'input[name="signed-urls-key-file-path"]' ) );
|
729 |
+
}
|
730 |
+
} );
|
731 |
+
|
732 |
+
// Validate Signed URLs Object Prefix.
|
733 |
+
$( 'input[name="signed-urls-object-prefix"]' ).on( 'keyup', function( e ) {
|
734 |
+
validateSignedUrlsObjectPrefix( $( this ) );
|
735 |
+
} );
|
736 |
+
|
737 |
+
// Re-enable submit button on Signed URLs Object Prefix change
|
738 |
+
$( 'input[name="enable-signed-urls-object-prefix"]' ).on( 'change', function( e ) {
|
739 |
var $input = $( this );
|
740 |
var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
|
741 |
|
742 |
+
if ( '1' !== $input.val() ) {
|
743 |
$submit.prop( 'disabled', false );
|
744 |
} else {
|
745 |
+
validateSignedUrlsObjectPrefix( $input.next( '.as3cf-setting' ).find( 'input[name="signed-urls-object-prefix"]' ) );
|
746 |
}
|
747 |
} );
|
748 |
|
813 |
return false;
|
814 |
}
|
815 |
} );
|
816 |
+
|
817 |
+
// Enable/Disable Block All Public Access button during setup depending on checkbox.
|
818 |
+
$( '.as3cf-change-bucket-access-prompt' ).on( 'change', '#origin-access-identity-confirmation', function( e ) {
|
819 |
+
$( '#block-public-access-confirmed' ).prop( 'disabled', ! $( this ).prop( 'checked' ) );
|
820 |
+
} );
|
821 |
+
|
822 |
+
// If there's an upgrade in progress when the page loads, ensure settings are locked.
|
823 |
+
$( '.as3cf-media-settings.locked.locked-upgrade' ).each( function() {
|
824 |
+
as3cf.Settings.Media.lock( 'upgrade' );
|
825 |
+
} );
|
826 |
} );
|
827 |
|
828 |
} )( jQuery, as3cfModal );
|
@@ -1 +1 @@
|
|
1 |
-
!function(a,b){function c(b){return a("#"+b+" .as3cf-main-settings form").find("input:not(.no-compare)").serialize()}function d(a){var b=l.find("#"+a),c=b.find("input[type=checkbox]");b.toggleClass("on").find("span").toggleClass("checked");var d=b.find("span.on").hasClass("checked");c.prop("checked",d).trigger("change")}function e(b){var c=b.next(".as3cf-validation-error"),d=a("#"+l.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9\.\-]/;e.test(b.val())?(c.show(),d.prop("disabled",!0)):(c.hide(),d.prop("disabled",!1))}function f(){var c=a("#"+b.prefix+"-bucket").val(),d=l.find('input[name="object-prefix"]'),e=d.val();""!==e&&(e=as3cf.provider_console_url_prefix_param+encodeURIComponent(e));var f=as3cf.provider_console_url+c+e;a("#"+b.prefix+"-view-bucket").attr("href",f)}function g(){a("#as3cf-remove-local-file").is(":checked")&&a("#as3cf-serve-from-s3").is(":not(:checked)")?a("#as3cf-lost-files-notice").show():a("#as3cf-lost-files-notice").hide()}function h(){a("#as3cf-remove-local-file").is(":checked")?a("#as3cf-remove-local-notice").show():a("#as3cf-remove-local-notice").hide()}function i(b){!0!==b?a("#as3cf-seo-friendly-url-notice").show():a("#as3cf-seo-friendly-url-notice").hide()}function j(){a(".as3cf-url-preview").html("Generating...");var b={_nonce:as3cf.nonces.get_url_preview};a.each(a("#tab-"+as3cf.tabs.defaultTab+" .as3cf-main-settings form").serializeArray(),function(c,d){var e=d.name,f=d.value;e=e.replace("[]",""),b[e]=void 0===b[e]?f:a.isArray(b[e])?b[e].concat(f):[b[e],f]}),b.action="as3cf-get-url-preview",a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:b,error:function(a,b,c){alert(as3cf.strings.get_url_preview_error+c)},success:function(b,c,d){"undefined"!=typeof b.success?(a(".as3cf-url-preview").html(b.url),i(b.seo_friendly)):alert(as3cf.strings.get_url_preview_error+b.error)}})}function k(){return"#"+as3cf.tabs.defaultTab===location.hash?void(location.hash=""):(as3cf.tabs.toggle(location.hash.replace("#",""),!0),void a(document).trigger("as3cf.tabRendered",[location.hash.replace("#","")]))}var l,m={},n=/[^a-z0-9.-]/,o=a("body"),p=a(".as3cf-tab");a(".as3cf-settings");as3cf.tabs={defaultTab:"media",toggle:function(c,d){c=as3cf.tabs.sanitizeHash(c),p.hide(),l=a("#tab-"+c),l.show(),a(".nav-tab").removeClass("nav-tab-active"),a('a.nav-tab[data-tab="'+c+'"]').addClass("nav-tab-active"),a(".as3cf-main").data("tab",c),l.data("prefix")&&(b.prefix=l.data("prefix")),d||a(".as3cf-updated").removeClass("show"),"support"===c&&as3cf.tabs.getDiagnosticInfo()},getDiagnosticInfo:function(){var b=a(".debug-log-textarea");b.html(as3cf.strings.get_diagnostic_info);var c={action:"as3cf-get-diagnostic-info",_nonce:as3cf.nonces.get_diagnostic_info};a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:c,error:function(a,c,d){b.html(d)},success:function(a,c,d){"undefined"!=typeof a.success?b.html(a.diagnostic_info):(b.html(as3cf.strings.get_diagnostic_info_error),b.append(a.error))}})},sanitizeHash:function(b){var c=a("#tab-"+b);return 0===c.length&&(b=as3cf.tabs.defaultTab),b}},as3cf.buckets={validLength:3,bucketSelectLock:!1,loadList:function(c){"undefined"==typeof c&&(c=!1);var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select"),e=d.find(".bucket-select-region"),f=d.find(".as3cf-bucket-list"),g=a("#"+b.prefix+"-bucket").val();if(!1===c&&f.find("li").length>1)return a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+g+'"]').addClass("selected"),void this.scrollToSelected();f.html('<li class="loading">'+f.data("working")+"</li>"),this.disabledButtons();var h={action:b.prefix+"-get-buckets",_nonce:window[b.prefix.replace(/-/g,"_")].nonces.get_buckets};e.val()&&(h.region=e.val());var i=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:h,error:function(a,b,c){f.html(""),i.showError(as3cf.strings.get_buckets_error,c,"as3cf-bucket-select")},success:function(b,c,d){f.html(""),"undefined"!=typeof b.success?(a(".as3cf-bucket-error").hide(),0===b.buckets.length?f.html('<li class="loading">'+f.data("nothing-found")+"</li>"):(a(b.buckets).each(function(a,b){var c=b.Name===g?"selected":"";f.append('<li><a class="'+c+'" href="#" data-bucket="'+b.Name+'"><span class="bucket"><span class="dashicons dashicons-portfolio"></span> '+b.Name+'</span><span class="spinner"></span></span></a></li>')}),i.scrollToSelected(),i.disabledButtons())):i.showError(as3cf.strings.get_buckets_error,b.error,"as3cf-bucket-select")}})},scrollToSelected:function(){if(a(".as3cf-bucket-list a.selected").length){var b=a("ul.as3cf-bucket-list li").first().position().top+150;a(".as3cf-bucket-list").animate({scrollTop:a("ul.as3cf-bucket-list li a.selected").position().top-b})}},setSelected:function(c){a(".as3cf-bucket-list a").removeClass("selected"),c.addClass("selected"),a("#"+b.prefix+"-bucket-select-name").val(c.data("bucket"))},disabledButtons:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create"),d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual"),e=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select");0===c.length&&0===d.length&&0===e.length||(0<c.length&&this.isValidName(c.find(".as3cf-bucket-name").val())?c.find("button[type=submit]").prop("disabled",!1):c.find("button[type=submit]").prop("disabled",!0),0<d.length&&this.isValidName(d.find(".as3cf-bucket-name").val())?d.find("button[type=submit]").prop("disabled",!1):d.find("button[type=submit]").prop("disabled",!0),0<e.length&&1===e.find(".as3cf-bucket-list a.selected").length?e.find("button[type=submit]").prop("disabled",!1):e.find("button[type=submit]").prop("disabled",!0))},showError:function(b,c,d){var e=a(".as3cf-bucket-container").children(":visible"),f=e.find(".as3cf-bucket-error");d="undefined"==typeof d?null:d,d&&!e.hasClass(d)||(f.find("span.title").html(b+" —"),f.find("span.message").html(c),f.show(),this.bucketSelectLock=!1)},isValidName:function(a){return!(a.length<3||a.length>63)&&!0!==n.test(a)},updateNameNotice:function(b){var c=null;!0===n.test(b)?c=as3cf.strings.create_bucket_invalid_chars:b.length<3?c=as3cf.strings.create_bucket_name_short:b.length>63&&(c=as3cf.strings.create_bucket_name_long),c&&b.length>0?a(".as3cf-invalid-bucket-name").html(c):a(".as3cf-invalid-bucket-name").html("")}},as3cf.reloadUpdated=function(){var a=location.pathname+location.search;location.search.match(/[?&]updated=/)||(a+="&updated=1"),a+=location.hash,location.assign(a)},as3cf.showSettingsSavedNotice=function(){if(!(0<a("#setting-error-settings_updated:visible").length||0<a("#as3cf-settings_updated:visible").length)){var b='<div id="as3cf-settings_updated" class="updated settings-error notice is-dismissible"><p><strong>'+as3cf.strings.settings_saved+"</strong></p></div>";a("h2.nav-tab-wrapper").after(b),a(document).trigger("wp-updates-notice-added")}},a(document).ready(function(){k(),window.onhashchange=function(a){"function"==typeof history.replaceState&&"#"===location.href.slice(-1)&&history.replaceState({},"",location.href.slice(0,-1)),k()};var i=a(".as3cf-main .nav-tab-wrapper");a(".as3cf-compatibility-notice, div.updated, div.error, div.notice").not(".below-h2, .inline").insertAfter(i),p.length&&p.each(function(a,b){m[b.id]=c(b.id)}),a(window).on("beforeunload.as3cf-settings",function(){if(!a.isEmptyObject(m)){var b=l.attr("id");return c(b)!==m[b]?as3cf.strings.save_alert:void 0}}),a(document).on("submit",".as3cf-main-settings form",function(b){a(window).off("beforeunload.as3cf-settings")}),a(".as3cf-switch").on("click",function(b){a(this).hasClass("disabled")||d(a(this).attr("id"))}),p.on("change",".sub-toggle",function(b){var c=a(this).attr("id");a(".as3cf-setting."+c).toggleClass("hide")}),a(".as3cf-domain").on("change",'input[type="radio"]',function(b){var c=a(this).closest('input:radio[name="domain"]:checked'),d=c.val(),e=a(this).parents(".as3cf-domain").find(".as3cf-setting.cloudfront"),f="cloudfront"===d;e.toggleClass("hide",!f)}),a(".url-preview").on("change","input",function(a){j()}),g(),a("#as3cf-serve-from-s3,#as3cf-remove-local-file").on("change",function(a){g()}),h(),a("#as3cf-remove-local-file").on("change",function(a){h()}),a('.as3cf-setting input[type="text"]').keypress(function(a){if(13===a.which)return a.preventDefault(),!1}),a('input[name="cloudfront"]').on("keyup",function(b){e(a(this))}),a('input[name="domain"]').on("change",function(b){var c=a(this),d=a("#"+l.attr("id")+' form button[type="submit"]');"cloudfront"!==c.val()?d.prop("disabled",!1):e(c.next(".as3cf-setting").find('input[name="cloudfront"]'))}),a('input[name="object-prefix"]').on("change",function(a){f()}),a("#tab-media > .as3cf-bucket-error").detach().insertAfter(".as3cf-bucket-container h3"),as3cf.buckets.disabledButtons(),o.on("click",".bucket-action-refresh",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),o.on("change",".bucket-select-region",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),0<a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select").length&&as3cf.buckets.loadList(!0),o.on("click",".as3cf-bucket-list a",function(b){b.preventDefault(),as3cf.buckets.setSelected(a(this)),as3cf.buckets.disabledButtons()}),a(".as3cf-bucket-container").on("click","a.js-link",function(b){return b.preventDefault(),window.open(a(this).attr("href")),!1}),o.on("input keyup",".as3cf-bucket-create .as3cf-bucket-name",function(b){var c=a(this).val();as3cf.buckets.updateNameNotice(c),as3cf.buckets.disabledButtons()}),o.on("input keyup",".as3cf-bucket-manual .as3cf-bucket-name",function(b){var c=a(this).val();as3cf.buckets.updateNameNotice(c),as3cf.buckets.disabledButtons()}),a('.as3cf-bucket-container input[type="text"]').keypress(function(a){if(13===a.which)return a.preventDefault(),!1})})}(jQuery,as3cfModal);
|
1 |
+
!function(a,b){function c(b){return a("#"+b+" .as3cf-main-settings form").find("input:not(.no-compare)").serialize()}function d(a){var b=o.find("#"+a),c=b.find("input[type=checkbox]");b.toggleClass("on").find("span").toggleClass("checked");var d=b.find("span.on").hasClass("checked");c.prop("checked",d).trigger("change")}function e(b){var c=b.next(".as3cf-validation-error"),d=a("#"+o.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9\.\-]/;e.test(b.val())?(c.show(),d.prop("disabled",!0)):(c.hide(),d.prop("disabled",!1))}function f(b){var c=b.next(".as3cf-validation-error"),d=a("#"+o.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9]/;e.test(b.val())?(c.show(),d.prop("disabled",!0)):(c.hide(),d.prop("disabled",!1))}function g(b){var c=b.next(".as3cf-validation-error"),d=a("#"+o.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9\.\-\\:\/ ]/;e.test(b.val())?(c.show(),d.prop("disabled",!0)):(c.hide(),d.prop("disabled",!1))}function h(b){var c=b.next(".as3cf-validation-error"),d=a("#"+o.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9\-\/ ]/;e.test(b.val())?(c.show(),d.prop("disabled",!0)):(c.hide(),d.prop("disabled",!1))}function i(){var c=a("#"+b.prefix+"-bucket").val(),d=o.find('input[name="object-prefix"]'),e=d.val();""!==e&&(e=as3cf.provider_console_url_prefix_param+encodeURIComponent(e));var f=as3cf.provider_console_url+c+e;a("#"+b.prefix+"-view-bucket").attr("href",f)}function j(){a("#as3cf-remove-local-file").is(":checked")&&a("#as3cf-serve-from-s3").is(":not(:checked)")?a("#as3cf-lost-files-notice").show():a("#as3cf-lost-files-notice").hide()}function k(){a("#as3cf-remove-local-file").is(":checked")?a("#as3cf-remove-local-notice").show():a("#as3cf-remove-local-notice").hide()}function l(b){!0!==b?a("#as3cf-seo-friendly-url-notice").show():a("#as3cf-seo-friendly-url-notice").hide()}function m(){a(".as3cf-url-preview").html("Generating...");var b={_nonce:as3cf.nonces.get_url_preview};a.each(a("#tab-"+as3cf.tabs.defaultTab+" .as3cf-main-settings form").serializeArray(),function(c,d){var e=d.name,f=d.value;e=e.replace("[]",""),b[e]=void 0===b[e]?f:a.isArray(b[e])?b[e].concat(f):[b[e],f]}),b.action="as3cf-get-url-preview",a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:b,error:function(a,b,c){alert(as3cf.strings.get_url_preview_error+c)},success:function(b,c,d){"undefined"!=typeof b.success?(a(".as3cf-url-preview").html(b.url),l(b.seo_friendly)):alert(as3cf.strings.get_url_preview_error+b.error)}})}function n(){return"#"+as3cf.tabs.defaultTab===location.hash?void(location.hash=""):(as3cf.tabs.toggle(location.hash.replace("#",""),!0),void a(document).trigger("as3cf.tabRendered",[location.hash.replace("#","")]))}var o,p={},q=/[^a-z0-9.-]/,r=a("body"),s=a(".as3cf-tab");a(".as3cf-settings");as3cf.tabs={defaultTab:"media",toggle:function(c,d){c=as3cf.tabs.sanitizeHash(c),s.hide(),o=a("#tab-"+c),o.show(),a(".nav-tab").removeClass("nav-tab-active"),a('a.nav-tab[data-tab="'+c+'"]').addClass("nav-tab-active"),a(".as3cf-main").data("tab",c),o.data("prefix")&&(b.prefix=o.data("prefix")),d||a(".as3cf-updated").removeClass("show"),"support"===c&&as3cf.tabs.getDiagnosticInfo()},getDiagnosticInfo:function(){var b=a(".debug-log-textarea");b.html(as3cf.strings.get_diagnostic_info);var c={action:"as3cf-get-diagnostic-info",_nonce:as3cf.nonces.get_diagnostic_info};a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:c,error:function(a,c,d){b.html(d)},success:function(a,c,d){"undefined"!=typeof a.success?b.html(a.diagnostic_info):(b.html(as3cf.strings.get_diagnostic_info_error),b.append(a.error))}})},sanitizeHash:function(b){var c=a("#tab-"+b);return 0===c.length&&(b=as3cf.tabs.defaultTab),b}},as3cf.buckets={validLength:3,bucketSelectLock:!1,loadList:function(c){"undefined"==typeof c&&(c=!1);var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select"),e=d.find(".bucket-select-region"),f=d.find(".as3cf-bucket-list"),g=a("#"+b.prefix+"-bucket").val();if(!1===c&&f.find("li").length>1)return a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+g+'"]').addClass("selected"),void this.scrollToSelected();f.html('<li class="loading">'+f.data("working")+"</li>"),this.disabledButtons();var h={action:b.prefix+"-get-buckets",_nonce:window[b.prefix.replace(/-/g,"_")].nonces.get_buckets};e.val()&&(h.region=e.val());var i=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:h,error:function(a,b,c){f.html(""),i.showError(as3cf.strings.get_buckets_error,c,"as3cf-bucket-select")},success:function(b,c,d){f.html(""),"undefined"!=typeof b.success?(a(".as3cf-bucket-error").hide(),0===b.buckets.length?f.html('<li class="loading">'+f.data("nothing-found")+"</li>"):(a(b.buckets).each(function(a,b){var c=b.Name===g?"selected":"";f.append('<li><a class="'+c+'" href="#" data-bucket="'+b.Name+'"><span class="bucket"><span class="dashicons dashicons-portfolio"></span> '+b.Name+'</span><span class="spinner"></span></span></a></li>')}),i.scrollToSelected(),i.disabledButtons())):i.showError(as3cf.strings.get_buckets_error,b.error,"as3cf-bucket-select")}})},scrollToSelected:function(){if(a(".as3cf-bucket-list a.selected").length){var b=a("ul.as3cf-bucket-list li").first().position().top+150;a(".as3cf-bucket-list").animate({scrollTop:a("ul.as3cf-bucket-list li a.selected").position().top-b})}},setSelected:function(c){a(".as3cf-bucket-list a").removeClass("selected"),c.addClass("selected"),a("#"+b.prefix+"-bucket-select-name").val(c.data("bucket"))},disabledButtons:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create"),d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual"),e=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select");0===c.length&&0===d.length&&0===e.length||(0<c.length&&this.isValidName(c.find(".as3cf-bucket-name").val())?c.find("button[type=submit]").prop("disabled",!1):c.find("button[type=submit]").prop("disabled",!0),0<d.length&&this.isValidName(d.find(".as3cf-bucket-name").val())?d.find("button[type=submit]").prop("disabled",!1):d.find("button[type=submit]").prop("disabled",!0),0<e.length&&1===e.find(".as3cf-bucket-list a.selected").length?e.find("button[type=submit]").prop("disabled",!1):e.find("button[type=submit]").prop("disabled",!0))},showError:function(b,c,d){var e=a(".as3cf-bucket-container").children(":visible"),f=e.find(".as3cf-bucket-error");d="undefined"==typeof d?null:d,d&&!e.hasClass(d)||(f.find("span.title").html(b+" —"),f.find("span.message").html(c),f.show(),this.bucketSelectLock=!1)},isValidName:function(a){return!(a.length<3||a.length>63)&&!0!==q.test(a)},updateNameNotice:function(b){var c=null;!0===q.test(b)?c=as3cf.strings.create_bucket_invalid_chars:b.length<3?c=as3cf.strings.create_bucket_name_short:b.length>63&&(c=as3cf.strings.create_bucket_name_long),c&&b.length>0?a(".as3cf-invalid-bucket-name").html(c):a(".as3cf-invalid-bucket-name").html("")}},as3cf.reloadUpdated=function(){var a=location.pathname+location.search;location.search.match(/[?&]updated=/)||(a+="&updated=1"),a+=location.hash,location.assign(a)},as3cf.showSettingsSavedNotice=function(){if(!(0<a("#setting-error-settings_updated:visible").length||0<a("#as3cf-settings_updated:visible").length)){var b='<div id="as3cf-settings_updated" class="updated settings-error notice is-dismissible"><p><strong>'+as3cf.strings.settings_saved+"</strong></p></div>";a("h2.nav-tab-wrapper").after(b),a(document).trigger("wp-updates-notice-added")}},as3cf.Settings=as3cf.Settings?as3cf.Settings:{},as3cf.Settings.Media={lock:function(b){a("#as3cf-media-settings-locked-"+b).show(),a(".as3cf-media-settings").addClass("locked locked-"+b),a(".as3cf-media-settings.locked-"+b).each(function(){a(this).find("input,button").prop("disabled",!0),a(this).find(".as3cf-settings-container").addClass("as3cf-locked-setting"),a(this).find("a.as3cf-change-settings").hide()})},unlock:function(b){a(".as3cf-media-settings.locked-"+b).each(function(){a(this).find("input,button").filter(":not(.disabled)").prop("disabled",!1),a(this).find(".as3cf-settings-container").removeClass("as3cf-locked-setting"),a(this).find("a.as3cf-change-settings").show(),a(this).removeClass("locked locked-"+b)}),a("#as3cf-media-settings-locked-"+b).hide()}},a(document).ready(function(){n(),window.onhashchange=function(a){"function"==typeof history.replaceState&&"#"===location.href.slice(-1)&&history.replaceState({},"",location.href.slice(0,-1)),n()};var l=a(".as3cf-main .nav-tab-wrapper");a(".as3cf-compatibility-notice, div.updated, div.error, div.notice").not(".below-h2, .inline").insertAfter(l),s.length&&s.each(function(a,b){p[b.id]=c(b.id)}),a(window).on("beforeunload.as3cf-settings",function(){if(!a.isEmptyObject(p)){var b=o.attr("id");return c(b)!==p[b]?as3cf.strings.save_alert:void 0}}),a(document).on("submit",".as3cf-main-settings form",function(b){a(window).off("beforeunload.as3cf-settings")}),a(".as3cf-switch").on("click",function(b){a(this).hasClass("disabled")||a(this).parents().hasClass("locked")||d(a(this).attr("id"))}),s.on("change",".sub-toggle",function(b){var c=a(this).attr("id");a(".as3cf-setting."+c).toggleClass("hide")}),a(".url-preview").on("change","input",function(a){m()}),j(),a("#as3cf-serve-from-s3,#as3cf-remove-local-file").on("change",function(a){j()}),k(),a("#as3cf-remove-local-file").on("change",function(a){k()}),a('.as3cf-setting input[type="text"]').keypress(function(a){if(13===a.which)return a.preventDefault(),!1}),a(".as3cf-enable-delivery-domain-container").on("change",'input[type="checkbox"]',function(b){var c=a(this).is(":checked"),d=a(this).parents(".as3cf-enable-delivery-domain-container").find(".as3cf-setting.as3cf-delivery-domain");d.toggleClass("hide",!c);var e=a(this).parents(".as3cf-enable-delivery-domain-container").siblings(".as3cf-enable-signed-urls-container");e.toggleClass("hide",!c)}),a('input[name="enable-delivery-domain"]').on("change",function(b){var c=a(this),d=a("#"+o.attr("id")+' form button[type="submit"]');"1"!==c.val()?d.prop("disabled",!1):e(c.next(".as3cf-setting").find('input[name="delivery-domain"]'))}),a('input[name="delivery-domain"]').on("keyup",function(b){e(a(this))}),a(".as3cf-enable-signed-urls-container").on("change",'input[type="checkbox"]',function(b){var c=a(this).is(":checked"),d=a(this).parents(".as3cf-enable-signed-urls-container").find(".as3cf-setting.as3cf-signed-urls");d.toggleClass("hide",!c)}),a('input[name="signed-urls-key-id"]').on("keyup",function(b){f(a(this))}),a('input[name="enable-signed-urls-key-id"]').on("change",function(b){var c=a(this),d=a("#"+o.attr("id")+' form button[type="submit"]');"1"!==c.val()?d.prop("disabled",!1):f(c.next(".as3cf-setting").find('input[name="signed-urls-key-id"]'))}),a('input[name="signed-urls-key-file-path"]').on("keyup",function(b){g(a(this))}),a('input[name="enable-signed-urls-key-file-path"]').on("change",function(b){var c=a(this),d=a("#"+o.attr("id")+' form button[type="submit"]');"1"!==c.val()?d.prop("disabled",!1):g(c.next(".as3cf-setting").find('input[name="signed-urls-key-file-path"]'))}),a('input[name="signed-urls-object-prefix"]').on("keyup",function(b){h(a(this))}),a('input[name="enable-signed-urls-object-prefix"]').on("change",function(b){var c=a(this),d=a("#"+o.attr("id")+' form button[type="submit"]');"1"!==c.val()?d.prop("disabled",!1):h(c.next(".as3cf-setting").find('input[name="signed-urls-object-prefix"]'))}),a('input[name="object-prefix"]').on("change",function(a){i()}),a("#tab-media > .as3cf-bucket-error").detach().insertAfter(".as3cf-bucket-container h3"),as3cf.buckets.disabledButtons(),r.on("click",".bucket-action-refresh",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),r.on("change",".bucket-select-region",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),0<a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select").length&&as3cf.buckets.loadList(!0),r.on("click",".as3cf-bucket-list a",function(b){b.preventDefault(),as3cf.buckets.setSelected(a(this)),as3cf.buckets.disabledButtons()}),a(".as3cf-bucket-container").on("click","a.js-link",function(b){return b.preventDefault(),window.open(a(this).attr("href")),!1}),r.on("input keyup",".as3cf-bucket-create .as3cf-bucket-name",function(b){var c=a(this).val();as3cf.buckets.updateNameNotice(c),as3cf.buckets.disabledButtons()}),r.on("input keyup",".as3cf-bucket-manual .as3cf-bucket-name",function(b){var c=a(this).val();as3cf.buckets.updateNameNotice(c),as3cf.buckets.disabledButtons()}),a('.as3cf-bucket-container input[type="text"]').keypress(function(a){if(13===a.which)return a.preventDefault(),!1}),a(".as3cf-change-bucket-access-prompt").on("change","#origin-access-identity-confirmation",function(b){a("#block-public-access-confirmed").prop("disabled",!a(this).prop("checked"))}),a(".as3cf-media-settings.locked.locked-upgrade").each(function(){as3cf.Settings.Media.lock("upgrade")})})}(jQuery,as3cfModal);
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.as3cf-delivery-provider-select {
|
2 |
+
.as3cf-delivery-provider-select-options {
|
3 |
+
margin-bottom: 30px;
|
4 |
+
|
5 |
+
.as3cf-delivery-provider-sub-option {
|
6 |
+
margin-left: 25px;
|
7 |
+
|
8 |
+
.as3cf-setting {
|
9 |
+
display: none;
|
10 |
+
margin-left: 25px;
|
11 |
+
}
|
12 |
+
|
13 |
+
&.selected {
|
14 |
+
.as3cf-setting {
|
15 |
+
display: block;
|
16 |
+
}
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
.as3cf-delivery-provider-sub-option-container > .as3cf-delivery-provider-sub-option {
|
21 |
+
display: none;
|
22 |
+
}
|
23 |
+
|
24 |
+
.as3cf-delivery-provider-sub-option-container.selected > .as3cf-delivery-provider-sub-option {
|
25 |
+
display: block;
|
26 |
+
}
|
27 |
+
}
|
28 |
+
}
|
@@ -1,6 +1,98 @@
|
|
1 |
body.as3cf-pro {
|
|
|
|
|
|
|
|
|
2 |
.attachments-browser .media-toolbar-secondary {
|
3 |
max-width: 100%;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
}
|
5 |
}
|
6 |
|
@@ -23,4 +115,4 @@ body.as3cf-pro {
|
|
23 |
.attachment-info .attachment-s3-details {
|
24 |
font-weight: bold;
|
25 |
margin-bottom: 5px;
|
26 |
-
}
|
1 |
body.as3cf-pro {
|
2 |
+
.media-toolbar-mode-select {
|
3 |
+
overflow: visible;
|
4 |
+
}
|
5 |
+
|
6 |
.attachments-browser .media-toolbar-secondary {
|
7 |
max-width: 100%;
|
8 |
+
|
9 |
+
.offload-buttons {
|
10 |
+
margin-right: 10px;
|
11 |
+
position: relative;
|
12 |
+
display: none !important;
|
13 |
+
|
14 |
+
&.visible {
|
15 |
+
display: inline-block !important;
|
16 |
+
}
|
17 |
+
|
18 |
+
.button {
|
19 |
+
margin: 0;
|
20 |
+
text-align: left;
|
21 |
+
|
22 |
+
@media screen and (max-width: 782px) {
|
23 |
+
min-height: 40px;
|
24 |
+
}
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
.offload-buttons__action-default {
|
29 |
+
width: calc(100% - 32px);
|
30 |
+
position: relative;
|
31 |
+
z-index: 2;
|
32 |
+
}
|
33 |
+
|
34 |
+
.offload-buttons__toggle {
|
35 |
+
width: 32px;
|
36 |
+
position: relative;
|
37 |
+
border-left: 1px solid rgba(255, 255, 255, 0.2);
|
38 |
+
z-index: 2;
|
39 |
+
|
40 |
+
&:focus {
|
41 |
+
box-shadow: none;
|
42 |
+
}
|
43 |
+
|
44 |
+
&::after {
|
45 |
+
content: '';
|
46 |
+
display: inline-block;
|
47 |
+
width: 0;
|
48 |
+
height: 0;
|
49 |
+
vertical-align: 0.255em;
|
50 |
+
border-top: 0.3em solid;
|
51 |
+
border-right: 0.3em solid transparent;
|
52 |
+
border-bottom: 0;
|
53 |
+
border-left: 0.3em solid transparent;
|
54 |
+
transition: 0.2s all ease;
|
55 |
+
}
|
56 |
+
|
57 |
+
&.opened {
|
58 |
+
&::after {
|
59 |
+
transform: rotate(180deg);
|
60 |
+
}
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
.offload-buttons__submenu {
|
65 |
+
position: absolute;
|
66 |
+
left: 0;
|
67 |
+
top: 0;
|
68 |
+
z-index: 1;
|
69 |
+
transform: translateY(33px);
|
70 |
+
border-radius: 3px;
|
71 |
+
overflow: hidden;
|
72 |
+
box-shadow: 0 2px 5px 2px rgba(0, 0, 0, 0.3);
|
73 |
+
|
74 |
+
@media screen and (max-width: 782px) {
|
75 |
+
transform: translateY(41px);
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
.offload-buttons__action {
|
80 |
+
display: block;
|
81 |
+
width: 100%;
|
82 |
+
margin: 0;
|
83 |
+
border-radius: 0;
|
84 |
+
text-align-last: left;
|
85 |
+
border: none;
|
86 |
+
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
|
87 |
+
|
88 |
+
&:last-child {
|
89 |
+
border: none;
|
90 |
+
}
|
91 |
+
|
92 |
+
&:focus {
|
93 |
+
box-shadow: none;
|
94 |
+
}
|
95 |
+
}
|
96 |
}
|
97 |
}
|
98 |
|
115 |
.attachment-info .attachment-s3-details {
|
116 |
font-weight: bold;
|
117 |
margin-bottom: 5px;
|
118 |
+
}
|
@@ -78,10 +78,12 @@ $as3cf_assets: #0769ad;
|
|
78 |
.as3cf-notice, .error, .updated, .updated.show {
|
79 |
display: none;
|
80 |
}
|
|
|
81 |
.fatal .error, .as3cf-notice.important, .dbrains-api-down {
|
82 |
display: block;
|
83 |
}
|
84 |
}
|
|
|
85 |
.as3cf-notice, .error, .updated {
|
86 |
max-width: 650px;
|
87 |
margin-top: 15px;
|
@@ -90,6 +92,7 @@ $as3cf_assets: #0769ad;
|
|
90 |
|
91 |
.as3cf-updated {
|
92 |
display: none;
|
|
|
93 |
&.as3cf-notice, &.show {
|
94 |
display: block;
|
95 |
}
|
@@ -106,27 +109,38 @@ $as3cf_assets: #0769ad;
|
|
106 |
}
|
107 |
|
108 |
/**
|
109 |
-
* Show Storage Provider / Bucket Select / media Settings
|
110 |
*/
|
111 |
.as3cf-tab {
|
|
|
112 |
.as3cf-main-settings {
|
113 |
.as3cf-provider-select {
|
114 |
display: none;
|
115 |
}
|
116 |
|
117 |
-
.as3cf-bucket-container
|
|
|
118 |
display: none;
|
119 |
|
120 |
-
|
121 |
-
|
122 |
}
|
123 |
}
|
124 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
.as3cf-media-settings {
|
126 |
display: none;
|
127 |
}
|
128 |
}
|
129 |
|
|
|
130 |
&.as3cf-needs-access-keys, &.as3cf-has-access-keys.as3cf-change-provider {
|
131 |
.as3cf-can-write-error {
|
132 |
display: none;
|
@@ -141,12 +155,21 @@ $as3cf_assets: #0769ad;
|
|
141 |
display: none;
|
142 |
}
|
143 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
.as3cf-media-settings {
|
145 |
display: none;
|
146 |
}
|
147 |
}
|
148 |
}
|
149 |
|
|
|
150 |
&.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider), &.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) {
|
151 |
.as3cf-can-write-error {
|
152 |
display: none;
|
@@ -161,13 +184,55 @@ $as3cf_assets: #0769ad;
|
|
161 |
display: block;
|
162 |
}
|
163 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
.as3cf-media-settings {
|
165 |
display: none;
|
166 |
}
|
167 |
}
|
168 |
}
|
169 |
|
170 |
-
|
|
|
|
|
|
|
|
|
|
|
171 |
.as3cf-main-settings {
|
172 |
.as3cf-provider-select {
|
173 |
display: none;
|
@@ -177,6 +242,39 @@ $as3cf_assets: #0769ad;
|
|
177 |
display: none;
|
178 |
}
|
179 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
180 |
.as3cf-media-settings {
|
181 |
display: block;
|
182 |
}
|
@@ -210,6 +308,7 @@ $as3cf_assets: #0769ad;
|
|
210 |
.as3cf-main-settings {
|
211 |
p {
|
212 |
font-size: 13px;
|
|
|
213 |
a {
|
214 |
color: #444;
|
215 |
}
|
@@ -235,6 +334,7 @@ $as3cf_assets: #0769ad;
|
|
235 |
padding: 0 20px 10px;
|
236 |
overflow-x: scroll;
|
237 |
}
|
|
|
238 |
span {
|
239 |
color: #aaa;
|
240 |
text-transform: uppercase;
|
@@ -246,6 +346,7 @@ $as3cf_assets: #0769ad;
|
|
246 |
label {
|
247 |
display: block;
|
248 |
margin-bottom: 10px;
|
|
|
249 |
&.disabled, &.disabled p {
|
250 |
color: #bbb;
|
251 |
cursor: default;
|
@@ -257,6 +358,7 @@ $as3cf_assets: #0769ad;
|
|
257 |
color: #6b6b6b;
|
258 |
margin: 0;
|
259 |
font-size: 12px;
|
|
|
260 |
&.as3cf-setting {
|
261 |
margin-top: 5px;
|
262 |
}
|
@@ -324,6 +426,16 @@ $as3cf_assets: #0769ad;
|
|
324 |
&.hide {
|
325 |
display: none;
|
326 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
327 |
}
|
328 |
|
329 |
div.as3cf-setting {
|
@@ -343,18 +455,27 @@ $as3cf_assets: #0769ad;
|
|
343 |
border-bottom: 1px solid #ddd;
|
344 |
padding: 20px 0px;
|
345 |
}
|
|
|
346 |
&.as3cf-setting-title td {
|
347 |
padding-bottom: 0;
|
348 |
}
|
|
|
349 |
&.as3cf-setting-title:first-child td {
|
350 |
padding-top: 20px;
|
351 |
}
|
|
|
352 |
&.configure-url:first-child td {
|
353 |
padding-top: 5px;
|
354 |
padding-bottom: 0;
|
355 |
}
|
|
|
|
|
|
|
|
|
|
|
356 |
td {
|
357 |
padding: 15px 0;
|
|
|
358 |
&:first-child {
|
359 |
vertical-align: top;
|
360 |
min-width: 120px;
|
@@ -375,6 +496,7 @@ $as3cf_assets: #0769ad;
|
|
375 |
padding: 0;
|
376 |
margin: 0;
|
377 |
}
|
|
|
378 |
h4 {
|
379 |
margin: 0;
|
380 |
}
|
@@ -388,12 +510,15 @@ $as3cf_assets: #0769ad;
|
|
388 |
color: #444;
|
389 |
text-decoration: none;
|
390 |
margin-right: 10px;
|
|
|
391 |
&:hover, &:active {
|
392 |
color: #00a0d2;
|
393 |
}
|
|
|
394 |
&:focus {
|
395 |
box-shadow: none;
|
396 |
}
|
|
|
397 |
.dashicons-external {
|
398 |
margin-top: -2px;
|
399 |
}
|
@@ -463,12 +588,13 @@ $as3cf_assets: #0769ad;
|
|
463 |
background: #ccc;
|
464 |
color: #fff;
|
465 |
padding: 2px 5px;
|
466 |
-
margin: 0 0
|
467 |
float: right;
|
468 |
white-space: nowrap;
|
|
|
469 |
}
|
470 |
|
471 |
-
.as3cf-defined-setting {
|
472 |
color: #bbb;
|
473 |
|
474 |
label {
|
@@ -489,21 +615,50 @@ $as3cf_assets: #0769ad;
|
|
489 |
}
|
490 |
|
491 |
p.actions {
|
492 |
-
margin:
|
493 |
-
|
494 |
-
|
|
|
495 |
overflow: hidden;
|
496 |
|
|
|
497 |
.right {
|
|
|
498 |
margin-left: 15px;
|
|
|
|
|
499 |
|
500 |
&:last-of-type {
|
501 |
margin-left: 0;
|
502 |
}
|
503 |
}
|
504 |
|
505 |
-
|
506 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
507 |
}
|
508 |
}
|
509 |
}
|
@@ -555,9 +710,11 @@ $as3cf_assets: #0769ad;
|
|
555 |
margin: 0;
|
556 |
}
|
557 |
}
|
|
|
558 |
.as3cf-bucket-list {
|
559 |
margin: 5px 0 0 0;
|
560 |
}
|
|
|
561 |
td {
|
562 |
padding: 5px 0;
|
563 |
|
@@ -566,10 +723,14 @@ $as3cf_assets: #0769ad;
|
|
566 |
line-height: 30px;
|
567 |
vertical-align: top;
|
568 |
}
|
|
|
|
|
|
|
|
|
569 |
}
|
570 |
}
|
571 |
|
572 |
-
|
573 |
margin: 15px 0;
|
574 |
border-top: 1px solid #ccc;
|
575 |
padding-top: 15px;
|
@@ -586,7 +747,7 @@ $as3cf_assets: #0769ad;
|
|
586 |
margin-right: 20px;
|
587 |
line-height: 28px;
|
588 |
}
|
589 |
-
}
|
590 |
|
591 |
.as3cf-bucket-list {
|
592 |
padding: 15px;
|
@@ -620,12 +781,45 @@ $as3cf_assets: #0769ad;
|
|
620 |
}
|
621 |
}
|
622 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
623 |
#tab-media {
|
624 |
display: block;
|
625 |
}
|
626 |
|
627 |
#tab-support {
|
628 |
min-height: 900px;
|
|
|
629 |
.as3cf-sidebar {
|
630 |
top: 11px;
|
631 |
}
|
@@ -962,6 +1156,7 @@ textarea.as3cf-access-key-constants-snippet.code {
|
|
962 |
|
963 |
.extra {
|
964 |
background: white;
|
|
|
965 |
a {
|
966 |
color: $as3cf_assets;
|
967 |
text-decoration: none;
|
78 |
.as3cf-notice, .error, .updated, .updated.show {
|
79 |
display: none;
|
80 |
}
|
81 |
+
|
82 |
.fatal .error, .as3cf-notice.important, .dbrains-api-down {
|
83 |
display: block;
|
84 |
}
|
85 |
}
|
86 |
+
|
87 |
.as3cf-notice, .error, .updated {
|
88 |
max-width: 650px;
|
89 |
margin-top: 15px;
|
92 |
|
93 |
.as3cf-updated {
|
94 |
display: none;
|
95 |
+
|
96 |
&.as3cf-notice, &.show {
|
97 |
display: block;
|
98 |
}
|
109 |
}
|
110 |
|
111 |
/**
|
112 |
+
* Show Storage Provider / Bucket Select / Delivery Provider Select / media Settings
|
113 |
*/
|
114 |
.as3cf-tab {
|
115 |
+
/* Initial State: Show Nothing (overridden below) */
|
116 |
.as3cf-main-settings {
|
117 |
.as3cf-provider-select {
|
118 |
display: none;
|
119 |
}
|
120 |
|
121 |
+
.as3cf-bucket-container,
|
122 |
+
.as3cf-change-bucket-access-prompt {
|
123 |
display: none;
|
124 |
|
125 |
+
h3 {
|
126 |
+
margin-bottom: -0.5em;
|
127 |
}
|
128 |
}
|
129 |
|
130 |
+
a.as3cf-change-provider {
|
131 |
+
display: none;
|
132 |
+
}
|
133 |
+
|
134 |
+
.as3cf-delivery-provider-select {
|
135 |
+
display: none;
|
136 |
+
}
|
137 |
+
|
138 |
.as3cf-media-settings {
|
139 |
display: none;
|
140 |
}
|
141 |
}
|
142 |
|
143 |
+
/* Need/Change Storage Provider */
|
144 |
&.as3cf-needs-access-keys, &.as3cf-has-access-keys.as3cf-change-provider {
|
145 |
.as3cf-can-write-error {
|
146 |
display: none;
|
155 |
display: none;
|
156 |
}
|
157 |
|
158 |
+
.as3cf-change-bucket-access-prompt {
|
159 |
+
display: none;
|
160 |
+
}
|
161 |
+
|
162 |
+
.as3cf-delivery-provider-select {
|
163 |
+
display: none;
|
164 |
+
}
|
165 |
+
|
166 |
.as3cf-media-settings {
|
167 |
display: none;
|
168 |
}
|
169 |
}
|
170 |
}
|
171 |
|
172 |
+
/* Need/Change Bucket */
|
173 |
&.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider), &.as3cf-has-access-keys.as3cf-change-bucket:not(.as3cf-change-provider) {
|
174 |
.as3cf-can-write-error {
|
175 |
display: none;
|
184 |
display: block;
|
185 |
}
|
186 |
|
187 |
+
.as3cf-change-bucket-access-prompt {
|
188 |
+
display: none;
|
189 |
+
}
|
190 |
+
|
191 |
+
.as3cf-delivery-provider-select {
|
192 |
+
display: none;
|
193 |
+
}
|
194 |
+
|
195 |
+
.as3cf-media-settings {
|
196 |
+
display: none;
|
197 |
+
}
|
198 |
+
}
|
199 |
+
}
|
200 |
+
|
201 |
+
/* Change Bucket Access */
|
202 |
+
&.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-bucket-access {
|
203 |
+
.as3cf-can-write-error {
|
204 |
+
display: none;
|
205 |
+
}
|
206 |
+
|
207 |
+
.as3cf-main-settings {
|
208 |
+
.as3cf-provider-select {
|
209 |
+
display: none;
|
210 |
+
}
|
211 |
+
|
212 |
+
.as3cf-bucket-container {
|
213 |
+
display: none;
|
214 |
+
}
|
215 |
+
|
216 |
+
.as3cf-change-bucket-access-prompt {
|
217 |
+
display: block;
|
218 |
+
}
|
219 |
+
|
220 |
+
.as3cf-delivery-provider-select {
|
221 |
+
display: none;
|
222 |
+
}
|
223 |
+
|
224 |
.as3cf-media-settings {
|
225 |
display: none;
|
226 |
}
|
227 |
}
|
228 |
}
|
229 |
|
230 |
+
/* Change Delivery Provider */
|
231 |
+
&.as3cf-has-access-keys.as3cf-has-bucket.as3cf-change-delivery-provider {
|
232 |
+
.as3cf-can-write-error {
|
233 |
+
display: none;
|
234 |
+
}
|
235 |
+
|
236 |
.as3cf-main-settings {
|
237 |
.as3cf-provider-select {
|
238 |
display: none;
|
242 |
display: none;
|
243 |
}
|
244 |
|
245 |
+
.as3cf-change-bucket-access-prompt {
|
246 |
+
display: none;
|
247 |
+
}
|
248 |
+
|
249 |
+
.as3cf-delivery-provider-select {
|
250 |
+
display: block;
|
251 |
+
}
|
252 |
+
|
253 |
+
.as3cf-media-settings {
|
254 |
+
display: none;
|
255 |
+
}
|
256 |
+
}
|
257 |
+
}
|
258 |
+
|
259 |
+
/* Normal Media Settings */
|
260 |
+
&.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider):not(.as3cf-change-bucket):not(.as3cf-change-bucket-access):not(.as3cf-change-delivery-provider) {
|
261 |
+
.as3cf-main-settings {
|
262 |
+
.as3cf-provider-select {
|
263 |
+
display: none;
|
264 |
+
}
|
265 |
+
|
266 |
+
.as3cf-bucket-container {
|
267 |
+
display: none;
|
268 |
+
}
|
269 |
+
|
270 |
+
.as3cf-change-bucket-access-prompt {
|
271 |
+
display: none;
|
272 |
+
}
|
273 |
+
|
274 |
+
.as3cf-delivery-provider-select {
|
275 |
+
display: none;
|
276 |
+
}
|
277 |
+
|
278 |
.as3cf-media-settings {
|
279 |
display: block;
|
280 |
}
|
308 |
.as3cf-main-settings {
|
309 |
p {
|
310 |
font-size: 13px;
|
311 |
+
|
312 |
a {
|
313 |
color: #444;
|
314 |
}
|
334 |
padding: 0 20px 10px;
|
335 |
overflow-x: scroll;
|
336 |
}
|
337 |
+
|
338 |
span {
|
339 |
color: #aaa;
|
340 |
text-transform: uppercase;
|
346 |
label {
|
347 |
display: block;
|
348 |
margin-bottom: 10px;
|
349 |
+
|
350 |
&.disabled, &.disabled p {
|
351 |
color: #bbb;
|
352 |
cursor: default;
|
358 |
color: #6b6b6b;
|
359 |
margin: 0;
|
360 |
font-size: 12px;
|
361 |
+
|
362 |
&.as3cf-setting {
|
363 |
margin-top: 5px;
|
364 |
}
|
426 |
&.hide {
|
427 |
display: none;
|
428 |
}
|
429 |
+
|
430 |
+
.as3cf-sub-setting {
|
431 |
+
.as3cf-sub-setting-heading {
|
432 |
+
padding-top: 15px;
|
433 |
+
}
|
434 |
+
|
435 |
+
.as3cf-defined-in-config {
|
436 |
+
margin-top: 15px;
|
437 |
+
}
|
438 |
+
}
|
439 |
}
|
440 |
|
441 |
div.as3cf-setting {
|
455 |
border-bottom: 1px solid #ddd;
|
456 |
padding: 20px 0px;
|
457 |
}
|
458 |
+
|
459 |
&.as3cf-setting-title td {
|
460 |
padding-bottom: 0;
|
461 |
}
|
462 |
+
|
463 |
&.as3cf-setting-title:first-child td {
|
464 |
padding-top: 20px;
|
465 |
}
|
466 |
+
|
467 |
&.configure-url:first-child td {
|
468 |
padding-top: 5px;
|
469 |
padding-bottom: 0;
|
470 |
}
|
471 |
+
|
472 |
+
&.hide {
|
473 |
+
display: none;
|
474 |
+
}
|
475 |
+
|
476 |
td {
|
477 |
padding: 15px 0;
|
478 |
+
|
479 |
&:first-child {
|
480 |
vertical-align: top;
|
481 |
min-width: 120px;
|
496 |
padding: 0;
|
497 |
margin: 0;
|
498 |
}
|
499 |
+
|
500 |
h4 {
|
501 |
margin: 0;
|
502 |
}
|
510 |
color: #444;
|
511 |
text-decoration: none;
|
512 |
margin-right: 10px;
|
513 |
+
|
514 |
&:hover, &:active {
|
515 |
color: #00a0d2;
|
516 |
}
|
517 |
+
|
518 |
&:focus {
|
519 |
box-shadow: none;
|
520 |
}
|
521 |
+
|
522 |
.dashicons-external {
|
523 |
margin-top: -2px;
|
524 |
}
|
588 |
background: #ccc;
|
589 |
color: #fff;
|
590 |
padding: 2px 5px;
|
591 |
+
margin: 0 0 3px 5px;
|
592 |
float: right;
|
593 |
white-space: nowrap;
|
594 |
+
clear: right;
|
595 |
}
|
596 |
|
597 |
+
.as3cf-defined-setting, .as3cf-locked-setting {
|
598 |
color: #bbb;
|
599 |
|
600 |
label {
|
615 |
}
|
616 |
|
617 |
p.actions {
|
618 |
+
margin: 30px 0;
|
619 |
+
border-top: 1px solid #ccc;
|
620 |
+
//padding: 20px 30px;
|
621 |
+
padding-top: 15px;
|
622 |
overflow: hidden;
|
623 |
|
624 |
+
button,
|
625 |
.right {
|
626 |
+
float: right;
|
627 |
margin-left: 15px;
|
628 |
+
margin-right: 0;
|
629 |
+
min-width: 90px;
|
630 |
|
631 |
&:last-of-type {
|
632 |
margin-left: 0;
|
633 |
}
|
634 |
}
|
635 |
|
636 |
+
span {
|
637 |
+
display: inline-block;
|
638 |
+
margin-right: 20px;
|
639 |
+
line-height: 28px;
|
640 |
+
}
|
641 |
+
}
|
642 |
+
|
643 |
+
/**
|
644 |
+
* When entire tab's settings are locked.
|
645 |
+
*/
|
646 |
+
.locked {
|
647 |
+
.as3cf-radio-group {
|
648 |
+
label, label p {
|
649 |
+
color: #bbb;
|
650 |
+
cursor: default;
|
651 |
+
}
|
652 |
+
}
|
653 |
+
|
654 |
+
.as3cf-switch {
|
655 |
+
cursor: default;
|
656 |
+
background: #e6e6e6;
|
657 |
+
|
658 |
+
span {
|
659 |
+
background: #f1f1f1;
|
660 |
+
color: #d6d6d6;
|
661 |
+
}
|
662 |
}
|
663 |
}
|
664 |
}
|
710 |
margin: 0;
|
711 |
}
|
712 |
}
|
713 |
+
|
714 |
.as3cf-bucket-list {
|
715 |
margin: 5px 0 0 0;
|
716 |
}
|
717 |
+
|
718 |
td {
|
719 |
padding: 5px 0;
|
720 |
|
723 |
line-height: 30px;
|
724 |
vertical-align: top;
|
725 |
}
|
726 |
+
|
727 |
+
.as3cf-defined-in-config {
|
728 |
+
margin-top: -1.75em;
|
729 |
+
}
|
730 |
}
|
731 |
}
|
732 |
|
733 |
+
/*.bucket-actions {
|
734 |
margin: 15px 0;
|
735 |
border-top: 1px solid #ccc;
|
736 |
padding-top: 15px;
|
747 |
margin-right: 20px;
|
748 |
line-height: 28px;
|
749 |
}
|
750 |
+
}*/
|
751 |
|
752 |
.as3cf-bucket-list {
|
753 |
padding: 15px;
|
781 |
}
|
782 |
}
|
783 |
|
784 |
+
/**
|
785 |
+
* Change Bucket Access
|
786 |
+
*/
|
787 |
+
.as3cf-change-bucket-access-prompt {
|
788 |
+
h3 {
|
789 |
+
line-height: 1.3;
|
790 |
+
text-transform: none;
|
791 |
+
}
|
792 |
+
|
793 |
+
.as3cf-radio-group {
|
794 |
+
margin-bottom: 25px;
|
795 |
+
}
|
796 |
+
|
797 |
+
.note {
|
798 |
+
color: #999;
|
799 |
+
}
|
800 |
+
}
|
801 |
+
|
802 |
+
/**
|
803 |
+
* Change Delivery Provider
|
804 |
+
*/
|
805 |
+
.as3cf-delivery-provider-select {
|
806 |
+
h3 {
|
807 |
+
line-height: 1.3;
|
808 |
+
text-transform: none;
|
809 |
+
}
|
810 |
+
|
811 |
+
.note {
|
812 |
+
color: #999;
|
813 |
+
}
|
814 |
+
}
|
815 |
+
|
816 |
#tab-media {
|
817 |
display: block;
|
818 |
}
|
819 |
|
820 |
#tab-support {
|
821 |
min-height: 900px;
|
822 |
+
|
823 |
.as3cf-sidebar {
|
824 |
top: 11px;
|
825 |
}
|
1156 |
|
1157 |
.extra {
|
1158 |
background: white;
|
1159 |
+
|
1160 |
a {
|
1161 |
color: $as3cf_assets;
|
1162 |
text-decoration: none;
|
@@ -1,11 +1,23 @@
|
|
1 |
<?php
|
2 |
|
3 |
use DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item;
|
4 |
-
use DeliciousBrains\WP_Offload_Media\Providers\
|
5 |
-
use DeliciousBrains\WP_Offload_Media\Providers\
|
6 |
-
use DeliciousBrains\WP_Offload_Media\Providers\
|
7 |
-
use DeliciousBrains\WP_Offload_Media\Providers\
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
use DeliciousBrains\WP_Offload_Media\Providers\Provider;
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_Content_Replace_URLs;
|
10 |
use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_EDD_Replace_URLs;
|
11 |
use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_File_Sizes;
|
@@ -18,12 +30,12 @@ use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_WPOS3_To_AS3CF;
|
|
18 |
class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
19 |
|
20 |
/**
|
21 |
-
* @var
|
22 |
*/
|
23 |
-
private $
|
24 |
|
25 |
/**
|
26 |
-
* @var
|
27 |
*/
|
28 |
private $provider_client;
|
29 |
|
@@ -32,6 +44,11 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
32 |
*/
|
33 |
private $provider_client_region;
|
34 |
|
|
|
|
|
|
|
|
|
|
|
35 |
/**
|
36 |
* @var array
|
37 |
*/
|
@@ -85,12 +102,22 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
85 |
/**
|
86 |
* @var string
|
87 |
*/
|
88 |
-
protected static $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
|
90 |
/**
|
91 |
-
* @var array Known provider classes.
|
92 |
*/
|
93 |
-
protected static $
|
94 |
|
95 |
/**
|
96 |
* @var AS3CF_Plugin_Compatibility
|
@@ -138,15 +165,30 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
138 |
$this->plugin_title = __( 'Offload Media Lite', 'amazon-s3-and-cloudfront' );
|
139 |
$this->plugin_menu_title = __( 'Offload Media Lite', 'amazon-s3-and-cloudfront' );
|
140 |
|
141 |
-
static::$
|
142 |
-
AWS_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\AWS_Provider',
|
143 |
-
DigitalOcean_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\DigitalOcean_Provider',
|
144 |
-
GCP_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\GCP_Provider',
|
145 |
-
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
|
147 |
Media_Library_Item::init_cache();
|
148 |
|
149 |
-
$this->
|
|
|
150 |
|
151 |
// Bundled SDK may require AWS setup before data migrations.
|
152 |
$this->handle_aws_access_key_migration();
|
@@ -184,6 +226,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
184 |
|
185 |
// Rewriting URLs, doesn't depend on plugin being setup
|
186 |
add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 99, 2 );
|
|
|
187 |
add_filter( 'get_image_tag', array( $this, 'maybe_encode_get_image_tag' ), 99, 6 );
|
188 |
add_filter( 'wp_get_attachment_image_src', array( $this, 'maybe_encode_wp_get_attachment_image_src' ), 99, 4 );
|
189 |
add_filter( 'wp_prepare_attachment_for_js', array( $this, 'maybe_encode_wp_prepare_attachment_for_js', ), 99, 3 );
|
@@ -217,50 +260,114 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
217 |
|
218 |
// Register storage provider scripts and styles
|
219 |
$this->register_storage_provider_assets();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
}
|
221 |
|
222 |
/**
|
223 |
-
* @return
|
224 |
*/
|
225 |
-
public function
|
226 |
-
return $this->
|
227 |
}
|
228 |
|
229 |
/**
|
230 |
-
* @param
|
231 |
*
|
232 |
* @throws Exception
|
233 |
*/
|
234 |
-
public function
|
235 |
-
if ( empty( $
|
236 |
-
$
|
|
|
|
|
|
|
|
|
|
|
237 |
}
|
238 |
|
239 |
-
if ( is_string( $
|
240 |
-
$
|
241 |
}
|
242 |
|
243 |
-
$
|
|
|
|
|
|
|
|
|
|
|
244 |
}
|
245 |
|
246 |
/**
|
247 |
* Returns the currently supported Providers.
|
248 |
*
|
|
|
|
|
249 |
* @return array
|
250 |
*/
|
251 |
-
public function get_provider_classes() {
|
252 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
}
|
254 |
|
255 |
/**
|
256 |
* Returns provider class name for given key.
|
257 |
*
|
258 |
* @param string $key_name
|
|
|
259 |
*
|
260 |
-
* @return
|
261 |
*/
|
262 |
-
public function get_provider_class( $key_name ) {
|
263 |
-
|
|
|
|
|
|
|
264 |
|
265 |
return empty( $classes[ $key_name ] ) ? null : $classes[ $key_name ];
|
266 |
}
|
@@ -269,12 +376,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
269 |
* Provider name for given key.
|
270 |
*
|
271 |
* @param string $key_name
|
|
|
272 |
*
|
273 |
* @return string
|
274 |
*/
|
275 |
-
public function get_provider_name( $key_name ) {
|
276 |
-
|
277 |
-
|
|
|
|
|
278 |
|
279 |
return empty( $class ) ? __( 'Unknown', 'amazon-s3-and-cloudfront' ) : $class::get_provider_name();
|
280 |
}
|
@@ -283,12 +393,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
283 |
* Provider & Service name for given key.
|
284 |
*
|
285 |
* @param string $key_name
|
|
|
286 |
*
|
287 |
* @return string
|
288 |
*/
|
289 |
-
public function get_provider_service_name( $key_name ) {
|
290 |
-
|
291 |
-
|
|
|
|
|
292 |
|
293 |
return empty( $class ) ? __( 'Unknown', 'amazon-s3-and-cloudfront' ) : $class::get_provider_service_name();
|
294 |
}
|
@@ -352,7 +465,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
352 |
'key' => $key,
|
353 |
'disabled' => false,
|
354 |
'disabled_attr' => '',
|
355 |
-
'tr_class' => str_replace( '_', '-', $this->get_plugin_prefix() . '-' . $key . '-container' ),
|
356 |
'setting_msg' => '',
|
357 |
'is_defined' => false,
|
358 |
);
|
@@ -520,6 +633,52 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
520 |
return $aws_secret_access_key;
|
521 |
}
|
522 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
523 |
$value = parent::get_setting( $key, $default );
|
524 |
|
525 |
// Provider
|
@@ -532,6 +691,11 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
532 |
return $bucket;
|
533 |
}
|
534 |
|
|
|
|
|
|
|
|
|
|
|
535 |
return apply_filters( 'as3cf_setting_' . $key, $value );
|
536 |
}
|
537 |
|
@@ -589,14 +753,14 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
589 |
|
590 |
// Region of bucket translation
|
591 |
if ( 'region' === $key && isset( $settings['region'] ) ) {
|
592 |
-
return $this->
|
593 |
}
|
594 |
|
595 |
return false;
|
596 |
}
|
597 |
|
598 |
/**
|
599 |
-
* Get the bucket and if a constant
|
600 |
*
|
601 |
* @param string $key
|
602 |
* @param string $value
|
@@ -646,9 +810,58 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
646 |
*/
|
647 |
public function bucket_changed() {
|
648 |
$this->remove_setting( 'region' );
|
|
|
649 |
$this->save_settings();
|
650 |
}
|
651 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
652 |
/**
|
653 |
* Filter in defined settings with sensible defaults.
|
654 |
*
|
@@ -734,10 +947,18 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
734 |
$defined_settings = ! empty( $defined_settings ) ? $defined_settings : $this->get_defined_settings();
|
735 |
$whitelisted_settings = $this->get_settings_whitelist();
|
736 |
$settings_to_skip = array(
|
|
|
|
|
|
|
|
|
|
|
737 |
'bucket',
|
738 |
'region',
|
739 |
-
'
|
|
|
740 |
'virtual-host',
|
|
|
|
|
741 |
);
|
742 |
|
743 |
foreach ( $whitelisted_settings as $setting ) {
|
@@ -745,16 +966,41 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
745 |
continue;
|
746 |
}
|
747 |
|
748 |
-
if (
|
749 |
-
|
750 |
-
|
751 |
-
|
|
|
|
|
752 |
}
|
753 |
|
754 |
-
if (
|
755 |
-
|
756 |
-
|
757 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
758 |
}
|
759 |
|
760 |
if ( ! isset( $defined_settings[ $setting ] ) ) {
|
@@ -867,17 +1113,21 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
867 |
* @return string
|
868 |
*/
|
869 |
function get_url_preview( $escape = true, $suffix = 'photo.jpg' ) {
|
870 |
-
$
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
|
|
|
|
877 |
|
878 |
-
$
|
879 |
|
880 |
-
|
|
|
|
|
881 |
|
882 |
// Replace hyphens with non breaking hyphens for formatting
|
883 |
if ( $escape ) {
|
@@ -982,9 +1232,10 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
982 |
* to cope with possible different regions
|
983 |
*/
|
984 |
function remove_attachment_files_from_provider( $post_id, Media_Library_Item $as3cf_item, $include_backups = true, $log_error = false, $return_on_error = false, $force_new_provider_client = false ) {
|
985 |
-
$prefix
|
986 |
-
$
|
987 |
-
$paths
|
|
|
988 |
|
989 |
// If another item in current site shares full size *local* paths, only remove remote files not referenced by duplicates.
|
990 |
// We reference local paths as they should be reflected one way or another remotely, including backups.
|
@@ -1009,9 +1260,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1009 |
|
1010 |
$objects_to_remove = array();
|
1011 |
|
1012 |
-
foreach ( $paths as $path ) {
|
1013 |
$objects_to_remove[] = array(
|
1014 |
-
'Key' => $
|
1015 |
);
|
1016 |
}
|
1017 |
|
@@ -1178,7 +1429,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1178 |
$post_id,
|
1179 |
$duplicate_item->source_path(),
|
1180 |
wp_basename( $duplicate_item->original_source_path() ),
|
1181 |
-
$duplicate_item->
|
1182 |
);
|
1183 |
|
1184 |
$old_item->save();
|
@@ -1235,7 +1486,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1235 |
return $this->return_upload_error( $error_msg, $return_metadata );
|
1236 |
}
|
1237 |
|
1238 |
-
$acl = $this->
|
1239 |
|
1240 |
// check the attachment already exists in provider, eg. edit or restore image
|
1241 |
if ( $old_item ) {
|
@@ -1246,11 +1497,13 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1246 |
|
1247 |
// Use private ACL if existing offload is already private.
|
1248 |
if ( $old_item->is_private() ) {
|
1249 |
-
$acl = $this->
|
1250 |
}
|
1251 |
|
1252 |
// use existing prefix
|
1253 |
$prefix = $old_item->normalized_path_dir();
|
|
|
|
|
1254 |
// use existing bucket
|
1255 |
$bucket = $old_item->bucket();
|
1256 |
// get existing region
|
@@ -1259,8 +1512,14 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1259 |
$original_filename = wp_basename( $old_item->original_source_path() );
|
1260 |
} else {
|
1261 |
// derive prefix from various settings
|
1262 |
-
$
|
1263 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1264 |
|
1265 |
// use bucket from settings
|
1266 |
$bucket = $this->get_setting( 'bucket' );
|
@@ -1273,19 +1532,26 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1273 |
$original_filename = empty( $data['original_image'] ) ? null : $data['original_image'];
|
1274 |
}
|
1275 |
|
1276 |
-
$acl
|
1277 |
-
$acl
|
|
|
1278 |
|
1279 |
$args = array(
|
1280 |
'Bucket' => $bucket,
|
1281 |
'Key' => $prefix . $file_name,
|
1282 |
'SourceFile' => $file_path,
|
1283 |
-
'ACL' => $acl,
|
1284 |
'ContentType' => $type,
|
1285 |
'CacheControl' => 'max-age=31536000',
|
1286 |
'Expires' => date( 'D, d M Y H:i:s O', time() + 31536000 ),
|
1287 |
);
|
1288 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1289 |
// TODO: Remove GZIP functionality.
|
1290 |
// Handle gzip on supported items
|
1291 |
if ( $this->should_gzip_file( $file_path, $type ) && false !== ( $gzip_body = gzencode( file_get_contents( $file_path ) ) ) ) {
|
@@ -1295,18 +1561,26 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1295 |
$args['ContentEncoding'] = 'gzip';
|
1296 |
}
|
1297 |
|
1298 |
-
$
|
1299 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1300 |
|
1301 |
-
$
|
1302 |
-
$region = $bucket !== $args['Bucket'] ? $this->get_bucket_region( $args['Bucket'], true ) : $region;
|
1303 |
-
$is_private = $this->get_provider()->get_private_acl() === $args['ACL'] ? true : false;
|
1304 |
-
$private_sizes = empty( $old_item ) ? array() : $old_item->private_sizes();
|
1305 |
-
$item_id = empty( $old_item ) ? null : $old_item->id();
|
1306 |
|
1307 |
-
|
|
|
|
|
1308 |
|
1309 |
-
do_action( 'as3cf_upload_attachment_pre_remove', $post_id, $as3cf_item, $
|
1310 |
|
1311 |
$new_offloads = array();
|
1312 |
$files_to_remove = array();
|
@@ -1335,17 +1609,22 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1335 |
|
1336 |
foreach ( $file_paths as $size => $file_path ) {
|
1337 |
if ( ! in_array( $file_path, $files_to_remove ) ) {
|
1338 |
-
$acl = apply_filters( 'as3cf_upload_acl_sizes', $this->
|
1339 |
|
|
|
|
|
|
|
|
|
|
|
1340 |
$additional_images[ $size ] = array(
|
1341 |
-
'Key' => $
|
1342 |
'SourceFile' => $file_path,
|
1343 |
-
'ACL' => $acl,
|
1344 |
'ContentType' => $this->get_mime_type( $file_path ),
|
1345 |
);
|
1346 |
|
1347 |
-
if
|
1348 |
-
|
|
|
1349 |
}
|
1350 |
}
|
1351 |
}
|
@@ -1360,6 +1639,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1360 |
|
1361 |
$args = apply_filters( 'as3cf_object_meta', array_merge( $args, $image ), $post_id, $size, false );
|
1362 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1363 |
if ( ! file_exists( $args['SourceFile'] ) ) {
|
1364 |
if ( ! $duplicate ) {
|
1365 |
$upload_errors[] = $this->return_upload_error( sprintf( __( 'File %s does not exist', 'amazon-s3-and-cloudfront' ), $args['SourceFile'] ) );
|
@@ -1390,7 +1678,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1390 |
$as3cf_item->source_id(),
|
1391 |
$as3cf_item->source_path(),
|
1392 |
wp_basename( $image['SourceFile'] ),
|
1393 |
-
$as3cf_item->
|
1394 |
$as3cf_item->id()
|
1395 |
);
|
1396 |
}
|
@@ -1430,6 +1718,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1430 |
|
1431 |
// Additional image sizes have custom ACLs, record them.
|
1432 |
if ( ! empty( $private_sizes ) ) {
|
|
|
|
|
|
|
1433 |
$as3cf_item = new Media_Library_Item(
|
1434 |
$as3cf_item->provider(),
|
1435 |
$as3cf_item->region(),
|
@@ -1439,7 +1730,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1439 |
$as3cf_item->source_id(),
|
1440 |
$as3cf_item->source_path(),
|
1441 |
wp_basename( $as3cf_item->original_source_path() ),
|
1442 |
-
$
|
1443 |
$as3cf_item->id()
|
1444 |
);
|
1445 |
}
|
@@ -1875,7 +2166,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1875 |
* TODO: Performance - cache / static var by param.
|
1876 |
*/
|
1877 |
function is_plugin_setup( $with_credentials = false ) {
|
1878 |
-
if ( $with_credentials && $this->
|
1879 |
// AWS not configured
|
1880 |
return false;
|
1881 |
}
|
@@ -1904,7 +2195,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1904 |
* @param array $headers Header overrides for request
|
1905 |
* @param bool $skip_rewrite_check
|
1906 |
*
|
1907 |
-
* @return
|
1908 |
*/
|
1909 |
public function get_secure_attachment_url( $post_id, $expires = null, $size = null, $headers = array(), $skip_rewrite_check = false ) {
|
1910 |
if ( is_null( $expires ) ) {
|
@@ -1988,18 +2279,35 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
1988 |
}
|
1989 |
|
1990 |
/**
|
1991 |
-
* Get
|
1992 |
*
|
1993 |
-
* @param int
|
1994 |
-
* @param
|
1995 |
-
* @param string|null $size Size of the image to get
|
1996 |
-
* @param array|null $meta Pre retrieved _wp_attachment_metadata for the attachment
|
1997 |
-
* @param array $headers Header overrides for request
|
1998 |
-
* @param bool $skip_rewrite_check Always return the URL regardless of the 'Rewrite File URLs' setting.
|
1999 |
-
* Useful for the EDD and Woo addons to not break download URLs when the
|
2000 |
-
* option is disabled.
|
2001 |
*
|
2002 |
-
* @return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2003 |
*/
|
2004 |
public function get_attachment_url( $post_id, $expires = null, $size = null, $meta = null, $headers = array(), $skip_rewrite_check = false ) {
|
2005 |
if ( ! ( $as3cf_item = $this->is_attachment_served_by_provider( $post_id, $skip_rewrite_check ) ) ) {
|
@@ -2089,17 +2397,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2089 |
* @return string|WP_Error
|
2090 |
*/
|
2091 |
public function get_attachment_provider_url( $post_id, Media_Library_Item $as3cf_item, $expires = null, $size = null, $meta = null, $headers = array() ) {
|
2092 |
-
$
|
2093 |
|
2094 |
-
|
2095 |
-
$region = $this->get_provider()->sanitize_region( $as3cf_item->region() );
|
2096 |
-
} else {
|
2097 |
-
$region = '';
|
2098 |
-
}
|
2099 |
-
|
2100 |
-
$size = $this->maybe_convert_size_to_string( $post_id, $size );
|
2101 |
-
|
2102 |
-
// Force use of secured URL when ACL has been set to private
|
2103 |
if ( is_null( $expires ) ) {
|
2104 |
if ( is_null( $size ) && $as3cf_item->is_private() ) {
|
2105 |
// Full size URL private
|
@@ -2112,6 +2412,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2112 |
}
|
2113 |
}
|
2114 |
|
|
|
|
|
2115 |
if ( ! is_null( $size ) ) {
|
2116 |
if ( is_null( $meta ) ) {
|
2117 |
$meta = get_post_meta( $post_id, '_wp_attachment_metadata', true );
|
@@ -2129,32 +2431,40 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2129 |
}
|
2130 |
}
|
2131 |
|
2132 |
-
$scheme
|
2133 |
-
$
|
2134 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2135 |
|
2136 |
if ( ! is_null( $expires ) && $this->is_plugin_setup( true ) ) {
|
2137 |
try {
|
2138 |
-
|
2139 |
-
|
2140 |
-
}
|
2141 |
|
2142 |
-
|
2143 |
-
|
2144 |
-
|
|
|
|
|
|
|
|
|
2145 |
|
2146 |
-
return apply_filters( '
|
2147 |
} catch ( Exception $e ) {
|
2148 |
return new WP_Error( 'exception', $e->getMessage() );
|
2149 |
}
|
2150 |
}
|
2151 |
-
|
2152 |
-
$item_path = $this->maybe_update_cloudfront_path( $item_path );
|
2153 |
-
|
2154 |
-
$file = $this->encode_filename_in_path( $item_path );
|
2155 |
-
$url = $base_url . '/' . $file;
|
2156 |
-
|
2157 |
-
return apply_filters( 'as3cf_get_attachment_url', $url, $as3cf_item, $post_id, $expires, $headers );
|
2158 |
}
|
2159 |
|
2160 |
/**
|
@@ -2182,6 +2492,39 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2182 |
return $new_url;
|
2183 |
}
|
2184 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2185 |
/**
|
2186 |
* Maybe encode attachment URLs when retrieving the image tag
|
2187 |
*
|
@@ -2213,7 +2556,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2213 |
|
2214 |
$img_src = $matches[1];
|
2215 |
$new_img_src = $this->maybe_sign_intermediate_size( $img_src, $id, $size, $as3cf_item );
|
2216 |
-
$new_img_src =
|
2217 |
|
2218 |
return str_replace( $img_src, $new_img_src, $html );
|
2219 |
}
|
@@ -2236,7 +2579,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2236 |
|
2237 |
if ( isset( $image[0] ) ) {
|
2238 |
$url = $this->maybe_sign_intermediate_size( $image[0], $attachment_id, $size, $as3cf_item );
|
2239 |
-
$url =
|
2240 |
|
2241 |
$image[0] = $url;
|
2242 |
}
|
@@ -2260,13 +2603,13 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2260 |
}
|
2261 |
|
2262 |
if ( isset( $response['url'] ) ) {
|
2263 |
-
$response['url'] =
|
2264 |
}
|
2265 |
|
2266 |
if ( isset( $response['sizes'] ) && is_array( $response['sizes'] ) ) {
|
2267 |
foreach ( $response['sizes'] as $size => $value ) {
|
2268 |
-
$url = $this->maybe_sign_intermediate_size( $value['url'], $attachment->ID, $size, $as3cf_item );
|
2269 |
-
$url =
|
2270 |
|
2271 |
$response['sizes'][ $size ]['url'] = $url;
|
2272 |
}
|
@@ -2292,7 +2635,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2292 |
|
2293 |
if ( isset( $data['url'] ) ) {
|
2294 |
$url = $this->maybe_sign_intermediate_size( $data['url'], $post_id, $size, $as3cf_item );
|
2295 |
-
$url =
|
2296 |
|
2297 |
$data['url'] = $url;
|
2298 |
}
|
@@ -2307,17 +2650,18 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2307 |
* @param int $attachment_id
|
2308 |
* @param string|array $size
|
2309 |
* @param bool|Media_Library_Item $as3cf_item
|
|
|
2310 |
*
|
2311 |
* @return string|WP_Error
|
2312 |
*/
|
2313 |
-
protected function maybe_sign_intermediate_size( $url, $attachment_id, $size, $as3cf_item = false ) {
|
2314 |
if ( ! $as3cf_item ) {
|
2315 |
$as3cf_item = Media_Library_Item::get_by_source_id( $attachment_id );
|
2316 |
}
|
2317 |
|
2318 |
-
$size =
|
2319 |
|
2320 |
-
if ( $as3cf_item->is_private_size( $size ) ) {
|
2321 |
// Private file, add AWS signature if required
|
2322 |
return $this->get_attachment_provider_url( $attachment_id, $as3cf_item, null, $size );
|
2323 |
}
|
@@ -2325,81 +2669,17 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2325 |
return $url;
|
2326 |
}
|
2327 |
|
2328 |
-
/**
|
2329 |
-
* Convert dimensions to size
|
2330 |
-
*
|
2331 |
-
* @param int $attachment_id
|
2332 |
-
* @param array $dimensions
|
2333 |
-
*
|
2334 |
-
* @return null|string
|
2335 |
-
*/
|
2336 |
-
protected function convert_dimensions_to_size_name( $attachment_id, $dimensions ) {
|
2337 |
-
$w = ( isset( $dimensions[0] ) && $dimensions[0] > 0 ) ? $dimensions[0] : 1;
|
2338 |
-
$h = ( isset( $dimensions[1] ) && $dimensions[1] > 0 ) ? $dimensions[1] : 1;
|
2339 |
-
$original_aspect_ratio = $w / $h;
|
2340 |
-
$meta = wp_get_attachment_metadata( $attachment_id );
|
2341 |
-
|
2342 |
-
if ( ! isset( $meta['sizes'] ) || empty( $meta['sizes'] ) ) {
|
2343 |
-
return null;
|
2344 |
-
}
|
2345 |
-
|
2346 |
-
$sizes = $meta['sizes'];
|
2347 |
-
uasort( $sizes, function ( $a, $b ) {
|
2348 |
-
// Order by image area
|
2349 |
-
return ( $a['width'] * $a['height'] ) - ( $b['width'] * $b['height'] );
|
2350 |
-
} );
|
2351 |
-
|
2352 |
-
$nearest_matches = array();
|
2353 |
-
|
2354 |
-
foreach ( $sizes as $size => $value ) {
|
2355 |
-
if ( $w > $value['width'] || $h > $value['height'] ) {
|
2356 |
-
continue;
|
2357 |
-
}
|
2358 |
-
|
2359 |
-
$aspect_ratio = $value['width'] / $value['height'];
|
2360 |
-
|
2361 |
-
if ( $aspect_ratio === $original_aspect_ratio ) {
|
2362 |
-
return $size;
|
2363 |
-
}
|
2364 |
-
|
2365 |
-
$nearest_matches[] = $size;
|
2366 |
-
}
|
2367 |
-
|
2368 |
-
// Return nearest match
|
2369 |
-
if ( ! empty( $nearest_matches ) ) {
|
2370 |
-
return $nearest_matches[0];
|
2371 |
-
}
|
2372 |
-
|
2373 |
-
return null;
|
2374 |
-
}
|
2375 |
-
|
2376 |
-
/**
|
2377 |
-
* Maybe convert size to string
|
2378 |
-
*
|
2379 |
-
* @param int $attachment_id
|
2380 |
-
* @param mixed $size
|
2381 |
-
*
|
2382 |
-
* @return null|string
|
2383 |
-
*/
|
2384 |
-
protected function maybe_convert_size_to_string( $attachment_id, $size ) {
|
2385 |
-
if ( is_array( $size ) ) {
|
2386 |
-
return $this->convert_dimensions_to_size_name( $attachment_id, $size );
|
2387 |
-
}
|
2388 |
-
|
2389 |
-
return $size;
|
2390 |
-
}
|
2391 |
-
|
2392 |
/**
|
2393 |
* Is attachment served by provider.
|
2394 |
*
|
2395 |
-
* @param int
|
2396 |
-
* @param bool
|
2397 |
-
* @param bool
|
2398 |
-
* @param
|
2399 |
*
|
2400 |
* @return bool|Media_Library_Item
|
2401 |
*/
|
2402 |
-
public function is_attachment_served_by_provider( $attachment_id, $skip_rewrite_check = false, $skip_current_provider_check = false,
|
2403 |
if ( ! $skip_rewrite_check && ! $this->get_setting( 'serve-from-s3' ) ) {
|
2404 |
// Not serving provider URLs
|
2405 |
return false;
|
@@ -2413,7 +2693,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2413 |
}
|
2414 |
|
2415 |
if ( ! $skip_current_provider_check && empty( $provider ) ) {
|
2416 |
-
$provider = $this->
|
2417 |
}
|
2418 |
|
2419 |
if ( ! empty( $provider ) && $provider::get_provider_key_name() !== $as3cf_item->provider() ) {
|
@@ -2424,44 +2704,6 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2424 |
return $as3cf_item;
|
2425 |
}
|
2426 |
|
2427 |
-
/**
|
2428 |
-
* Encode file names according to RFC 3986 when generating urls
|
2429 |
-
* As per Amazon https://forums.aws.amazon.com/thread.jspa?threadID=55746#jive-message-244233
|
2430 |
-
*
|
2431 |
-
* @param string $file
|
2432 |
-
*
|
2433 |
-
* @return string Encoded filename
|
2434 |
-
*/
|
2435 |
-
public function encode_filename_in_path( $file ) {
|
2436 |
-
$url = parse_url( $file );
|
2437 |
-
|
2438 |
-
if ( ! isset( $url['path'] ) ) {
|
2439 |
-
// Can't determine path, return original
|
2440 |
-
return $file;
|
2441 |
-
}
|
2442 |
-
|
2443 |
-
if ( isset( $url['query'] ) ) {
|
2444 |
-
// Manually strip query string, as passing $url['path'] to basename results in corrupt � characters
|
2445 |
-
$file_name = wp_basename( str_replace( '?' . $url['query'], '', $file ) );
|
2446 |
-
} else {
|
2447 |
-
$file_name = wp_basename( $file );
|
2448 |
-
}
|
2449 |
-
|
2450 |
-
if ( false !== strpos( $file_name, '%' ) ) {
|
2451 |
-
// File name already encoded, return original
|
2452 |
-
return $file;
|
2453 |
-
}
|
2454 |
-
|
2455 |
-
$encoded_file_name = rawurlencode( $file_name );
|
2456 |
-
|
2457 |
-
if ( $file_name === $encoded_file_name ) {
|
2458 |
-
// File name doesn't need encoding, return original
|
2459 |
-
return $file;
|
2460 |
-
}
|
2461 |
-
|
2462 |
-
return str_replace( $file_name, $encoded_file_name, $file );
|
2463 |
-
}
|
2464 |
-
|
2465 |
/**
|
2466 |
* Allow processes to update the file on provider via update_attached_file()
|
2467 |
*
|
@@ -2488,8 +2730,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2488 |
|
2489 |
/**
|
2490 |
* Return the provider URL when the local file is missing
|
2491 |
-
* unless we know the calling process is and we are happy
|
2492 |
-
* to copy the file back to the server to be used
|
2493 |
*
|
2494 |
* @param string $file
|
2495 |
* @param int $attachment_id
|
@@ -2497,8 +2739,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2497 |
* @return string
|
2498 |
*/
|
2499 |
function get_attached_file( $file, $attachment_id ) {
|
2500 |
-
|
2501 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2502 |
}
|
2503 |
|
2504 |
$url = $this->get_attachment_url( $attachment_id );
|
@@ -2610,7 +2859,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2610 |
$region = AS3CF_REGION;
|
2611 |
}
|
2612 |
|
2613 |
-
if ( ! is_null( $region ) && $this->
|
2614 |
$args['LocationConstraint'] = $region;
|
2615 |
}
|
2616 |
|
@@ -2670,6 +2919,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2670 |
|
2671 |
$this->set_setting( 'bucket', $bucket_name );
|
2672 |
|
|
|
|
|
|
|
2673 |
if ( empty( $region ) ) {
|
2674 |
// retrieve the bucket region if not supplied
|
2675 |
$region = $this->get_bucket_region( $bucket_name );
|
@@ -2678,7 +2930,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2678 |
}
|
2679 |
}
|
2680 |
|
2681 |
-
if ( ! $this->
|
2682 |
$region = '';
|
2683 |
}
|
2684 |
|
@@ -2718,27 +2970,59 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2718 |
}
|
2719 |
|
2720 |
/**
|
2721 |
-
*
|
2722 |
*
|
2723 |
-
* @param
|
|
|
|
|
2724 |
*/
|
2725 |
-
public function
|
2726 |
-
$
|
2727 |
-
|
2728 |
-
|
2729 |
-
|
2730 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2731 |
array( $this, 'render_page' )
|
2732 |
);
|
2733 |
}
|
2734 |
|
2735 |
/**
|
2736 |
-
* What is the default provider for legacy data?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2737 |
*
|
2738 |
* @return string
|
2739 |
*/
|
2740 |
-
public static function
|
2741 |
-
return static::$
|
2742 |
}
|
2743 |
|
2744 |
/**
|
@@ -2747,7 +3031,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2747 |
* @return string
|
2748 |
*/
|
2749 |
public function get_default_region() {
|
2750 |
-
return $this->
|
2751 |
}
|
2752 |
|
2753 |
/**
|
@@ -2756,7 +3040,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2756 |
* @param bool|string $region specify region to client for signature
|
2757 |
* @param bool $force force return of new provider client when swapping regions
|
2758 |
*
|
2759 |
-
* @return
|
2760 |
* @throws Exception
|
2761 |
*/
|
2762 |
public function get_provider_client( $region = false, $force = false ) {
|
@@ -2767,17 +3051,17 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2767 |
$args = array();
|
2768 |
|
2769 |
if ( $force ) {
|
2770 |
-
$this->
|
2771 |
}
|
2772 |
|
2773 |
if ( $region ) {
|
2774 |
-
$args['region'] = $this->
|
2775 |
}
|
2776 |
|
2777 |
$provider_client_region = isset( $args['region'] ) ? $args['region'] : $region;
|
2778 |
|
2779 |
try {
|
2780 |
-
$this->set_client( $this->
|
2781 |
} catch ( Exception $e ) {
|
2782 |
AS3CF_Error::log( $e->getMessage() );
|
2783 |
$this->set_client( new Null_Provider );
|
@@ -2790,8 +3074,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2790 |
/**
|
2791 |
* Setter for Provider client
|
2792 |
*
|
2793 |
-
* @param
|
2794 |
-
* @param bool|string
|
2795 |
*/
|
2796 |
public function set_client( $client, $region = false ) {
|
2797 |
$this->provider_client = $client;
|
@@ -2830,7 +3114,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2830 |
return new WP_Error( 'exception', $error_msg_title . $error_msg );
|
2831 |
}
|
2832 |
|
2833 |
-
$region = $this->
|
2834 |
|
2835 |
if ( is_string( $region ) ) {
|
2836 |
$regions[ $bucket ] = $region;
|
@@ -2847,7 +3131,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2847 |
$this->verify_ajax_request();
|
2848 |
|
2849 |
$region = empty( $_POST['region'] ) ? '' : $_POST['region'];
|
2850 |
-
$region = $this->check_region( $region, $this->
|
2851 |
|
2852 |
$result = $this->get_buckets( $region );
|
2853 |
|
@@ -2896,14 +3180,14 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2896 |
* @throws Exception
|
2897 |
*/
|
2898 |
function check_write_permission( $bucket = null, $region = null ) {
|
2899 |
-
if ( $this->
|
2900 |
// If no access keys set then no need check.
|
2901 |
return false;
|
2902 |
}
|
2903 |
|
2904 |
if ( is_null( $bucket ) ) {
|
2905 |
// If changing provider or bucket don't bother to test saved bucket permissions.
|
2906 |
-
if ( ! empty( $_GET['action'] ) && in_array( $_GET['action'], array( 'change-provider', 'change-bucket' ) ) ) {
|
2907 |
return false;
|
2908 |
}
|
2909 |
|
@@ -2992,6 +3276,20 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
2992 |
wp_register_script( 'as3cf-storage-provider', $src, array( 'jquery' ), $version, true );
|
2993 |
}
|
2994 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2995 |
/**
|
2996 |
* On plugin load.
|
2997 |
*/
|
@@ -3008,8 +3306,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3008 |
|
3009 |
add_action( 'network_admin_notices', array( $this, 'settings_saved_notice' ) );
|
3010 |
|
3011 |
-
$this->enqueue_style( 'as3cf-styles', 'assets/css/styles', array( 'as3cf-modal', 'as3cf-storage-provider' ) );
|
3012 |
-
$this->enqueue_script( 'as3cf-script', 'assets/js/script', array( 'jquery', 'underscore', 'as3cf-modal', 'as3cf-storage-provider' ) );
|
3013 |
|
3014 |
wp_localize_script( 'as3cf-script',
|
3015 |
'as3cf',
|
@@ -3040,8 +3338,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3040 |
'aws_keys_remove' => wp_create_nonce( 'as3cf-aws-keys-remove' ),
|
3041 |
),
|
3042 |
'is_pro' => $this->is_pro(),
|
3043 |
-
'provider_console_url' => $this->
|
3044 |
-
'provider_console_url_prefix_param' => $this->
|
3045 |
)
|
3046 |
);
|
3047 |
|
@@ -3059,6 +3357,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3059 |
*/
|
3060 |
function get_settings_whitelist() {
|
3061 |
return array(
|
|
|
3062 |
'provider',
|
3063 |
'access-key-id',
|
3064 |
'secret-access-key',
|
@@ -3067,18 +3366,28 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3067 |
'use-server-roles',
|
3068 |
'bucket',
|
3069 |
'region',
|
3070 |
-
'
|
3071 |
-
'
|
3072 |
-
'permissions',
|
3073 |
-
'cloudfront',
|
3074 |
'object-prefix',
|
3075 |
-
'copy-to-s3',
|
3076 |
-
'serve-from-s3',
|
3077 |
-
'remove-local-file',
|
3078 |
-
'force-https',
|
3079 |
-
'object-versioning',
|
3080 |
'use-yearmonth-folders',
|
3081 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3082 |
);
|
3083 |
}
|
3084 |
|
@@ -3104,6 +3413,26 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3104 |
return array( 'key-file' );
|
3105 |
}
|
3106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3107 |
/**
|
3108 |
* Handle the saving of the settings page
|
3109 |
*/
|
@@ -3121,14 +3450,23 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3121 |
}
|
3122 |
|
3123 |
// Keep track of original provider at start of settings change flow.
|
3124 |
-
$orig_provider =
|
3125 |
|
3126 |
-
|
|
|
|
|
|
|
|
|
|
|
3127 |
// Changing Provider currently doesn't need anything special over saving settings,
|
3128 |
// but if not already set needs to be handled rather than change-bucket raising its hand.
|
3129 |
$changed_keys = $this->handle_save_settings();
|
3130 |
} elseif ( empty( $this->get_setting( 'bucket' ) ) || ( ! empty( $_GET['action'] ) && 'change-bucket' === $_GET['action'] ) ) {
|
3131 |
$changed_keys = $this->handle_change_bucket();
|
|
|
|
|
|
|
|
|
3132 |
} elseif ( ! empty( $_GET['action'] ) ) {
|
3133 |
$changed_keys = apply_filters( 'as3cf_handle_post_request', array() );
|
3134 |
} else {
|
@@ -3147,17 +3485,45 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3147 |
if ( ! empty( $changed_keys ) ) {
|
3148 |
$action = null;
|
3149 |
|
3150 |
-
|
3151 |
-
|
3152 |
-
|
3153 |
-
|
3154 |
-
|
3155 |
-
|
3156 |
-
|
|
|
|
|
|
|
3157 |
} else {
|
3158 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3159 |
}
|
3160 |
}
|
|
|
|
|
3161 |
}
|
3162 |
|
3163 |
// Stash which step we're on in possibly multi-step config.
|
@@ -3165,14 +3531,28 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3165 |
|
3166 |
// Depending on the step we're on, we may need another step if not already determined by newly saved settings.
|
3167 |
if ( empty( $action ) && ! empty( $prev_action ) ) {
|
3168 |
-
// After change-provider we always want the user to confirm the bucket is still ok.
|
3169 |
-
// This gets round the change-provider => change-bucket => "back" problem.
|
3170 |
-
// but then no change in provider settings problem.
|
3171 |
if ( 'change-provider' === $prev_action && ! $this->get_defined_setting( 'bucket', false ) ) {
|
|
|
|
|
|
|
3172 |
$action = 'change-bucket';
|
|
|
|
|
|
|
3173 |
}
|
3174 |
}
|
3175 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3176 |
if ( ! empty( $action ) ) {
|
3177 |
$url_args['action'] = $action;
|
3178 |
|
@@ -3183,6 +3563,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3183 |
if ( ! empty( $orig_provider ) ) {
|
3184 |
$url_args['orig_provider'] = $orig_provider;
|
3185 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3186 |
}
|
3187 |
|
3188 |
$url = $this->get_plugin_page_url( $url_args );
|
@@ -3197,6 +3586,10 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3197 |
* @throws Exception
|
3198 |
*/
|
3199 |
private function handle_change_bucket() {
|
|
|
|
|
|
|
|
|
3200 |
// Quick check that bucket name actually given.
|
3201 |
$bucket = empty( $_POST['bucket_name'] ) ? false : $_POST['bucket_name'];
|
3202 |
|
@@ -3219,7 +3612,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3219 |
|
3220 |
// Check and set region.
|
3221 |
$region = empty( $_POST['region_name'] ) ? '' : $_POST['region_name'];
|
3222 |
-
$region_required = 'create' === $bucket_mode ? true : $this->
|
3223 |
$region = $this->check_region( $region, $region_required );
|
3224 |
|
3225 |
if ( false === $region ) {
|
@@ -3285,6 +3678,109 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3285 |
return $changed_keys;
|
3286 |
}
|
3287 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3288 |
/**
|
3289 |
* Handle saving settings submitted by user.
|
3290 |
*
|
@@ -3333,10 +3829,42 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3333 |
continue;
|
3334 |
}
|
3335 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3336 |
$this->set_setting( $var, $value );
|
3337 |
|
3338 |
// Some setting changes might have knock-on effects that require confirmation of secondary settings.
|
3339 |
-
if ( isset( $old_settings[ $var ] ) && $old_settings[ $var ] !== $value ) {
|
3340 |
$changed_keys[] = $var;
|
3341 |
}
|
3342 |
}
|
@@ -3518,7 +4046,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3518 |
|
3519 |
foreach ( $blogs as $blog ) {
|
3520 |
$blog = (array) $blog;
|
3521 |
-
$blog_ids[] = $blog['blog_id'];
|
3522 |
}
|
3523 |
|
3524 |
return $blog_ids;
|
@@ -3537,58 +4065,6 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3537 |
return true;
|
3538 |
}
|
3539 |
|
3540 |
-
/**
|
3541 |
-
* Apply ACL to an attachment and associated files
|
3542 |
-
*
|
3543 |
-
* @param int $post_id
|
3544 |
-
* @param Media_Library_Item $as3cf_item
|
3545 |
-
* @param bool $private
|
3546 |
-
*
|
3547 |
-
* @return Media_Library_Item|bool|WP_Error
|
3548 |
-
*/
|
3549 |
-
public function set_attachment_acl_on_provider( $post_id, Media_Library_Item $as3cf_item, $private ) {
|
3550 |
-
// Return early if already set to the desired ACL
|
3551 |
-
if ( $as3cf_item->is_private() === $private ) {
|
3552 |
-
return false;
|
3553 |
-
}
|
3554 |
-
|
3555 |
-
$acl = $private ? $this->get_provider()->get_private_acl() : $this->get_provider()->get_default_acl();
|
3556 |
-
|
3557 |
-
$args = array(
|
3558 |
-
'ACL' => $acl,
|
3559 |
-
'Bucket' => $as3cf_item->bucket(),
|
3560 |
-
'Key' => $as3cf_item->path(),
|
3561 |
-
);
|
3562 |
-
|
3563 |
-
$region = empty( $as3cf_item->region() ) ? false : $as3cf_item->region();
|
3564 |
-
|
3565 |
-
try {
|
3566 |
-
$provider_client = $this->get_provider_client( $region, true );
|
3567 |
-
$provider_client->update_object_acl( $args );
|
3568 |
-
|
3569 |
-
$as3cf_item = new Media_Library_Item(
|
3570 |
-
$as3cf_item->provider(),
|
3571 |
-
$as3cf_item->region(),
|
3572 |
-
$as3cf_item->bucket(),
|
3573 |
-
$as3cf_item->path(),
|
3574 |
-
$private,
|
3575 |
-
$as3cf_item->source_id(),
|
3576 |
-
$as3cf_item->source_path(),
|
3577 |
-
wp_basename( $as3cf_item->original_source_path() ),
|
3578 |
-
$as3cf_item->private_sizes(),
|
3579 |
-
$as3cf_item->id()
|
3580 |
-
);
|
3581 |
-
$as3cf_item->save();
|
3582 |
-
} catch ( Exception $e ) {
|
3583 |
-
$msg = 'Error setting ACL to ' . $acl . ' for ' . $as3cf_item->path() . ': ' . $e->getMessage();
|
3584 |
-
AS3CF_Error::log( $msg );
|
3585 |
-
|
3586 |
-
return new WP_Error( 'acl_exception', $msg );
|
3587 |
-
}
|
3588 |
-
|
3589 |
-
return $as3cf_item;
|
3590 |
-
}
|
3591 |
-
|
3592 |
/**
|
3593 |
* Make admin notice for when object ACL has changed
|
3594 |
*
|
@@ -3596,7 +4072,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3596 |
*/
|
3597 |
function make_acl_admin_notice( Media_Library_Item $as3cf_item ) {
|
3598 |
$filename = wp_basename( $as3cf_item->path() );
|
3599 |
-
$acl = $as3cf_item->is_private() ? $this->
|
3600 |
$acl_name = $this->get_acl_display_name( $acl );
|
3601 |
$text = sprintf( __( '<strong>WP Offload Media</strong> — The file %s has been given %s permissions in the bucket.', 'amazon-s3-and-cloudfront' ), "<strong>{$filename}</strong>", "<strong>{$acl_name}</strong>" );
|
3602 |
|
@@ -3867,17 +4343,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3867 |
$media_counts = $this->media_counts();
|
3868 |
|
3869 |
$output .= 'Media Files: ';
|
3870 |
-
$output .= number_format_i18n( $media_counts['total'] )
|
3871 |
$output .= "\r\n";
|
3872 |
|
3873 |
$output .= 'Offloaded Media Files: ';
|
3874 |
-
$output .= number_format_i18n( $media_counts['offloaded'] )
|
3875 |
$output .= "\r\n";
|
3876 |
|
3877 |
$output .= 'Not Offloaded Media Files: ';
|
3878 |
-
$output .= number_format_i18n( $media_counts['not_offloaded'] )
|
3879 |
-
$output .= "\r\n";
|
3880 |
-
$output .= 'Note: Approximate values, paths *try* and discard duplicates.';
|
3881 |
$output .= "\r\n\r\n";
|
3882 |
|
3883 |
$output .= 'Number of Image Sizes: ';
|
@@ -3962,42 +4436,47 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
3962 |
$output .= "\r\n";
|
3963 |
$output .= "\r\n";
|
3964 |
|
3965 |
-
$
|
|
|
|
|
|
|
|
|
3966 |
|
3967 |
-
if ( empty( $
|
3968 |
-
$output .= 'Provider: Not configured';
|
3969 |
$output .= "\r\n";
|
3970 |
} else {
|
3971 |
-
$output .= 'Provider: ' . $
|
3972 |
$output .= "\r\n";
|
3973 |
|
3974 |
-
if ( $
|
3975 |
-
$output .= 'Use Server Roles: '
|
|
|
3976 |
} else {
|
3977 |
$output .= 'Use Server Roles: N/A';
|
3978 |
}
|
3979 |
$output .= "\r\n";
|
3980 |
|
3981 |
-
if ( $
|
3982 |
$output .= 'Key File Path: ';
|
3983 |
-
$output .= empty( $
|
3984 |
$output .= "\r\n";
|
3985 |
$output .= 'Key File Path Define: ';
|
3986 |
-
$output .= $
|
3987 |
} else {
|
3988 |
$output .= 'Key File Path: N/A';
|
3989 |
}
|
3990 |
$output .= "\r\n";
|
3991 |
|
3992 |
-
if ( $
|
3993 |
$output .= 'Access Keys Set: ';
|
3994 |
-
$output .= $
|
3995 |
$output .= "\r\n";
|
3996 |
$output .= 'Access Key ID Define: ';
|
3997 |
-
$output .= $
|
3998 |
$output .= "\r\n";
|
3999 |
$output .= 'Secret Access Key Define: ';
|
4000 |
-
$output .= $
|
4001 |
} else {
|
4002 |
$output .= 'Access Keys Set: N/A';
|
4003 |
}
|
@@ -4005,15 +4484,41 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
4005 |
}
|
4006 |
$output .= "\r\n";
|
4007 |
|
|
|
4008 |
$output .= 'Bucket: ';
|
4009 |
-
$output .=
|
4010 |
$output .= "\r\n";
|
|
|
4011 |
$output .= 'Region: ';
|
4012 |
-
|
4013 |
-
|
4014 |
-
|
|
|
|
|
|
|
4015 |
}
|
4016 |
$output .= "\r\n";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4017 |
$output .= "\r\n";
|
4018 |
|
4019 |
$output .= 'Copy Files to Bucket: ';
|
@@ -4022,8 +4527,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
4022 |
$output .= 'Enable Path: ';
|
4023 |
$output .= $this->on_off( 'enable-object-prefix' );
|
4024 |
$output .= "\r\n";
|
|
|
4025 |
$output .= 'Custom Path: ';
|
4026 |
-
$output .=
|
4027 |
$output .= "\r\n";
|
4028 |
$output .= 'Use Year/Month: ';
|
4029 |
$output .= $this->on_off( 'use-yearmonth-folders' );
|
@@ -4033,15 +4539,47 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
4033 |
$output .= "\r\n";
|
4034 |
$output .= "\r\n";
|
4035 |
|
4036 |
-
$
|
4037 |
-
|
4038 |
-
$
|
4039 |
-
|
4040 |
-
|
4041 |
-
|
4042 |
-
|
4043 |
-
|
4044 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4045 |
$output .= 'Force HTTPS: ';
|
4046 |
$output .= $this->on_off( 'force-https' );
|
4047 |
$output .= "\r\n";
|
@@ -4206,6 +4744,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
4206 |
* @return string
|
4207 |
*/
|
4208 |
function get_acl_display_name( $acl ) {
|
|
|
4209 |
$acl = ( 'public-read' === $acl ) ? 'public' : $acl;
|
4210 |
|
4211 |
return ucwords( str_replace( '-', ' ', $acl ) );
|
@@ -4335,7 +4874,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
4335 |
* @return string
|
4336 |
*/
|
4337 |
function get_access_denied_notice_message( $single = true ) {
|
4338 |
-
if ( $this->
|
4339 |
return sprintf( __( '<a href="%s">Define your access keys</a> to enable write access to the bucket', 'amazon-s3-and-cloudfront' ), '#settings' );
|
4340 |
}
|
4341 |
|
@@ -4439,38 +4978,29 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
4439 |
*/
|
4440 |
public function media_counts( $skip_transient = false, $force = false ) {
|
4441 |
if ( $skip_transient || false === ( $attachment_counts = get_site_transient( 'as3cf_attachment_counts' ) ) ) {
|
4442 |
-
$table_prefixes
|
4443 |
-
$total
|
4444 |
-
$
|
4445 |
-
$
|
4446 |
-
$offloaded_paths = 0;
|
4447 |
-
$not_offloaded = 0;
|
4448 |
-
$not_offloaded_paths = 0;
|
4449 |
|
4450 |
foreach ( $table_prefixes as $blog_id => $table_prefix ) {
|
4451 |
$this->switch_to_blog( $blog_id );
|
4452 |
|
4453 |
-
$counts
|
4454 |
-
$total
|
4455 |
-
$
|
4456 |
-
$
|
4457 |
-
$offloaded_paths += $counts['offloaded_paths'];
|
4458 |
-
$not_offloaded += $counts['not_offloaded'];
|
4459 |
-
$not_offloaded_paths += $counts['not_offloaded_paths'];
|
4460 |
|
4461 |
$this->restore_current_blog();
|
4462 |
}
|
4463 |
|
4464 |
$attachment_counts = array(
|
4465 |
-
'total'
|
4466 |
-
'
|
4467 |
-
'
|
4468 |
-
'offloaded_paths' => $offloaded_paths,
|
4469 |
-
'not_offloaded' => $not_offloaded,
|
4470 |
-
'not_offloaded_paths' => $not_offloaded_paths,
|
4471 |
);
|
4472 |
|
4473 |
-
set_site_transient( 'as3cf_attachment_counts', $attachment_counts,
|
4474 |
}
|
4475 |
|
4476 |
return $attachment_counts;
|
@@ -4581,25 +5111,6 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
4581 |
exit( $exit_code );
|
4582 |
}
|
4583 |
|
4584 |
-
/**
|
4585 |
-
* Show the deprecated Domain option setting?
|
4586 |
-
*
|
4587 |
-
* @param null|string $domain
|
4588 |
-
*
|
4589 |
-
* @return bool
|
4590 |
-
*/
|
4591 |
-
public function show_deprecated_domain_setting( $domain = null ) {
|
4592 |
-
if ( is_null( $domain ) ) {
|
4593 |
-
$domain = $this->get_setting( 'domain' );
|
4594 |
-
}
|
4595 |
-
|
4596 |
-
if ( ! in_array( $domain, array( 'path', 'cloudfront' ) ) ) {
|
4597 |
-
return true;
|
4598 |
-
}
|
4599 |
-
|
4600 |
-
return apply_filters( 'as3cf_show_deprecated_domain_setting', false );
|
4601 |
-
}
|
4602 |
-
|
4603 |
/**
|
4604 |
* Upgrade the 'virtual host' / 'bucket as domain' setting to the
|
4605 |
* new CloudFront / Domain setting
|
@@ -4642,15 +5153,20 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
4642 |
}
|
4643 |
|
4644 |
/**
|
4645 |
-
* Potentially update path for
|
4646 |
*
|
4647 |
-
* @param string
|
|
|
|
|
4648 |
*
|
4649 |
* @return string
|
|
|
|
|
4650 |
*/
|
4651 |
-
public function
|
4652 |
-
if (
|
4653 |
-
$path_parts = apply_filters( 'as3cf_cloudfront_path_parts', explode( '/', $path ), $
|
|
|
4654 |
|
4655 |
if ( ! empty( $path_parts ) ) {
|
4656 |
$path = implode( '/', $path_parts );
|
@@ -4744,7 +5260,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
4744 |
$provider_object['key'] = $provider_object['path'];
|
4745 |
$provider_object['url'] = $this->get_attachment_provider_url( $id, $as3cf_item );
|
4746 |
|
4747 |
-
$acl = $as3cf_item->is_private() ? $this->
|
4748 |
$acl_info = array(
|
4749 |
'acl' => $acl,
|
4750 |
'name' => $this->get_acl_display_name( $acl ),
|
@@ -4756,7 +5272,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
4756 |
}
|
4757 |
|
4758 |
$provider_object['acl'] = $acl_info;
|
4759 |
-
$provider_object['region'] = $this->
|
4760 |
$provider_object['provider_name'] = $this->get_provider_service_name( $provider_object['provider'] );
|
4761 |
|
4762 |
return $provider_object;
|
@@ -4838,7 +5354,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
4838 |
*
|
4839 |
* @return array
|
4840 |
*/
|
4841 |
-
function add_media_row_actions(
|
4842 |
return $actions;
|
4843 |
}
|
4844 |
|
@@ -4927,19 +5443,64 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
4927 |
/**
|
4928 |
* Get ACL for intermediate size.
|
4929 |
*
|
4930 |
-
* @param int
|
4931 |
-
* @param string
|
|
|
|
|
4932 |
*
|
4933 |
-
* @return string
|
4934 |
*/
|
4935 |
-
public function get_acl_for_intermediate_size( $attachment_id, $size ) {
|
4936 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4937 |
|
4938 |
-
|
4939 |
-
|
|
|
4940 |
}
|
4941 |
|
4942 |
-
|
|
|
4943 |
}
|
4944 |
|
4945 |
/**
|
@@ -5046,7 +5607,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
5046 |
);
|
5047 |
$this->notices->add_notice( $message, $args );
|
5048 |
|
5049 |
-
if ( is_a( $this->
|
5050 |
// Have access keys been defined in still active AWS plugin's database settings?
|
5051 |
$aws_settings = get_site_option( 'aws_settings' );
|
5052 |
|
@@ -5115,4 +5676,30 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
|
5115 |
|
5116 |
return $data;
|
5117 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5118 |
}
|
1 |
<?php
|
2 |
|
3 |
use DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item;
|
4 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Delivery\Another_CDN;
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Delivery\AWS_CloudFront;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Delivery\Cloudflare;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Delivery\Delivery_Provider;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Delivery\DigitalOcean_Spaces_CDN;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Delivery\GCP_CDN;
|
10 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Delivery\KeyCDN;
|
11 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Delivery\Other;
|
12 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Delivery\StackPath;
|
13 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Delivery\Storage;
|
14 |
use DeliciousBrains\WP_Offload_Media\Providers\Provider;
|
15 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Storage\AWS_Provider;
|
16 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Storage\DigitalOcean_Provider;
|
17 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Storage\GCP_Provider;
|
18 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Storage\Null_Provider;
|
19 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Storage\Storage_Provider;
|
20 |
+
use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade;
|
21 |
use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_Content_Replace_URLs;
|
22 |
use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_EDD_Replace_URLs;
|
23 |
use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_File_Sizes;
|
30 |
class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
|
31 |
|
32 |
/**
|
33 |
+
* @var Storage_Provider
|
34 |
*/
|
35 |
+
private $storage_provider;
|
36 |
|
37 |
/**
|
38 |
+
* @var Storage_Provider
|
39 |
*/
|
40 |
private $provider_client;
|
41 |
|
44 |
*/
|
45 |
private $provider_client_region;
|
46 |
|
47 |
+
/**
|
48 |
+
* @var Delivery_Provider
|
49 |
+
*/
|
50 |
+
private $delivery_provider;
|
51 |
+
|
52 |
/**
|
53 |
* @var array
|
54 |
*/
|
102 |
/**
|
103 |
* @var string
|
104 |
*/
|
105 |
+
protected static $default_storage_provider = 'aws';
|
106 |
+
|
107 |
+
/**
|
108 |
+
* @var string
|
109 |
+
*/
|
110 |
+
protected static $default_delivery_provider = 'storage';
|
111 |
+
|
112 |
+
/**
|
113 |
+
* @var array Known storage provider classes.
|
114 |
+
*/
|
115 |
+
protected static $storage_provider_classes = array();
|
116 |
|
117 |
/**
|
118 |
+
* @var array Known delivery provider classes.
|
119 |
*/
|
120 |
+
protected static $delivery_provider_classes = array();
|
121 |
|
122 |
/**
|
123 |
* @var AS3CF_Plugin_Compatibility
|
165 |
$this->plugin_title = __( 'Offload Media Lite', 'amazon-s3-and-cloudfront' );
|
166 |
$this->plugin_menu_title = __( 'Offload Media Lite', 'amazon-s3-and-cloudfront' );
|
167 |
|
168 |
+
static::$storage_provider_classes = apply_filters( 'as3cf_storage_provider_classes', array(
|
169 |
+
AWS_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Storage\AWS_Provider',
|
170 |
+
DigitalOcean_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Storage\DigitalOcean_Provider',
|
171 |
+
GCP_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Storage\GCP_Provider',
|
172 |
+
) );
|
173 |
+
|
174 |
+
static::$delivery_provider_classes = apply_filters( 'as3cf_delivery_provider_classes', array(
|
175 |
+
AWS_CloudFront::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\AWS_CloudFront',
|
176 |
+
DigitalOcean_Spaces_CDN::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\DigitalOcean_Spaces_CDN',
|
177 |
+
GCP_CDN::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\GCP_CDN',
|
178 |
+
Another_CDN::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\Another_CDN',
|
179 |
+
// Sub Options of Another CDN.
|
180 |
+
Cloudflare::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\Cloudflare',
|
181 |
+
KeyCDN::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\KeyCDN',
|
182 |
+
StackPath::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\StackPath',
|
183 |
+
Other::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\Other',
|
184 |
+
// Fallback to raw storage URLs.
|
185 |
+
Storage::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\Delivery\Storage',
|
186 |
+
) );
|
187 |
|
188 |
Media_Library_Item::init_cache();
|
189 |
|
190 |
+
$this->set_storage_provider();
|
191 |
+
$this->set_delivery_provider();
|
192 |
|
193 |
// Bundled SDK may require AWS setup before data migrations.
|
194 |
$this->handle_aws_access_key_migration();
|
226 |
|
227 |
// Rewriting URLs, doesn't depend on plugin being setup
|
228 |
add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 99, 2 );
|
229 |
+
add_filter( 'wp_get_attachment_image_attributes', array( $this, 'wp_get_attachment_image_attributes' ), 99, 3 );
|
230 |
add_filter( 'get_image_tag', array( $this, 'maybe_encode_get_image_tag' ), 99, 6 );
|
231 |
add_filter( 'wp_get_attachment_image_src', array( $this, 'maybe_encode_wp_get_attachment_image_src' ), 99, 4 );
|
232 |
add_filter( 'wp_prepare_attachment_for_js', array( $this, 'maybe_encode_wp_prepare_attachment_for_js', ), 99, 3 );
|
260 |
|
261 |
// Register storage provider scripts and styles
|
262 |
$this->register_storage_provider_assets();
|
263 |
+
|
264 |
+
// Register delivery provider scripts and styles
|
265 |
+
$this->register_delivery_provider_assets();
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* @return Storage_Provider
|
270 |
+
*/
|
271 |
+
public function get_storage_provider() {
|
272 |
+
return $this->storage_provider;
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* @param Storage_Provider|string|null $storage_provider
|
277 |
+
*
|
278 |
+
* @throws Exception
|
279 |
+
*/
|
280 |
+
public function set_storage_provider( $storage_provider = null ) {
|
281 |
+
if ( empty( $storage_provider ) ) {
|
282 |
+
$storage_provider = $this->get_core_setting( 'provider', static::get_default_storage_provider() );
|
283 |
+
}
|
284 |
+
|
285 |
+
// Specified provider does not exist, fall back to default.
|
286 |
+
if ( is_string( $storage_provider ) && empty( self::$storage_provider_classes[ $storage_provider ] ) ) {
|
287 |
+
$storage_provider = static::get_default_storage_provider();
|
288 |
+
}
|
289 |
+
|
290 |
+
if ( is_string( $storage_provider ) && ! empty( self::$storage_provider_classes[ $storage_provider ] ) ) {
|
291 |
+
$storage_provider = new self::$storage_provider_classes[ $storage_provider ]( $this );
|
292 |
+
}
|
293 |
+
|
294 |
+
if ( ! empty( $storage_provider ) && ! is_string( $storage_provider ) ) {
|
295 |
+
$this->storage_provider = $storage_provider;
|
296 |
+
} else {
|
297 |
+
// We really tried, we really did, but we're going to have to let things fail.
|
298 |
+
$this->storage_provider = null;
|
299 |
+
}
|
300 |
}
|
301 |
|
302 |
/**
|
303 |
+
* @return Delivery_Provider
|
304 |
*/
|
305 |
+
public function get_delivery_provider() {
|
306 |
+
return $this->delivery_provider;
|
307 |
}
|
308 |
|
309 |
/**
|
310 |
+
* @param Delivery_Provider|string|null $delivery_provider
|
311 |
*
|
312 |
* @throws Exception
|
313 |
*/
|
314 |
+
public function set_delivery_provider( $delivery_provider = null ) {
|
315 |
+
if ( empty( $delivery_provider ) ) {
|
316 |
+
$delivery_provider = $this->get_core_setting( 'delivery-provider', static::get_default_delivery_provider() );
|
317 |
+
}
|
318 |
+
|
319 |
+
// Specified provider does not exist, fall back to default.
|
320 |
+
if ( is_string( $delivery_provider ) && empty( self::$delivery_provider_classes[ $delivery_provider ] ) ) {
|
321 |
+
$delivery_provider = static::get_default_delivery_provider();
|
322 |
}
|
323 |
|
324 |
+
if ( is_string( $delivery_provider ) && ! empty( self::$delivery_provider_classes[ $delivery_provider ] ) ) {
|
325 |
+
$delivery_provider = new self::$delivery_provider_classes[ $delivery_provider ]( $this );
|
326 |
}
|
327 |
|
328 |
+
if ( ! empty( $delivery_provider ) && ! is_string( $delivery_provider ) ) {
|
329 |
+
$this->delivery_provider = $delivery_provider;
|
330 |
+
} else {
|
331 |
+
// We really tried, we really did, but we're going to have to let things fail.
|
332 |
+
$this->delivery_provider = null;
|
333 |
+
}
|
334 |
}
|
335 |
|
336 |
/**
|
337 |
* Returns the currently supported Providers.
|
338 |
*
|
339 |
+
* @param string $type Which type of provider, "storage" or "delivery".
|
340 |
+
*
|
341 |
* @return array
|
342 |
*/
|
343 |
+
public function get_provider_classes( $type ) {
|
344 |
+
switch ( $type ) {
|
345 |
+
case 'storage':
|
346 |
+
$providers = self::$storage_provider_classes;
|
347 |
+
break;
|
348 |
+
case 'delivery':
|
349 |
+
$providers = self::$delivery_provider_classes;
|
350 |
+
break;
|
351 |
+
default:
|
352 |
+
$providers = array(); // Error.
|
353 |
+
}
|
354 |
+
|
355 |
+
return $providers;
|
356 |
}
|
357 |
|
358 |
/**
|
359 |
* Returns provider class name for given key.
|
360 |
*
|
361 |
* @param string $key_name
|
362 |
+
* @param string $type
|
363 |
*
|
364 |
+
* @return Provider|null
|
365 |
*/
|
366 |
+
public function get_provider_class( $key_name, $type = 'storage' ) {
|
367 |
+
if ( empty( $type ) ) {
|
368 |
+
$type = 'storage';
|
369 |
+
}
|
370 |
+
$classes = $this->get_provider_classes( $type );
|
371 |
|
372 |
return empty( $classes[ $key_name ] ) ? null : $classes[ $key_name ];
|
373 |
}
|
376 |
* Provider name for given key.
|
377 |
*
|
378 |
* @param string $key_name
|
379 |
+
* @param string $type
|
380 |
*
|
381 |
* @return string
|
382 |
*/
|
383 |
+
public function get_provider_name( $key_name, $type = 'storage' ) {
|
384 |
+
if ( empty( $type ) ) {
|
385 |
+
$type = 'storage';
|
386 |
+
}
|
387 |
+
$class = $this->get_provider_class( $key_name, $type );
|
388 |
|
389 |
return empty( $class ) ? __( 'Unknown', 'amazon-s3-and-cloudfront' ) : $class::get_provider_name();
|
390 |
}
|
393 |
* Provider & Service name for given key.
|
394 |
*
|
395 |
* @param string $key_name
|
396 |
+
* @param string $type
|
397 |
*
|
398 |
* @return string
|
399 |
*/
|
400 |
+
public function get_provider_service_name( $key_name, $type = 'storage' ) {
|
401 |
+
if ( empty( $type ) ) {
|
402 |
+
$type = 'storage';
|
403 |
+
}
|
404 |
+
$class = $this->get_provider_class( $key_name, $type );
|
405 |
|
406 |
return empty( $class ) ? __( 'Unknown', 'amazon-s3-and-cloudfront' ) : $class::get_provider_service_name();
|
407 |
}
|
465 |
'key' => $key,
|
466 |
'disabled' => false,
|
467 |
'disabled_attr' => '',
|
468 |
+
'tr_class' => 'as3cf-settings-container ' . str_replace( '_', '-', $this->get_plugin_prefix() . '-' . $key . '-container' ),
|
469 |
'setting_msg' => '',
|
470 |
'is_defined' => false,
|
471 |
);
|
633 |
return $aws_secret_access_key;
|
634 |
}
|
635 |
|
636 |
+
// Delivery Provider since 2.4.
|
637 |
+
if ( 'delivery-provider' === $key && ! isset( $settings['delivery-provider'] ) ) {
|
638 |
+
if ( ! empty( $this->get_setting( 'delivery-domain' ) ) ) {
|
639 |
+
// Try and guess delivery provider from delivery domain, default to "other" if domain unknown.
|
640 |
+
$delivery_provider = 'other';
|
641 |
+
$domain = $this->get_setting( 'cloudfront' );
|
642 |
+
|
643 |
+
if ( strstr( $domain, '.cloudfront.net' ) ) {
|
644 |
+
$delivery_provider = AWS_CloudFront::get_provider_key_name();
|
645 |
+
} elseif ( strstr( $domain, '.cdn.digitaloceanspaces.com' ) ) {
|
646 |
+
$delivery_provider = DigitalOcean_Spaces_CDN::get_provider_key_name();
|
647 |
+
} elseif (
|
648 |
+
'gcp' === $this->get_storage_provider()->get_provider_key_name() &&
|
649 |
+
false === strstr( $domain, $this->get_storage_provider()->get_domain() )
|
650 |
+
) {
|
651 |
+
$delivery_provider = GCP_CDN::get_provider_key_name();
|
652 |
+
}
|
653 |
+
} else {
|
654 |
+
// No delivery provider, fallback to default, which should equate to delivery via storage provider's defaults.
|
655 |
+
$delivery_provider = $default;
|
656 |
+
}
|
657 |
+
|
658 |
+
return $delivery_provider;
|
659 |
+
}
|
660 |
+
|
661 |
+
// Delivery Domain since 2.4.
|
662 |
+
if ( 'enable-delivery-domain' === $key && ! isset( $settings['enable-delivery-domain'] ) ) {
|
663 |
+
if ( ! empty( $this->get_setting( 'delivery-domain' ) ) ) {
|
664 |
+
return true;
|
665 |
+
}
|
666 |
+
|
667 |
+
return false;
|
668 |
+
}
|
669 |
+
|
670 |
+
// Delivery Domain since 2.4.
|
671 |
+
if ( 'delivery-domain' === $key && ! isset( $settings['delivery-domain'] ) ) {
|
672 |
+
if ( 'cloudfront' === $this->get_setting( 'domain' ) && ! empty( $this->get_setting( 'cloudfront' ) ) ) {
|
673 |
+
$delivery_domain = $this->get_setting( 'cloudfront' );
|
674 |
+
} else {
|
675 |
+
// No delivery domain, fallback to storage provider's default domain.
|
676 |
+
$delivery_domain = '';
|
677 |
+
}
|
678 |
+
|
679 |
+
return $delivery_domain;
|
680 |
+
}
|
681 |
+
|
682 |
$value = parent::get_setting( $key, $default );
|
683 |
|
684 |
// Provider
|
691 |
return $bucket;
|
692 |
}
|
693 |
|
694 |
+
// Use Bucket ACLs
|
695 |
+
if ( null !== ( $use_bucket_acls = $this->get_setting_use_bucket_acls( $settings, $key, null ) ) ) {
|
696 |
+
return $use_bucket_acls;
|
697 |
+
}
|
698 |
+
|
699 |
return apply_filters( 'as3cf_setting_' . $key, $value );
|
700 |
}
|
701 |
|
753 |
|
754 |
// Region of bucket translation
|
755 |
if ( 'region' === $key && isset( $settings['region'] ) ) {
|
756 |
+
return $this->get_storage_provider()->sanitize_region( $settings['region'] );
|
757 |
}
|
758 |
|
759 |
return false;
|
760 |
}
|
761 |
|
762 |
/**
|
763 |
+
* Get the bucket and if a constant remove from database and clear region
|
764 |
*
|
765 |
* @param string $key
|
766 |
* @param string $value
|
810 |
*/
|
811 |
public function bucket_changed() {
|
812 |
$this->remove_setting( 'region' );
|
813 |
+
$this->remove_setting( 'use-bucket-acls' );
|
814 |
$this->save_settings();
|
815 |
}
|
816 |
|
817 |
+
/**
|
818 |
+
* Get the derived use-bucket-acls setting
|
819 |
+
*
|
820 |
+
* @param array $settings
|
821 |
+
* @param string $key
|
822 |
+
* @param mixed $default
|
823 |
+
*
|
824 |
+
* @return bool|null
|
825 |
+
*/
|
826 |
+
public function get_setting_use_bucket_acls( $settings, $key, $default ) {
|
827 |
+
if ( 'use-bucket-acls' === $key && isset( $settings['use-bucket-acls'] ) ) {
|
828 |
+
return $settings['use-bucket-acls'];
|
829 |
+
}
|
830 |
+
|
831 |
+
if ( 'use-bucket-acls' === $key && ! isset( $settings['use-bucket-acls'] ) ) {
|
832 |
+
if ( ! $this->get_storage_provider()->block_public_access_allowed() ) {
|
833 |
+
// Got no choice, must use ACLs.
|
834 |
+
parent::set_setting( 'use-bucket-acls', true );
|
835 |
+
$this->save_settings();
|
836 |
+
|
837 |
+
return true;
|
838 |
+
}
|
839 |
+
|
840 |
+
$bucket = $this->get_setting( 'bucket' );
|
841 |
+
$region = $this->get_setting( 'region' );
|
842 |
+
|
843 |
+
try {
|
844 |
+
$public_access_blocked = $this->get_provider_client( $region )->public_access_blocked( $bucket );
|
845 |
+
} catch ( Exception $e ) {
|
846 |
+
$public_access_blocked = null;
|
847 |
+
}
|
848 |
+
|
849 |
+
// At present, we default to using ACLs if public access to bucket status unknown.
|
850 |
+
if ( empty( $public_access_blocked ) || true !== $public_access_blocked ) {
|
851 |
+
$use_bucket_acls = true;
|
852 |
+
} else {
|
853 |
+
$use_bucket_acls = false;
|
854 |
+
}
|
855 |
+
|
856 |
+
parent::set_setting( 'use-bucket-acls', $use_bucket_acls );
|
857 |
+
$this->save_settings();
|
858 |
+
|
859 |
+
return $use_bucket_acls;
|
860 |
+
}
|
861 |
+
|
862 |
+
return $default;
|
863 |
+
}
|
864 |
+
|
865 |
/**
|
866 |
* Filter in defined settings with sensible defaults.
|
867 |
*
|
947 |
$defined_settings = ! empty( $defined_settings ) ? $defined_settings : $this->get_defined_settings();
|
948 |
$whitelisted_settings = $this->get_settings_whitelist();
|
949 |
$settings_to_skip = array(
|
950 |
+
'access-key-id',
|
951 |
+
'secret-access-key',
|
952 |
+
'key-file-path',
|
953 |
+
'key-file',
|
954 |
+
'use-server-roles',
|
955 |
'bucket',
|
956 |
'region',
|
957 |
+
'delivery-provider-service-name',
|
958 |
+
'use-bucket-acls',
|
959 |
'virtual-host',
|
960 |
+
'domain', // Legacy
|
961 |
+
'cloudfront', // Legacy
|
962 |
);
|
963 |
|
964 |
foreach ( $whitelisted_settings as $setting ) {
|
966 |
continue;
|
967 |
}
|
968 |
|
969 |
+
if (
|
970 |
+
'object-prefix' === $setting &&
|
971 |
+
isset( $defined_settings['enable-object-prefix'] ) &&
|
972 |
+
empty( $defined_settings['enable-object-prefix'] )
|
973 |
+
) {
|
974 |
+
continue;
|
975 |
}
|
976 |
|
977 |
+
if (
|
978 |
+
in_array( $setting, array( 'enable-delivery-domain', 'delivery-domain' ) ) &&
|
979 |
+
! $this->get_delivery_provider()->delivery_domain_allowed()
|
980 |
+
) {
|
981 |
+
continue;
|
982 |
+
}
|
983 |
+
|
984 |
+
if (
|
985 |
+
'delivery-domain' === $setting &&
|
986 |
+
isset( $defined_settings['enable-delivery-domain'] ) &&
|
987 |
+
empty( $defined_settings['enable-delivery-domain'] )
|
988 |
+
) {
|
989 |
+
continue;
|
990 |
+
}
|
991 |
+
|
992 |
+
if (
|
993 |
+
in_array( $setting, array( 'enable-signed-urls', 'signed-urls-key-id', 'signed-urls-key-file-path', 'signed-urls-object-prefix' ) ) &&
|
994 |
+
! $this->get_delivery_provider()->use_signed_urls_key_file_allowed()
|
995 |
+
) {
|
996 |
+
continue;
|
997 |
+
}
|
998 |
+
|
999 |
+
if (
|
1000 |
+
in_array( $setting, array( 'signed-urls-key-id', 'signed-urls-key-file-path', 'signed-urls-object-prefix' ) ) &&
|
1001 |
+
isset( $defined_settings['enable-signed-urls'] ) && empty( $defined_settings['enable-signed-urls'] )
|
1002 |
+
) {
|
1003 |
+
continue;
|
1004 |
}
|
1005 |
|
1006 |
if ( ! isset( $defined_settings[ $setting ] ) ) {
|
1113 |
* @return string
|
1114 |
*/
|
1115 |
function get_url_preview( $escape = true, $suffix = 'photo.jpg' ) {
|
1116 |
+
$as3cf_item = new Media_Library_Item(
|
1117 |
+
$this->get_storage_provider()->get_provider_key_name(),
|
1118 |
+
$this->get_setting( 'region' ),
|
1119 |
+
$this->get_setting( 'bucket' ),
|
1120 |
+
AS3CF_Utils::trailingslash_prefix( $this->get_file_prefix() ) . $suffix,
|
1121 |
+
false,
|
1122 |
+
null,
|
1123 |
+
null
|
1124 |
+
);
|
1125 |
|
1126 |
+
$url = $this->get_attachment_provider_url( null, $as3cf_item );
|
1127 |
|
1128 |
+
if ( is_wp_error( $url ) ) {
|
1129 |
+
return '';
|
1130 |
+
}
|
1131 |
|
1132 |
// Replace hyphens with non breaking hyphens for formatting
|
1133 |
if ( $escape ) {
|
1232 |
* to cope with possible different regions
|
1233 |
*/
|
1234 |
function remove_attachment_files_from_provider( $post_id, Media_Library_Item $as3cf_item, $include_backups = true, $log_error = false, $return_on_error = false, $force_new_provider_client = false ) {
|
1235 |
+
$prefix = $as3cf_item->normalized_path_dir();
|
1236 |
+
$private_prefix = $as3cf_item->private_prefix();
|
1237 |
+
$paths = AS3CF_Utils::get_attachment_file_paths( $post_id, false, false, $include_backups );
|
1238 |
+
$paths = apply_filters( 'as3cf_remove_attachment_paths', $paths, $post_id, $as3cf_item, $include_backups );
|
1239 |
|
1240 |
// If another item in current site shares full size *local* paths, only remove remote files not referenced by duplicates.
|
1241 |
// We reference local paths as they should be reflected one way or another remotely, including backups.
|
1260 |
|
1261 |
$objects_to_remove = array();
|
1262 |
|
1263 |
+
foreach ( $paths as $size => $path ) {
|
1264 |
$objects_to_remove[] = array(
|
1265 |
+
'Key' => $as3cf_item->key( wp_basename( $path ) ),
|
1266 |
);
|
1267 |
}
|
1268 |
|
1429 |
$post_id,
|
1430 |
$duplicate_item->source_path(),
|
1431 |
wp_basename( $duplicate_item->original_source_path() ),
|
1432 |
+
$duplicate_item->extra_info()
|
1433 |
);
|
1434 |
|
1435 |
$old_item->save();
|
1486 |
return $this->return_upload_error( $error_msg, $return_metadata );
|
1487 |
}
|
1488 |
|
1489 |
+
$acl = $this->get_storage_provider()->get_default_acl();
|
1490 |
|
1491 |
// check the attachment already exists in provider, eg. edit or restore image
|
1492 |
if ( $old_item ) {
|
1497 |
|
1498 |
// Use private ACL if existing offload is already private.
|
1499 |
if ( $old_item->is_private() ) {
|
1500 |
+
$acl = $this->get_storage_provider()->get_private_acl();
|
1501 |
}
|
1502 |
|
1503 |
// use existing prefix
|
1504 |
$prefix = $old_item->normalized_path_dir();
|
1505 |
+
// use existing private prefix
|
1506 |
+
$private_prefix = $old_item->private_prefix();
|
1507 |
// use existing bucket
|
1508 |
$bucket = $old_item->bucket();
|
1509 |
// get existing region
|
1512 |
$original_filename = wp_basename( $old_item->original_source_path() );
|
1513 |
} else {
|
1514 |
// derive prefix from various settings
|
1515 |
+
$prefix = $this->get_new_attachment_prefix( $post_id, $data );
|
1516 |
+
|
1517 |
+
// maybe set a private prefix.
|
1518 |
+
if ( $this->private_prefix_enabled() ) {
|
1519 |
+
$private_prefix = AS3CF_Utils::trailingslash_prefix( $this->get_setting( 'signed-urls-object-prefix', '' ) );
|
1520 |
+
} else {
|
1521 |
+
$private_prefix = '';
|
1522 |
+
}
|
1523 |
|
1524 |
// use bucket from settings
|
1525 |
$bucket = $this->get_setting( 'bucket' );
|
1532 |
$original_filename = empty( $data['original_image'] ) ? null : $data['original_image'];
|
1533 |
}
|
1534 |
|
1535 |
+
$acl = apply_filters( 'wps3_upload_acl', $acl, $type, $data, $post_id, $this ); // Old naming convention, will be deprecated soon
|
1536 |
+
$acl = apply_filters( 'as3cf_upload_acl', $acl, $data, $post_id );
|
1537 |
+
$is_private = ( ! empty( $acl ) && $this->get_storage_provider()->get_private_acl() === $acl ) ? true : false;
|
1538 |
|
1539 |
$args = array(
|
1540 |
'Bucket' => $bucket,
|
1541 |
'Key' => $prefix . $file_name,
|
1542 |
'SourceFile' => $file_path,
|
|
|
1543 |
'ContentType' => $type,
|
1544 |
'CacheControl' => 'max-age=31536000',
|
1545 |
'Expires' => date( 'D, d M Y H:i:s O', time() + 31536000 ),
|
1546 |
);
|
1547 |
|
1548 |
+
$image_size = wp_attachment_is_image( $post_id ) ? 'full' : '';
|
1549 |
+
|
1550 |
+
// Only set ACL if actually required, some storage provider and bucket settings disable changing ACL.
|
1551 |
+
if ( ! empty( $acl ) && $this->use_acl_for_intermediate_size( $post_id, $image_size, $bucket ) ) {
|
1552 |
+
$args['ACL'] = $acl;
|
1553 |
+
}
|
1554 |
+
|
1555 |
// TODO: Remove GZIP functionality.
|
1556 |
// Handle gzip on supported items
|
1557 |
if ( $this->should_gzip_file( $file_path, $type ) && false !== ( $gzip_body = gzencode( file_get_contents( $file_path ) ) ) ) {
|
1561 |
$args['ContentEncoding'] = 'gzip';
|
1562 |
}
|
1563 |
|
1564 |
+
$args = apply_filters( 'as3cf_object_meta', $args, $post_id, $image_size, false );
|
1565 |
+
|
1566 |
+
$provider = $this->get_storage_provider()->get_provider_key_name();
|
1567 |
+
$region = $bucket !== $args['Bucket'] ? $this->get_bucket_region( $args['Bucket'], true ) : $region;
|
1568 |
+
$is_private = ( ! empty( $args['ACL'] ) && $this->get_storage_provider()->get_private_acl() === $args['ACL'] ) ? true : $is_private;
|
1569 |
+
$extra_info = empty( $old_item ) ? array( 'private_prefix' => $private_prefix ) : $old_item->extra_info();
|
1570 |
+
$item_id = empty( $old_item ) ? null : $old_item->id();
|
1571 |
+
|
1572 |
+
// Protect against filter use and only set ACL if actually required, some storage provider and bucket settings disable changing ACL.
|
1573 |
+
if ( isset( $args['ACL'] ) && ! $this->use_acl_for_intermediate_size( $post_id, $image_size, $bucket ) ) {
|
1574 |
+
unset( $args['ACL'] );
|
1575 |
+
}
|
1576 |
|
1577 |
+
$as3cf_item = new Media_Library_Item( $provider, $region, $args['Bucket'], $args['Key'], $is_private, $post_id, $file_path, $original_filename, $extra_info, $item_id );
|
|
|
|
|
|
|
|
|
1578 |
|
1579 |
+
// With public path and private prefix now in place, we can set the final path for the full sized file.
|
1580 |
+
$size_private_prefix = $as3cf_item->is_private() ? $as3cf_item->private_prefix() : '';
|
1581 |
+
$args['Key'] = $size_private_prefix . $args['Key'];
|
1582 |
|
1583 |
+
do_action( 'as3cf_upload_attachment_pre_remove', $post_id, $as3cf_item, $as3cf_item->normalized_path_dir(), $args );
|
1584 |
|
1585 |
$new_offloads = array();
|
1586 |
$files_to_remove = array();
|
1609 |
|
1610 |
foreach ( $file_paths as $size => $file_path ) {
|
1611 |
if ( ! in_array( $file_path, $files_to_remove ) ) {
|
1612 |
+
$acl = apply_filters( 'as3cf_upload_acl_sizes', $this->get_storage_provider()->get_default_acl(), $size, $post_id, $data );
|
1613 |
|
1614 |
+
if ( ! empty( $acl ) && $this->get_storage_provider()->get_private_acl() === $acl ) {
|
1615 |
+
$private_sizes[] = $size;
|
1616 |
+
}
|
1617 |
+
|
1618 |
+
// Public path, modified to private in next block as needed.
|
1619 |
$additional_images[ $size ] = array(
|
1620 |
+
'Key' => $as3cf_item->normalized_path_dir() . wp_basename( $file_path ),
|
1621 |
'SourceFile' => $file_path,
|
|
|
1622 |
'ContentType' => $this->get_mime_type( $file_path ),
|
1623 |
);
|
1624 |
|
1625 |
+
// Only set ACL if actually required, some storage provider and bucket settings disable changing ACL.
|
1626 |
+
if ( ! empty( $acl ) && $this->use_acl_for_intermediate_size( $post_id, $size, $bucket, $as3cf_item ) ) {
|
1627 |
+
$additional_images[ $size ]['ACL'] = $acl;
|
1628 |
}
|
1629 |
}
|
1630 |
}
|
1639 |
|
1640 |
$args = apply_filters( 'as3cf_object_meta', array_merge( $args, $image ), $post_id, $size, false );
|
1641 |
|
1642 |
+
// Is size private and therefore needs to be in private prefix?
|
1643 |
+
$size_private_prefix = in_array( $size, $private_sizes ) ? $as3cf_item->private_prefix() : '';
|
1644 |
+
$args['Key'] = $size_private_prefix . $args['Key'];
|
1645 |
+
|
1646 |
+
// Protect against filter use and only set ACL if actually required, some storage provider and bucket settings disable changing ACL.
|
1647 |
+
if ( isset( $args['ACL'] ) && ! $this->use_acl_for_intermediate_size( $post_id, $size, $bucket, $as3cf_item ) ) {
|
1648 |
+
unset( $args['ACL'] );
|
1649 |
+
}
|
1650 |
+
|
1651 |
if ( ! file_exists( $args['SourceFile'] ) ) {
|
1652 |
if ( ! $duplicate ) {
|
1653 |
$upload_errors[] = $this->return_upload_error( sprintf( __( 'File %s does not exist', 'amazon-s3-and-cloudfront' ), $args['SourceFile'] ) );
|
1678 |
$as3cf_item->source_id(),
|
1679 |
$as3cf_item->source_path(),
|
1680 |
wp_basename( $image['SourceFile'] ),
|
1681 |
+
$as3cf_item->extra_info(),
|
1682 |
$as3cf_item->id()
|
1683 |
);
|
1684 |
}
|
1718 |
|
1719 |
// Additional image sizes have custom ACLs, record them.
|
1720 |
if ( ! empty( $private_sizes ) ) {
|
1721 |
+
$extra_info = $as3cf_item->extra_info();
|
1722 |
+
$extra_info['private_sizes'] = $private_sizes;
|
1723 |
+
|
1724 |
$as3cf_item = new Media_Library_Item(
|
1725 |
$as3cf_item->provider(),
|
1726 |
$as3cf_item->region(),
|
1730 |
$as3cf_item->source_id(),
|
1731 |
$as3cf_item->source_path(),
|
1732 |
wp_basename( $as3cf_item->original_source_path() ),
|
1733 |
+
$extra_info,
|
1734 |
$as3cf_item->id()
|
1735 |
);
|
1736 |
}
|
2166 |
* TODO: Performance - cache / static var by param.
|
2167 |
*/
|
2168 |
function is_plugin_setup( $with_credentials = false ) {
|
2169 |
+
if ( $with_credentials && $this->get_storage_provider()->needs_access_keys() ) {
|
2170 |
// AWS not configured
|
2171 |
return false;
|
2172 |
}
|
2195 |
* @param array $headers Header overrides for request
|
2196 |
* @param bool $skip_rewrite_check
|
2197 |
*
|
2198 |
+
* @return string|bool|WP_Error
|
2199 |
*/
|
2200 |
public function get_secure_attachment_url( $post_id, $expires = null, $size = null, $headers = array(), $skip_rewrite_check = false ) {
|
2201 |
if ( is_null( $expires ) ) {
|
2279 |
}
|
2280 |
|
2281 |
/**
|
2282 |
+
* Get attachment's new public prefix path for current settings.
|
2283 |
*
|
2284 |
+
* @param int $post_id Attachment ID
|
2285 |
+
* @param array $metadata Optional attachment metadata
|
|
|
|
|
|
|
|
|
|
|
|
|
2286 |
*
|
2287 |
+
* @return string
|
2288 |
+
*/
|
2289 |
+
public function get_new_attachment_prefix( $post_id, $metadata = null ) {
|
2290 |
+
if ( empty( $metadata ) ) {
|
2291 |
+
$metadata = wp_get_attachment_metadata( $post_id, true );
|
2292 |
+
}
|
2293 |
+
|
2294 |
+
$time = $this->get_attachment_folder_year_month( $post_id, $metadata );
|
2295 |
+
|
2296 |
+
return $this->get_file_prefix( $time );
|
2297 |
+
}
|
2298 |
+
|
2299 |
+
/**
|
2300 |
+
* Get the url of the file from provider
|
2301 |
+
*
|
2302 |
+
* @param int $post_id Post ID of the attachment, required.
|
2303 |
+
* @param int|null $expires Seconds for the link to live, optional.
|
2304 |
+
* @param string|null $size Size of the image to get, optional.
|
2305 |
+
* @param array|null $meta Pre retrieved _wp_attachment_metadata for the attachment, optional.
|
2306 |
+
* @param array $headers Header overrides for request, optional.
|
2307 |
+
* @param bool $skip_rewrite_check Always return the URL regardless of the 'Rewrite File URLs' setting, optional, default: false.
|
2308 |
+
* Useful for the EDD and Woo addons to not break download URLs when the option is disabled.
|
2309 |
+
*
|
2310 |
+
* @return string|bool|WP_Error
|
2311 |
*/
|
2312 |
public function get_attachment_url( $post_id, $expires = null, $size = null, $meta = null, $headers = array(), $skip_rewrite_check = false ) {
|
2313 |
if ( ! ( $as3cf_item = $this->is_attachment_served_by_provider( $post_id, $skip_rewrite_check ) ) ) {
|
2397 |
* @return string|WP_Error
|
2398 |
*/
|
2399 |
public function get_attachment_provider_url( $post_id, Media_Library_Item $as3cf_item, $expires = null, $size = null, $meta = null, $headers = array() ) {
|
2400 |
+
$size = AS3CF_Utils::maybe_convert_size_to_string( $post_id, $size );
|
2401 |
|
2402 |
+
// Is a signed expiring URL required for the requested object?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2403 |
if ( is_null( $expires ) ) {
|
2404 |
if ( is_null( $size ) && $as3cf_item->is_private() ) {
|
2405 |
// Full size URL private
|
2412 |
}
|
2413 |
}
|
2414 |
|
2415 |
+
$item_path = $as3cf_item->path();
|
2416 |
+
|
2417 |
if ( ! is_null( $size ) ) {
|
2418 |
if ( is_null( $meta ) ) {
|
2419 |
$meta = get_post_meta( $post_id, '_wp_attachment_metadata', true );
|
2431 |
}
|
2432 |
}
|
2433 |
|
2434 |
+
$scheme = $this->get_url_scheme();
|
2435 |
+
$enable_delivery_domain = $this->get_delivery_provider()->delivery_domain_allowed() ? $this->get_setting( 'enable-delivery-domain' ) : false;
|
2436 |
+
$delivery_domain = $this->get_setting( 'delivery-domain' );
|
2437 |
+
|
2438 |
+
if ( ! $enable_delivery_domain || empty( $delivery_domain ) ) {
|
2439 |
+
$region = $as3cf_item->region();
|
2440 |
+
|
2441 |
+
if ( is_wp_error( $region ) ) {
|
2442 |
+
return $region;
|
2443 |
+
}
|
2444 |
+
|
2445 |
+
$delivery_domain = $this->get_storage_provider()->get_url_domain( $as3cf_item->bucket(), $region, $expires );
|
2446 |
+
} else {
|
2447 |
+
$delivery_domain = AS3CF_Utils::sanitize_custom_domain( $delivery_domain );
|
2448 |
+
}
|
2449 |
|
2450 |
if ( ! is_null( $expires ) && $this->is_plugin_setup( true ) ) {
|
2451 |
try {
|
2452 |
+
$timestamp = time() + apply_filters( 'as3cf_expires', $expires );
|
2453 |
+
$url = $this->get_delivery_provider()->get_signed_url( $as3cf_item, $item_path, $delivery_domain, $scheme, $timestamp, $headers );
|
|
|
2454 |
|
2455 |
+
return apply_filters( 'as3cf_get_attachment_secure_url', $url, $as3cf_item, $post_id, $timestamp, $headers );
|
2456 |
+
} catch ( Exception $e ) {
|
2457 |
+
return new WP_Error( 'exception', $e->getMessage() );
|
2458 |
+
}
|
2459 |
+
} else {
|
2460 |
+
try {
|
2461 |
+
$url = $this->get_delivery_provider()->get_url( $as3cf_item, $item_path, $delivery_domain, $scheme, $headers );
|
2462 |
|
2463 |
+
return apply_filters( 'as3cf_get_attachment_url', $url, $as3cf_item, $post_id, $expires, $headers );
|
2464 |
} catch ( Exception $e ) {
|
2465 |
return new WP_Error( 'exception', $e->getMessage() );
|
2466 |
}
|
2467 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2468 |
}
|
2469 |
|
2470 |
/**
|
2492 |
return $new_url;
|
2493 |
}
|
2494 |
|
2495 |
+
/**
|
2496 |
+
* Filters the list of attachment image attributes.
|
2497 |
+
*
|
2498 |
+
* @param array $attr Attributes for the image markup.
|
2499 |
+
* @param WP_Post $attachment Image attachment post.
|
2500 |
+
* @param string|array $size Requested size. Image size or array of width and height values (in that order).
|
2501 |
+
*
|
2502 |
+
* @return array
|
2503 |
+
*/
|
2504 |
+
public function wp_get_attachment_image_attributes( $attr, $attachment, $size ) {
|
2505 |
+
if ( ! ( $as3cf_item = $this->is_attachment_served_by_provider( $attachment->ID ) ) ) {
|
2506 |
+
return $attr;
|
2507 |
+
}
|
2508 |
+
|
2509 |
+
$size = AS3CF_Utils::maybe_convert_size_to_string( $attachment->ID, $size );
|
2510 |
+
|
2511 |
+
// image_downsize incorrectly substitutes size filename into full URL for src attribute instead of clobbering.
|
2512 |
+
// So we need to fix up the src attribute if a size is being used.
|
2513 |
+
if ( ! empty( $size ) && ! empty( $attr['src'] ) ) {
|
2514 |
+
$attr['src'] = $this->get_attachment_provider_url( $attachment->ID, $as3cf_item, null, $size );
|
2515 |
+
}
|
2516 |
+
|
2517 |
+
/**
|
2518 |
+
* Filtered list of attachment image attributes.
|
2519 |
+
*
|
2520 |
+
* @param array $attr Attributes for the image markup.
|
2521 |
+
* @param WP_Post $attachment Image attachment post.
|
2522 |
+
* @param string $size Requested size.
|
2523 |
+
* @param Media_Library_Item $as3cf_item
|
2524 |
+
*/
|
2525 |
+
return apply_filters( 'as3cf_wp_get_attachment_image_attributes', $attr, $attachment, $size, $as3cf_item );
|
2526 |
+
}
|
2527 |
+
|
2528 |
/**
|
2529 |
* Maybe encode attachment URLs when retrieving the image tag
|
2530 |
*
|
2556 |
|
2557 |
$img_src = $matches[1];
|
2558 |
$new_img_src = $this->maybe_sign_intermediate_size( $img_src, $id, $size, $as3cf_item );
|
2559 |
+
$new_img_src = AS3CF_Utils::encode_filename_in_path( $new_img_src );
|
2560 |
|
2561 |
return str_replace( $img_src, $new_img_src, $html );
|
2562 |
}
|
2579 |
|
2580 |
if ( isset( $image[0] ) ) {
|
2581 |
$url = $this->maybe_sign_intermediate_size( $image[0], $attachment_id, $size, $as3cf_item );
|
2582 |
+
$url = AS3CF_Utils::encode_filename_in_path( $url );
|
2583 |
|
2584 |
$image[0] = $url;
|
2585 |
}
|
2603 |
}
|
2604 |
|
2605 |
if ( isset( $response['url'] ) ) {
|
2606 |
+
$response['url'] = AS3CF_Utils::encode_filename_in_path( $response['url'] );
|
2607 |
}
|
2608 |
|
2609 |
if ( isset( $response['sizes'] ) && is_array( $response['sizes'] ) ) {
|
2610 |
foreach ( $response['sizes'] as $size => $value ) {
|
2611 |
+
$url = $this->maybe_sign_intermediate_size( $value['url'], $attachment->ID, $size, $as3cf_item, true );
|
2612 |
+
$url = AS3CF_Utils::encode_filename_in_path( $url );
|
2613 |
|
2614 |
$response['sizes'][ $size ]['url'] = $url;
|
2615 |
}
|
2635 |
|
2636 |
if ( isset( $data['url'] ) ) {
|
2637 |
$url = $this->maybe_sign_intermediate_size( $data['url'], $post_id, $size, $as3cf_item );
|
2638 |
+
$url = AS3CF_Utils::encode_filename_in_path( $url );
|
2639 |
|
2640 |
$data['url'] = $url;
|
2641 |
}
|
2650 |
* @param int $attachment_id
|
2651 |
* @param string|array $size
|
2652 |
* @param bool|Media_Library_Item $as3cf_item
|
2653 |
+
* @param bool $force_rewrite If size not signed, make sure correct URL is being used anyway.
|
2654 |
*
|
2655 |
* @return string|WP_Error
|
2656 |
*/
|
2657 |
+
protected function maybe_sign_intermediate_size( $url, $attachment_id, $size, $as3cf_item = false, $force_rewrite = false ) {
|
2658 |
if ( ! $as3cf_item ) {
|
2659 |
$as3cf_item = Media_Library_Item::get_by_source_id( $attachment_id );
|
2660 |
}
|
2661 |
|
2662 |
+
$size = AS3CF_Utils::maybe_convert_size_to_string( $attachment_id, $size );
|
2663 |
|
2664 |
+
if ( $force_rewrite || $as3cf_item->is_private_size( $size ) ) {
|
2665 |
// Private file, add AWS signature if required
|
2666 |
return $this->get_attachment_provider_url( $attachment_id, $as3cf_item, null, $size );
|
2667 |
}
|
2669 |
return $url;
|
2670 |
}
|
2671 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2672 |
/**
|
2673 |
* Is attachment served by provider.
|
2674 |
*
|
2675 |
+
* @param int $attachment_id
|
2676 |
+
* @param bool $skip_rewrite_check Still check if offloaded even if not currently rewriting URLs? Default: false
|
2677 |
+
* @param bool $skip_current_provider_check Skip checking if offloaded to current provider. Default: false, negated if $provider supplied
|
2678 |
+
* @param Storage_Provider|null $provider Provider where attachment expected to be offloaded to. Default: currently configured provider
|
2679 |
*
|
2680 |
* @return bool|Media_Library_Item
|
2681 |
*/
|
2682 |
+
public function is_attachment_served_by_provider( $attachment_id, $skip_rewrite_check = false, $skip_current_provider_check = false, Storage_Provider $provider = null ) {
|
2683 |
if ( ! $skip_rewrite_check && ! $this->get_setting( 'serve-from-s3' ) ) {
|
2684 |
// Not serving provider URLs
|
2685 |
return false;
|
2693 |
}
|
2694 |
|
2695 |
if ( ! $skip_current_provider_check && empty( $provider ) ) {
|
2696 |
+
$provider = $this->get_storage_provider();
|
2697 |
}
|
2698 |
|
2699 |
if ( ! empty( $provider ) && $provider::get_provider_key_name() !== $as3cf_item->provider() ) {
|
2704 |
return $as3cf_item;
|
2705 |
}
|
2706 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2707 |
/**
|
2708 |
* Allow processes to update the file on provider via update_attached_file()
|
2709 |
*
|
2730 |
|
2731 |
/**
|
2732 |
* Return the provider URL when the local file is missing
|
2733 |
+
* unless we know who the calling process is and we are happy
|
2734 |
+
* to copy the file back to the server to be used.
|
2735 |
*
|
2736 |
* @param string $file
|
2737 |
* @param int $attachment_id
|
2739 |
* @return string
|
2740 |
*/
|
2741 |
function get_attached_file( $file, $attachment_id ) {
|
2742 |
+
$as3cf_item = $this->is_attachment_served_by_provider( $attachment_id );
|
2743 |
+
|
2744 |
+
if ( file_exists( $file ) || ! $as3cf_item ) {
|
2745 |
+
if ( $as3cf_item ) {
|
2746 |
+
// Although we have a local file, give filter implementors a chance to override or copy back siblings.
|
2747 |
+
return apply_filters( 'as3cf_get_attached_file_noop', $file, $file, $attachment_id, $as3cf_item );
|
2748 |
+
} else {
|
2749 |
+
return $file;
|
2750 |
+
}
|
2751 |
}
|
2752 |
|
2753 |
$url = $this->get_attachment_url( $attachment_id );
|
2859 |
$region = AS3CF_REGION;
|
2860 |
}
|
2861 |
|
2862 |
+
if ( ! is_null( $region ) && $this->get_storage_provider()->get_default_region() !== $region ) {
|
2863 |
$args['LocationConstraint'] = $region;
|
2864 |
}
|
2865 |
|
2919 |
|
2920 |
$this->set_setting( 'bucket', $bucket_name );
|
2921 |
|
2922 |
+
// Ensure Use Bucket ACLs is refreshed.
|
2923 |
+
$this->remove_setting( 'use-bucket-acls' );
|
2924 |
+
|
2925 |
if ( empty( $region ) ) {
|
2926 |
// retrieve the bucket region if not supplied
|
2927 |
$region = $this->get_bucket_region( $bucket_name );
|
2930 |
}
|
2931 |
}
|
2932 |
|
2933 |
+
if ( ! $this->get_storage_provider()->region_required() && $this->get_storage_provider()->get_default_region() === $region ) {
|
2934 |
$region = '';
|
2935 |
}
|
2936 |
|
2970 |
}
|
2971 |
|
2972 |
/**
|
2973 |
+
* In our settings screen?
|
2974 |
*
|
2975 |
+
* @param WP_Screen|null $screen
|
2976 |
+
*
|
2977 |
+
* @return bool
|
2978 |
*/
|
2979 |
+
public function our_screen( WP_Screen $screen = null ) {
|
2980 |
+
if ( ! is_admin() || empty( $this->hook_suffix ) ) {
|
2981 |
+
return false;
|
2982 |
+
}
|
2983 |
+
|
2984 |
+
if ( empty( $screen ) ) {
|
2985 |
+
$screen = get_current_screen();
|
2986 |
+
}
|
2987 |
+
|
2988 |
+
if ( false === strpos( $screen->id, $this->hook_suffix ) ) {
|
2989 |
+
return false;
|
2990 |
+
}
|
2991 |
+
|
2992 |
+
return true;
|
2993 |
+
}
|
2994 |
+
|
2995 |
+
/**
|
2996 |
+
* Add the settings page to the top-level AWS menu item for backwards compatibility.
|
2997 |
+
*
|
2998 |
+
* @param \Amazon_Web_Services $aws Plugin class instance from the amazon-web-services plugin.
|
2999 |
+
*/
|
3000 |
+
public function aws_admin_menu( $aws ) {
|
3001 |
+
$aws->add_page(
|
3002 |
+
$this->get_plugin_page_title(),
|
3003 |
+
$this->get_plugin_menu_title(),
|
3004 |
+
'manage_options',
|
3005 |
+
$this->plugin_slug,
|
3006 |
array( $this, 'render_page' )
|
3007 |
);
|
3008 |
}
|
3009 |
|
3010 |
/**
|
3011 |
+
* What is the default storage provider for legacy data?
|
3012 |
+
*
|
3013 |
+
* @return string
|
3014 |
+
*/
|
3015 |
+
public static function get_default_storage_provider() {
|
3016 |
+
return static::$default_storage_provider;
|
3017 |
+
}
|
3018 |
+
|
3019 |
+
/**
|
3020 |
+
* What is the default delivery provider for legacy data?
|
3021 |
*
|
3022 |
* @return string
|
3023 |
*/
|
3024 |
+
public static function get_default_delivery_provider() {
|
3025 |
+
return static::$default_delivery_provider;
|
3026 |
}
|
3027 |
|
3028 |
/**
|
3031 |
* @return string
|
3032 |
*/
|
3033 |
public function get_default_region() {
|
3034 |
+
return $this->get_storage_provider()->get_default_region();
|
3035 |
}
|
3036 |
|
3037 |
/**
|
3040 |
* @param bool|string $region specify region to client for signature
|
3041 |
* @param bool $force force return of new provider client when swapping regions
|
3042 |
*
|
3043 |
+
* @return Storage_Provider|Null_Provider
|
3044 |
* @throws Exception
|
3045 |
*/
|
3046 |
public function get_provider_client( $region = false, $force = false ) {
|
3051 |
$args = array();
|
3052 |
|
3053 |
if ( $force ) {
|
3054 |
+
$this->set_storage_provider();
|
3055 |
}
|
3056 |
|
3057 |
if ( $region ) {
|
3058 |
+
$args['region'] = $this->get_storage_provider()->sanitize_region( $region );
|
3059 |
}
|
3060 |
|
3061 |
$provider_client_region = isset( $args['region'] ) ? $args['region'] : $region;
|
3062 |
|
3063 |
try {
|
3064 |
+
$this->set_client( $this->get_storage_provider()->get_client( $args ), $provider_client_region );
|
3065 |
} catch ( Exception $e ) {
|
3066 |
AS3CF_Error::log( $e->getMessage() );
|
3067 |
$this->set_client( new Null_Provider );
|
3074 |
/**
|
3075 |
* Setter for Provider client
|
3076 |
*
|
3077 |
+
* @param Storage_Provider|Null_Provider $client
|
3078 |
+
* @param bool|string $region
|
3079 |
*/
|
3080 |
public function set_client( $client, $region = false ) {
|
3081 |
$this->provider_client = $client;
|
3114 |
return new WP_Error( 'exception', $error_msg_title . $error_msg );
|
3115 |
}
|
3116 |
|
3117 |
+
$region = $this->get_storage_provider()->sanitize_region( $region );
|
3118 |
|
3119 |
if ( is_string( $region ) ) {
|
3120 |
$regions[ $bucket ] = $region;
|
3131 |
$this->verify_ajax_request();
|
3132 |
|
3133 |
$region = empty( $_POST['region'] ) ? '' : $_POST['region'];
|
3134 |
+
$region = $this->check_region( $region, $this->get_storage_provider()->region_required() );
|
3135 |
|
3136 |
$result = $this->get_buckets( $region );
|
3137 |
|
3180 |
* @throws Exception
|
3181 |
*/
|
3182 |
function check_write_permission( $bucket = null, $region = null ) {
|
3183 |
+
if ( $this->get_storage_provider()->needs_access_keys() ) {
|
3184 |
// If no access keys set then no need check.
|
3185 |
return false;
|
3186 |
}
|
3187 |
|
3188 |
if ( is_null( $bucket ) ) {
|
3189 |
// If changing provider or bucket don't bother to test saved bucket permissions.
|
3190 |
+
if ( ! empty( $_GET['action'] ) && in_array( $_GET['action'], array( 'change-provider', 'change-bucket', 'change-delivery-provider' ) ) ) {
|
3191 |
return false;
|
3192 |
}
|
3193 |
|
3276 |
wp_register_script( 'as3cf-storage-provider', $src, array( 'jquery' ), $version, true );
|
3277 |
}
|
3278 |
|
3279 |
+
/**
|
3280 |
+
* Register delivery provider scripts and styles so they can be enqueued later
|
3281 |
+
*/
|
3282 |
+
function register_delivery_provider_assets() {
|
3283 |
+
$version = $this->get_asset_version();
|
3284 |
+
$suffix = $this->get_asset_suffix();
|
3285 |
+
|
3286 |
+
$src = plugins_url( 'assets/css/delivery-provider.css', $this->plugin_file_path );
|
3287 |
+
wp_register_style( 'as3cf-delivery-provider', $src, array(), $version );
|
3288 |
+
|
3289 |
+
$src = plugins_url( 'assets/js/delivery-provider' . $suffix . '.js', $this->plugin_file_path );
|
3290 |
+
wp_register_script( 'as3cf-delivery-provider', $src, array( 'jquery' ), $version, true );
|
3291 |
+
}
|
3292 |
+
|
3293 |
/**
|
3294 |
* On plugin load.
|
3295 |
*/
|
3306 |
|
3307 |
add_action( 'network_admin_notices', array( $this, 'settings_saved_notice' ) );
|
3308 |
|
3309 |
+
$this->enqueue_style( 'as3cf-styles', 'assets/css/styles', array( 'as3cf-modal', 'as3cf-storage-provider', 'as3cf-delivery-provider' ) );
|
3310 |
+
$this->enqueue_script( 'as3cf-script', 'assets/js/script', array( 'jquery', 'underscore', 'as3cf-modal', 'as3cf-storage-provider', 'as3cf-delivery-provider' ) );
|
3311 |
|
3312 |
wp_localize_script( 'as3cf-script',
|
3313 |
'as3cf',
|
3338 |
'aws_keys_remove' => wp_create_nonce( 'as3cf-aws-keys-remove' ),
|
3339 |
),
|
3340 |
'is_pro' => $this->is_pro(),
|
3341 |
+
'provider_console_url' => $this->get_storage_provider()->get_console_url(),
|
3342 |
+
'provider_console_url_prefix_param' => $this->get_storage_provider()->get_console_url_prefix_param(),
|
3343 |
)
|
3344 |
);
|
3345 |
|
3357 |
*/
|
3358 |
function get_settings_whitelist() {
|
3359 |
return array(
|
3360 |
+
// Storage
|
3361 |
'provider',
|
3362 |
'access-key-id',
|
3363 |
'secret-access-key',
|
3366 |
'use-server-roles',
|
3367 |
'bucket',
|
3368 |
'region',
|
3369 |
+
'use-bucket-acls',
|
3370 |
+
'enable-object-prefix',
|
|
|
|
|
3371 |
'object-prefix',
|
|
|
|
|
|
|
|
|
|
|
3372 |
'use-yearmonth-folders',
|
3373 |
+
'object-versioning',
|
3374 |
+
'copy-to-s3', // TODO: Rename
|
3375 |
+
// Delivery
|
3376 |
+
'delivery-provider',
|
3377 |
+
'delivery-provider-service-name',
|
3378 |
+
'enable-delivery-domain',
|
3379 |
+
'delivery-domain',
|
3380 |
+
'virtual-host', // Legacy
|
3381 |
+
'domain', // Legacy
|
3382 |
+
'cloudfront', // Legacy
|
3383 |
+
'enable-signed-urls',
|
3384 |
+
'signed-urls-key-id',
|
3385 |
+
'signed-urls-key-file-path',
|
3386 |
+
'signed-urls-object-prefix',
|
3387 |
+
'force-https',
|
3388 |
+
'serve-from-s3', // TODO: Rename
|
3389 |
+
// Advanced
|
3390 |
+
'remove-local-file',
|
3391 |
);
|
3392 |
}
|
3393 |
|
3413 |
return array( 'key-file' );
|
3414 |
}
|
3415 |
|
3416 |
+
/**
|
3417 |
+
* @inheritDoc
|
3418 |
+
*/
|
3419 |
+
function get_path_format_settings() {
|
3420 |
+
return array(
|
3421 |
+
'key-file-path',
|
3422 |
+
'signed-urls-key-file-path',
|
3423 |
+
);
|
3424 |
+
}
|
3425 |
+
|
3426 |
+
/**
|
3427 |
+
* @inheritDoc
|
3428 |
+
*/
|
3429 |
+
function get_prefix_format_settings() {
|
3430 |
+
return array(
|
3431 |
+
'object-prefix',
|
3432 |
+
'signed-urls-object-prefix',
|
3433 |
+
);
|
3434 |
+
}
|
3435 |
+
|
3436 |
/**
|
3437 |
* Handle the saving of the settings page
|
3438 |
*/
|
3450 |
}
|
3451 |
|
3452 |
// Keep track of original provider at start of settings change flow.
|
3453 |
+
$orig_provider = isset( $_GET['orig_provider'] ) ? $_GET['orig_provider'] : '';
|
3454 |
|
3455 |
+
// If we already have a bucket, then we should keep track of the associated provider too.
|
3456 |
+
if ( empty( $orig_provider ) && $this->get_setting( 'bucket', false ) ) {
|
3457 |
+
$orig_provider = $this->get_setting( 'provider' );
|
3458 |
+
}
|
3459 |
+
|
3460 |
+
if ( $this->get_storage_provider()->needs_access_keys() || ( ! empty( $_GET['action'] ) && 'change-provider' === $_GET['action'] ) ) {
|
3461 |
// Changing Provider currently doesn't need anything special over saving settings,
|
3462 |
// but if not already set needs to be handled rather than change-bucket raising its hand.
|
3463 |
$changed_keys = $this->handle_save_settings();
|
3464 |
} elseif ( empty( $this->get_setting( 'bucket' ) ) || ( ! empty( $_GET['action'] ) && 'change-bucket' === $_GET['action'] ) ) {
|
3465 |
$changed_keys = $this->handle_change_bucket();
|
3466 |
+
} elseif ( ! empty( $_GET['action'] ) && 'change-bucket-access' === $_GET['action'] ) {
|
3467 |
+
$changed_keys = $this->handle_change_bucket_access();
|
3468 |
+
} elseif ( ! empty( $_GET['action'] ) && 'change-delivery-provider' === $_GET['action'] ) {
|
3469 |
+
$changed_keys = $this->handle_save_settings();
|
3470 |
} elseif ( ! empty( $_GET['action'] ) ) {
|
3471 |
$changed_keys = apply_filters( 'as3cf_handle_post_request', array() );
|
3472 |
} else {
|
3485 |
if ( ! empty( $changed_keys ) ) {
|
3486 |
$action = null;
|
3487 |
|
3488 |
+
// If anything about the Provider has changed then we need to verify the bucket selection.
|
3489 |
+
// If the bucket has changed, and provider allows blocking public access to bucket, verify bucket access requirement.
|
3490 |
+
// Otherwise we can let the filter decide whether there is an action to take.
|
3491 |
+
// Last implementer will win, but the above handlers take care of grouping things appropriately.
|
3492 |
+
if ( ! empty( array_intersect( $changed_keys, array( 'provider', 'access-key-id', 'secret-access-key', 'key-file', 'use-server-roles' ) ) ) && ! $this->get_defined_setting( 'bucket', false ) ) {
|
3493 |
+
$action = 'change-bucket';
|
3494 |
+
} elseif ( ! empty( array_intersect( $changed_keys, array( 'bucket', 'region' ) ) ) && $this->get_storage_provider()->block_public_access_allowed() ) {
|
3495 |
+
// Not initial setup, show change bucket access regardless if allowed.
|
3496 |
+
if ( ! empty( $_GET['orig_provider'] ) ) {
|
3497 |
+
$action = 'change-bucket-access';
|
3498 |
} else {
|
3499 |
+
// Is Block All Public Access enabled?
|
3500 |
+
try {
|
3501 |
+
$public_access_blocked = $this->get_provider_client()->public_access_blocked( $this->get_setting( 'bucket' ) );
|
3502 |
+
} catch ( Exception $e ) {
|
3503 |
+
$public_access_blocked = null;
|
3504 |
+
}
|
3505 |
+
|
3506 |
+
if ( ! empty( $public_access_blocked ) && ! $this->get_delivery_provider()->use_signed_urls_key_file_allowed() ) {
|
3507 |
+
$action = 'change-bucket-access';
|
3508 |
+
}
|
3509 |
+
}
|
3510 |
+
} elseif ( in_array( 'delivery-provider', $changed_keys ) ) {
|
3511 |
+
// If delivery provider has just changed, there might be a masked change to enable-signed-urls.
|
3512 |
+
try {
|
3513 |
+
$this->set_delivery_provider();
|
3514 |
+
|
3515 |
+
if ( $this->get_setting( 'enable-signed-urls', false ) && ! $this->get_delivery_provider()->use_signed_urls_key_file_allowed() ) {
|
3516 |
+
$changed_keys[] = 'enable-signed-urls';
|
3517 |
+
$this->set_setting( 'enable-signed-urls', false );
|
3518 |
+
$this->save_settings();
|
3519 |
+
}
|
3520 |
+
} catch ( Exception $e ) {
|
3521 |
+
// Meh, no biggie, the move tool can always be run manually.
|
3522 |
+
AS3CF_Error::log( sprintf( __( 'Could not set new Delivery Provider: %s', 'amazon-s3-and-cloudfront' ), $e->getMessage() ) );
|
3523 |
}
|
3524 |
}
|
3525 |
+
|
3526 |
+
$action = empty( $action ) ? apply_filters( 'as3cf_action_for_changed_settings_key', $action, $changed_keys ) : $action;
|
3527 |
}
|
3528 |
|
3529 |
// Stash which step we're on in possibly multi-step config.
|
3531 |
|
3532 |
// Depending on the step we're on, we may need another step if not already determined by newly saved settings.
|
3533 |
if ( empty( $action ) && ! empty( $prev_action ) ) {
|
|
|
|
|
|
|
3534 |
if ( 'change-provider' === $prev_action && ! $this->get_defined_setting( 'bucket', false ) ) {
|
3535 |
+
// After change-provider we always want the user to confirm the bucket is still ok.
|
3536 |
+
// This gets round the change-provider => change-bucket => "back" problem.
|
3537 |
+
// but then no change in provider settings problem.
|
3538 |
$action = 'change-bucket';
|
3539 |
+
} elseif ( ! empty( $_GET['orig_provider'] ) && 'change-bucket' === $prev_action && $this->get_storage_provider()->block_public_access_allowed() ) {
|
3540 |
+
// If bucket didn't change, might want to update bucket access.
|
3541 |
+
$action = 'change-bucket-access';
|
3542 |
}
|
3543 |
}
|
3544 |
|
3545 |
+
// If no action set yet, but there were changes earlier, let filter implementors have a look at them.
|
3546 |
+
if ( ! empty( $_GET['changed'] ) ) {
|
3547 |
+
$changed = (array) $_GET['changed'];
|
3548 |
+
}
|
3549 |
+
|
3550 |
+
if ( empty( $action ) && ! empty( $changed ) ) {
|
3551 |
+
$action = null;
|
3552 |
+
|
3553 |
+
$action = apply_filters( 'as3cf_action_for_changed_settings_key', $action, $changed );
|
3554 |
+
}
|
3555 |
+
|
3556 |
if ( ! empty( $action ) ) {
|
3557 |
$url_args['action'] = $action;
|
3558 |
|
3563 |
if ( ! empty( $orig_provider ) ) {
|
3564 |
$url_args['orig_provider'] = $orig_provider;
|
3565 |
}
|
3566 |
+
|
3567 |
+
if ( ! empty( $changed ) ) {
|
3568 |
+
$url_args['changed'] = $changed;
|
3569 |
+
}
|
3570 |
+
|
3571 |
+
if ( ! empty( $changed_keys ) && is_array( $changed_keys ) ) {
|
3572 |
+
$changed = empty( $url_args['changed'] ) ? array() : $url_args['changed'];
|
3573 |
+
$url_args['changed'] = array_merge( $changed, $changed_keys );
|
3574 |
+
}
|
3575 |
}
|
3576 |
|
3577 |
$url = $this->get_plugin_page_url( $url_args );
|
3586 |
* @throws Exception
|
3587 |
*/
|
3588 |
private function handle_change_bucket() {
|
3589 |
+
if ( $this->get_defined_setting( 'bucket' ) ) {
|
3590 |
+
return array();
|
3591 |
+
}
|
3592 |
+
|
3593 |
// Quick check that bucket name actually given.
|
3594 |
$bucket = empty( $_POST['bucket_name'] ) ? false : $_POST['bucket_name'];
|
3595 |
|
3612 |
|
3613 |
// Check and set region.
|
3614 |
$region = empty( $_POST['region_name'] ) ? '' : $_POST['region_name'];
|
3615 |
+
$region_required = 'create' === $bucket_mode ? true : $this->get_storage_provider()->region_required();
|
3616 |
$region = $this->check_region( $region, $region_required );
|
3617 |
|
3618 |
if ( false === $region ) {
|
3678 |
return $changed_keys;
|
3679 |
}
|
3680 |
|
3681 |
+
/**
|
3682 |
+
* Handle saving the block all public access preference to the bucket.
|
3683 |
+
*
|
3684 |
+
* @return array|bool
|
3685 |
+
*
|
3686 |
+
* There's no actual setting for this, the state of public access to the bucket is checked as required.
|
3687 |
+
*/
|
3688 |
+
private function handle_change_bucket_access() {
|
3689 |
+
// Whatever happens, refresh the Use Bucket ACLs setting afterwards.
|
3690 |
+
$this->get_settings();
|
3691 |
+
$this->remove_setting( 'use-bucket-acls' );
|
3692 |
+
$this->save_settings();
|
3693 |
+
|
3694 |
+
if ( false === $this->get_storage_provider()->block_public_access_allowed() ) {
|
3695 |
+
$this->notices->add_notice(
|
3696 |
+
printf( _x( "Can't change Block All Public Access setting for %s buckets.", "Trying to change public access setting for given provider's bucket.", 'amazon-s3-and-cloudfront' ), $this->get_storage_provider()->get_provider_service_name() ),
|
3697 |
+
array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
|
3698 |
+
);
|
3699 |
+
|
3700 |
+
return false;
|
3701 |
+
}
|
3702 |
+
|
3703 |
+
if ( false === isset( $_POST['block-public-access'] ) ) {
|
3704 |
+
$this->notices->add_notice(
|
3705 |
+
__( 'No block public access setting provided.', 'amazon-s3-and-cloudfront' ),
|
3706 |
+
array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
|
3707 |
+
);
|
3708 |
+
|
3709 |
+
return false;
|
3710 |
+
}
|
3711 |
+
|
3712 |
+
$block_public_access = empty( $_POST['block-public-access'] ) ? false : true;
|
3713 |
+
|
3714 |
+
$bucket = $this->get_setting( 'bucket' );
|
3715 |
+
|
3716 |
+
if ( $this->get_storage_provider()->needs_access_keys() ) {
|
3717 |
+
$this->notices->add_notice(
|
3718 |
+
__( 'Storage Provider not configured with access credentials.', 'amazon-s3-and-cloudfront' ),
|
3719 |
+
array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
|
3720 |
+
);
|
3721 |
+
|
3722 |
+
return false;
|
3723 |
+
}
|
3724 |
+
|
3725 |
+
if ( empty( $bucket ) ) {
|
3726 |
+
$this->notices->add_notice(
|
3727 |
+
__( 'No bucket name provided.', 'amazon-s3-and-cloudfront' ),
|
3728 |
+
array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
|
3729 |
+
);
|
3730 |
+
|
3731 |
+
return false;
|
3732 |
+
}
|
3733 |
+
|
3734 |
+
try {
|
3735 |
+
$public_access_blocked = $this->get_provider_client()->public_access_blocked( $bucket );
|
3736 |
+
} catch ( Exception $e ) {
|
3737 |
+
$public_access_blocked = null;
|
3738 |
+
}
|
3739 |
+
|
3740 |
+
if ( empty( $block_public_access ) !== empty( $public_access_blocked ) ) {
|
3741 |
+
try {
|
3742 |
+
$this->get_provider_client()->block_public_access( $bucket, $block_public_access );
|
3743 |
+
} catch ( Exception $e ) {
|
3744 |
+
$this->notices->add_notice(
|
3745 |
+
__( 'Could not change Block All Public Access status for bucket.', 'amazon-s3-and-cloudfront' ),
|
3746 |
+
array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
|
3747 |
+
);
|
3748 |
+
|
3749 |
+
return false;
|
3750 |
+
}
|
3751 |
+
|
3752 |
+
// The bucket level request may succeed, but account level overrides may negate the change or the change simply silently failed.
|
3753 |
+
// So check that all is as expected as we can't change the account level settings.
|
3754 |
+
try {
|
3755 |
+
$public_access_blocked = $this->get_provider_client()->public_access_blocked( $bucket );
|
3756 |
+
} catch ( Exception $e ) {
|
3757 |
+
$public_access_blocked = null;
|
3758 |
+
}
|
3759 |
+
|
3760 |
+
if ( empty( $block_public_access ) !== empty( $public_access_blocked ) ) {
|
3761 |
+
if ( $block_public_access ) {
|
3762 |
+
$notice_message = __( '<strong>Failed to Enable Block All Public Access</strong> — We could not enable Block All Public Access. You will need to log in to the AWS Console and do it manually.', 'amazon-s3-and-cloudfront' );
|
3763 |
+
} else {
|
3764 |
+
$notice_message = __( '<strong>Failed to Disable Block All Public Access</strong> — We could not disable Block All Public Access. You will need to log in to the AWS Console and do it manually.', 'amazon-s3-and-cloudfront' );
|
3765 |
+
}
|
3766 |
+
$notice_message .= ' ' . $this->settings_more_info_link( 'bucket' );
|
3767 |
+
|
3768 |
+
$this->notices->add_notice(
|
3769 |
+
$notice_message,
|
3770 |
+
array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
|
3771 |
+
);
|
3772 |
+
|
3773 |
+
return false;
|
3774 |
+
}
|
3775 |
+
|
3776 |
+
// No settings keys actually changed, but flag it anyway as status of bucket has changed.
|
3777 |
+
return array( 'use-bucket-acls' );
|
3778 |
+
}
|
3779 |
+
|
3780 |
+
// No settings keys actually changed.
|
3781 |
+
return array();
|
3782 |
+
}
|
3783 |
+
|
3784 |
/**
|
3785 |
* Handle saving settings submitted by user.
|
3786 |
*
|
3829 |
continue;
|
3830 |
}
|
3831 |
|
3832 |
+
if ( 'signed-urls-key-id' === $var && empty( $value ) && ! empty( $_POST['enable-signed-urls'] ) ) {
|
3833 |
+
$this->notices->add_notice(
|
3834 |
+
$this->get_delivery_provider()->signed_urls_key_id_name() . _x( ' not provided.', 'missing form field', 'amazon-s3-and-cloudfront' ),
|
3835 |
+
array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
|
3836 |
+
);
|
3837 |
+
|
3838 |
+
return false;
|
3839 |
+
}
|
3840 |
+
|
3841 |
+
if ( 'signed-urls-key-file-path' === $var && is_string( $value ) && ! empty( $value ) ) {
|
3842 |
+
// Can be a Windows path with backslashes, so need to undo what POST does to them.
|
3843 |
+
$value = stripslashes( $value );
|
3844 |
+
}
|
3845 |
+
|
3846 |
+
if ( 'signed-urls-key-file-path' === $var && empty( $value ) && ! empty( $_POST['enable-signed-urls'] ) ) {
|
3847 |
+
$this->notices->add_notice(
|
3848 |
+
$this->get_delivery_provider()->signed_urls_key_file_path_name() . _x( ' not provided.', 'missing form field', 'amazon-s3-and-cloudfront' ),
|
3849 |
+
array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
|
3850 |
+
);
|
3851 |
+
|
3852 |
+
return false;
|
3853 |
+
}
|
3854 |
+
|
3855 |
+
if ( 'signed-urls-object-prefix' === $var && empty( $value ) && ! empty( $_POST['enable-signed-urls'] ) ) {
|
3856 |
+
$this->notices->add_notice(
|
3857 |
+
$this->get_delivery_provider()->signed_urls_object_prefix_name() . _x( ' not provided.', 'missing form field', 'amazon-s3-and-cloudfront' ),
|
3858 |
+
array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media' )
|
3859 |
+
);
|
3860 |
+
|
3861 |
+
return false;
|
3862 |
+
}
|
3863 |
+
|
3864 |
$this->set_setting( $var, $value );
|
3865 |
|
3866 |
// Some setting changes might have knock-on effects that require confirmation of secondary settings.
|
3867 |
+
if ( ( empty( $old_settings[ $var ] ) !== empty( $value ) ) || ( isset( $old_settings[ $var ] ) && $old_settings[ $var ] !== $value ) ) {
|
3868 |
$changed_keys[] = $var;
|
3869 |
}
|
3870 |
}
|
4046 |
|
4047 |
foreach ( $blogs as $blog ) {
|
4048 |
$blog = (array) $blog;
|
4049 |
+
$blog_ids[] = (int) $blog['blog_id'];
|
4050 |
}
|
4051 |
|
4052 |
return $blog_ids;
|
4065 |
return true;
|
4066 |
}
|
4067 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4068 |
/**
|
4069 |
* Make admin notice for when object ACL has changed
|
4070 |
*
|
4072 |
*/
|
4073 |
function make_acl_admin_notice( Media_Library_Item $as3cf_item ) {
|
4074 |
$filename = wp_basename( $as3cf_item->path() );
|
4075 |
+
$acl = $as3cf_item->is_private() ? $this->get_storage_provider()->get_private_acl() : $this->get_storage_provider()->get_default_acl();
|
4076 |
$acl_name = $this->get_acl_display_name( $acl );
|
4077 |
$text = sprintf( __( '<strong>WP Offload Media</strong> — The file %s has been given %s permissions in the bucket.', 'amazon-s3-and-cloudfront' ), "<strong>{$filename}</strong>", "<strong>{$acl_name}</strong>" );
|
4078 |
|
4343 |
$media_counts = $this->media_counts();
|
4344 |
|
4345 |
$output .= 'Media Files: ';
|
4346 |
+
$output .= number_format_i18n( $media_counts['total'] );
|
4347 |
$output .= "\r\n";
|
4348 |
|
4349 |
$output .= 'Offloaded Media Files: ';
|
4350 |
+
$output .= number_format_i18n( $media_counts['offloaded'] );
|
4351 |
$output .= "\r\n";
|
4352 |
|
4353 |
$output .= 'Not Offloaded Media Files: ';
|
4354 |
+
$output .= number_format_i18n( $media_counts['not_offloaded'] );
|
|
|
|
|
4355 |
$output .= "\r\n\r\n";
|
4356 |
|
4357 |
$output .= 'Number of Image Sizes: ';
|
4436 |
$output .= "\r\n";
|
4437 |
$output .= "\r\n";
|
4438 |
|
4439 |
+
$output .= 'OME Metadata Version: ';
|
4440 |
+
$output .= esc_html( $this->get_setting( 'post_meta_version' ) );
|
4441 |
+
$output .= "\r\n\r\n";
|
4442 |
+
|
4443 |
+
$storage_provider = $this->get_storage_provider();
|
4444 |
|
4445 |
+
if ( empty( $storage_provider ) ) {
|
4446 |
+
$output .= 'Storage Provider: Not configured';
|
4447 |
$output .= "\r\n";
|
4448 |
} else {
|
4449 |
+
$output .= 'Storage Provider: ' . $storage_provider::get_provider_service_name();
|
4450 |
$output .= "\r\n";
|
4451 |
|
4452 |
+
if ( $storage_provider::use_server_roles_allowed() ) {
|
4453 |
+
$output .= 'Use Server Roles: ';
|
4454 |
+
$output .= $storage_provider->use_server_roles() ? 'On' : 'Off';
|
4455 |
} else {
|
4456 |
$output .= 'Use Server Roles: N/A';
|
4457 |
}
|
4458 |
$output .= "\r\n";
|
4459 |
|
4460 |
+
if ( $storage_provider::use_key_file_allowed() ) {
|
4461 |
$output .= 'Key File Path: ';
|
4462 |
+
$output .= empty( $storage_provider->get_key_file_path() ) ? 'None' : esc_html( $storage_provider->get_key_file_path() );
|
4463 |
$output .= "\r\n";
|
4464 |
$output .= 'Key File Path Define: ';
|
4465 |
+
$output .= $storage_provider::key_file_path_constant() ? $storage_provider::key_file_path_constant() : 'Not defined';
|
4466 |
} else {
|
4467 |
$output .= 'Key File Path: N/A';
|
4468 |
}
|
4469 |
$output .= "\r\n";
|
4470 |
|
4471 |
+
if ( $storage_provider::use_access_keys_allowed() ) {
|
4472 |
$output .= 'Access Keys Set: ';
|
4473 |
+
$output .= $storage_provider->are_access_keys_set() ? 'Yes' : 'No';
|
4474 |
$output .= "\r\n";
|
4475 |
$output .= 'Access Key ID Define: ';
|
4476 |
+
$output .= $storage_provider::access_key_id_constant() ? $storage_provider::access_key_id_constant() : 'Not defined';
|
4477 |
$output .= "\r\n";
|
4478 |
$output .= 'Secret Access Key Define: ';
|
4479 |
+
$output .= $storage_provider::secret_access_key_constant() ? $storage_provider::secret_access_key_constant() : 'Not defined';
|
4480 |
} else {
|
4481 |
$output .= 'Access Keys Set: N/A';
|
4482 |
}
|
4484 |
}
|
4485 |
$output .= "\r\n";
|
4486 |
|
4487 |
+
$bucket = $this->get_setting( 'bucket' );
|
4488 |
$output .= 'Bucket: ';
|
4489 |
+
$output .= empty( $bucket ) ? '(none)' : esc_html( $bucket );
|
4490 |
$output .= "\r\n";
|
4491 |
+
$value = $this->get_setting( 'region' );
|
4492 |
$output .= 'Region: ';
|
4493 |
+
if ( is_wp_error( $value ) ) {
|
4494 |
+
$output .= '(error: "' . esc_html( $value->get_error_message() ) . '")';
|
4495 |
+
} elseif ( empty( $value ) ) {
|
4496 |
+
$output .= '(empty)';
|
4497 |
+
} else {
|
4498 |
+
$output .= esc_html( $value );
|
4499 |
}
|
4500 |
$output .= "\r\n";
|
4501 |
+
if (
|
4502 |
+
! empty( $storage_provider ) &&
|
4503 |
+
! empty( $bucket ) &&
|
4504 |
+
! $storage_provider->needs_access_keys() &&
|
4505 |
+
$storage_provider->block_public_access_allowed()
|
4506 |
+
) {
|
4507 |
+
try {
|
4508 |
+
$public_access_blocked = $this->get_provider_client()->public_access_blocked( $bucket );
|
4509 |
+
} catch ( Exception $e ) {
|
4510 |
+
$public_access_blocked = null;
|
4511 |
+
}
|
4512 |
+
$output .= 'Block All Public Access: ';
|
4513 |
+
if ( true === $public_access_blocked ) {
|
4514 |
+
$output .= 'Enabled';
|
4515 |
+
} elseif ( false === $public_access_blocked ) {
|
4516 |
+
$output .= 'Disabled';
|
4517 |
+
} else {
|
4518 |
+
$output .= 'Unknown';
|
4519 |
+
}
|
4520 |
+
$output .= "\r\n";
|
4521 |
+
}
|
4522 |
$output .= "\r\n";
|
4523 |
|
4524 |
$output .= 'Copy Files to Bucket: ';
|
4527 |
$output .= 'Enable Path: ';
|
4528 |
$output .= $this->on_off( 'enable-object-prefix' );
|
4529 |
$output .= "\r\n";
|
4530 |
+
$value = $this->get_setting( 'object-prefix' );
|
4531 |
$output .= 'Custom Path: ';
|
4532 |
+
$output .= empty( $value ) ? '(none)' : esc_html( $value );
|
4533 |
$output .= "\r\n";
|
4534 |
$output .= 'Use Year/Month: ';
|
4535 |
$output .= $this->on_off( 'use-yearmonth-folders' );
|
4539 |
$output .= "\r\n";
|
4540 |
$output .= "\r\n";
|
4541 |
|
4542 |
+
$delivery_provider = $this->get_delivery_provider();
|
4543 |
+
|
4544 |
+
if ( empty( $delivery_provider ) ) {
|
4545 |
+
$output .= 'Delivery Provider: Not configured';
|
4546 |
+
$output .= "\r\n";
|
4547 |
+
} else {
|
4548 |
+
$output .= 'Delivery Provider: ' . $delivery_provider::get_provider_service_name();
|
4549 |
+
$output .= "\r\n";
|
4550 |
+
$output .= 'Rewrite Media URLs: ';
|
4551 |
+
$output .= $this->on_off( 'serve-from-s3' );
|
4552 |
+
$output .= "\r\n";
|
4553 |
+
|
4554 |
+
if ( $delivery_provider::delivery_domain_allowed() ) {
|
4555 |
+
$output .= 'Enable Custom Domain (CNAME): ';
|
4556 |
+
$output .= $this->on_off( 'enable-delivery-domain' );
|
4557 |
+
$output .= "\r\n";
|
4558 |
+
$value = $this->get_setting( 'delivery-domain' );
|
4559 |
+
$output .= 'Custom Domain (CNAME): ';
|
4560 |
+
$output .= empty( $value ) ? '(none)' : esc_html( $value );
|
4561 |
+
$output .= "\r\n";
|
4562 |
+
}
|
4563 |
+
|
4564 |
+
if ( $delivery_provider::use_signed_urls_key_file_allowed() ) {
|
4565 |
+
$output .= 'Enable Signed URLs: ';
|
4566 |
+
$output .= $this->on_off( 'enable-signed-urls' );
|
4567 |
+
$output .= "\r\n";
|
4568 |
+
$output .= 'Signed URLs Key ID Set: ';
|
4569 |
+
$output .= $delivery_provider->get_signed_urls_key_id() ? 'Yes' : 'No';
|
4570 |
+
$output .= "\r\n";
|
4571 |
+
$value = $this->get_setting( 'signed-urls-key-file-path' );
|
4572 |
+
$output .= 'Signed URLs Key File Path: ';
|
4573 |
+
$output .= empty( $value ) ? '(none)' : esc_html( $value );
|
4574 |
+
$output .= "\r\n";
|
4575 |
+
$value = $this->get_setting( 'signed-urls-object-prefix' );
|
4576 |
+
$output .= 'Signed URLs Private Prefix: ';
|
4577 |
+
$output .= empty( $value ) ? '(none)' : esc_html( $value );
|
4578 |
+
$output .= "\r\n";
|
4579 |
+
}
|
4580 |
+
$output .= "\r\n";
|
4581 |
+
}
|
4582 |
+
|
4583 |
$output .= 'Force HTTPS: ';
|
4584 |
$output .= $this->on_off( 'force-https' );
|
4585 |
$output .= "\r\n";
|
4744 |
* @return string
|
4745 |
*/
|
4746 |
function get_acl_display_name( $acl ) {
|
4747 |
+
$acl = empty( $acl ) ? 'default' : $acl;
|
4748 |
$acl = ( 'public-read' === $acl ) ? 'public' : $acl;
|
4749 |
|
4750 |
return ucwords( str_replace( '-', ' ', $acl ) );
|
4874 |
* @return string
|
4875 |
*/
|
4876 |
function get_access_denied_notice_message( $single = true ) {
|
4877 |
+
if ( $this->get_storage_provider()->needs_access_keys() ) {
|
4878 |
return sprintf( __( '<a href="%s">Define your access keys</a> to enable write access to the bucket', 'amazon-s3-and-cloudfront' ), '#settings' );
|
4879 |
}
|
4880 |
|
4978 |
*/
|
4979 |
public function media_counts( $skip_transient = false, $force = false ) {
|
4980 |
if ( $skip_transient || false === ( $attachment_counts = get_site_transient( 'as3cf_attachment_counts' ) ) ) {
|
4981 |
+
$table_prefixes = $this->get_all_blog_table_prefixes();
|
4982 |
+
$total = 0;
|
4983 |
+
$offloaded = 0;
|
4984 |
+
$not_offloaded = 0;
|
|
|
|
|
|
|
4985 |
|
4986 |
foreach ( $table_prefixes as $blog_id => $table_prefix ) {
|
4987 |
$this->switch_to_blog( $blog_id );
|
4988 |
|
4989 |
+
$counts = Media_Library_Item::count_attachments( $skip_transient, $force );
|
4990 |
+
$total += $counts['total'];
|
4991 |
+
$offloaded += $counts['offloaded'];
|
4992 |
+
$not_offloaded += $counts['not_offloaded'];
|
|
|
|
|
|
|
4993 |
|
4994 |
$this->restore_current_blog();
|
4995 |
}
|
4996 |
|
4997 |
$attachment_counts = array(
|
4998 |
+
'total' => $total,
|
4999 |
+
'offloaded' => $offloaded,
|
5000 |
+
'not_offloaded' => $not_offloaded,
|
|
|
|
|
|
|
5001 |
);
|
5002 |
|
5003 |
+
set_site_transient( 'as3cf_attachment_counts', $attachment_counts, 5 * MINUTE_IN_SECONDS );
|
5004 |
}
|
5005 |
|
5006 |
return $attachment_counts;
|
5111 |
exit( $exit_code );
|
5112 |
}
|
5113 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5114 |
/**
|
5115 |
* Upgrade the 'virtual host' / 'bucket as domain' setting to the
|
5116 |
* new CloudFront / Domain setting
|
5153 |
}
|
5154 |
|
5155 |
/**
|
5156 |
+
* Potentially update path for delivery URLs.
|
5157 |
*
|
5158 |
+
* @param string $path Path in bucket to be used in URL.
|
5159 |
+
* @param string $domain Domain to be used in URL.
|
5160 |
+
* @param int|null $timestamp Optional time that signed URL expires.
|
5161 |
*
|
5162 |
* @return string
|
5163 |
+
*
|
5164 |
+
* Note: This is a wrapper for a filter, which only fires default (storage) delivery provider is not in use.
|
5165 |
*/
|
5166 |
+
public function maybe_update_delivery_path( $path, $domain, $timestamp = null ) {
|
5167 |
+
if ( static::get_default_delivery_provider() !== $this->get_delivery_provider()->get_provider_key_name() ) {
|
5168 |
+
$path_parts = apply_filters( 'as3cf_cloudfront_path_parts', explode( '/', $path ), $domain, $timestamp ); // Backwards compatibility.
|
5169 |
+
$path_parts = apply_filters( 'as3cf_delivery_domain_path_parts', $path_parts, $domain, $timestamp );
|
5170 |
|
5171 |
if ( ! empty( $path_parts ) ) {
|
5172 |
$path = implode( '/', $path_parts );
|
5260 |
$provider_object['key'] = $provider_object['path'];
|
5261 |
$provider_object['url'] = $this->get_attachment_provider_url( $id, $as3cf_item );
|
5262 |
|
5263 |
+
$acl = $as3cf_item->is_private() ? $this->get_storage_provider()->get_private_acl() : $this->get_storage_provider()->get_default_acl();
|
5264 |
$acl_info = array(
|
5265 |
'acl' => $acl,
|
5266 |
'name' => $this->get_acl_display_name( $acl ),
|
5272 |
}
|
5273 |
|
5274 |
$provider_object['acl'] = $acl_info;
|
5275 |
+
$provider_object['region'] = $this->get_storage_provider()->get_region_name( $provider_object['region'] );
|
5276 |
$provider_object['provider_name'] = $this->get_provider_service_name( $provider_object['provider'] );
|
5277 |
|
5278 |
return $provider_object;
|
5354 |
*
|
5355 |
* @return array
|
5356 |
*/
|
5357 |
+
function add_media_row_actions( array $actions, $post ) {
|
5358 |
return $actions;
|
5359 |
}
|
5360 |
|
5443 |
/**
|
5444 |
* Get ACL for intermediate size.
|
5445 |
*
|
5446 |
+
* @param int $attachment_id
|
5447 |
+
* @param string $size
|
5448 |
+
* @param string $bucket Optional bucket that ACL is potentially to be used with.
|
5449 |
+
* @param Media_Library_Item|null $as3cf_item Optional item.
|
5450 |
*
|
5451 |
+
* @return string|null
|
5452 |
*/
|
5453 |
+
public function get_acl_for_intermediate_size( $attachment_id, $size, $bucket = null, Media_Library_Item $as3cf_item = null ) {
|
5454 |
+
if ( empty( $as3cf_item ) ) {
|
5455 |
+
$as3cf_item = Media_Library_Item::get_by_source_id( $attachment_id );
|
5456 |
+
}
|
5457 |
+
|
5458 |
+
$acl = null;
|
5459 |
+
|
5460 |
+
if ( $this->use_acl_for_intermediate_size( $attachment_id, $size, $bucket, $as3cf_item ) ) {
|
5461 |
+
$acl = $this->get_storage_provider()->get_default_acl();
|
5462 |
+
|
5463 |
+
if ( ! empty( $as3cf_item ) ) {
|
5464 |
+
$acl = $as3cf_item->is_private_size( $size ) ? $this->get_storage_provider()->get_private_acl() : $this->get_storage_provider()->get_default_acl();
|
5465 |
+
}
|
5466 |
+
}
|
5467 |
+
|
5468 |
+
return $acl;
|
5469 |
+
}
|
5470 |
+
|
5471 |
+
/**
|
5472 |
+
* Are ACLs in use for intermediate size on bucket?
|
5473 |
+
*
|
5474 |
+
* @param int $attachment_id
|
5475 |
+
* @param string $size
|
5476 |
+
* @param string $bucket Optional bucket that ACL is potentially to be used with.
|
5477 |
+
* @param Media_Library_Item|null $as3cf_item Optional item.
|
5478 |
+
*
|
5479 |
+
* @return bool
|
5480 |
+
*/
|
5481 |
+
public function use_acl_for_intermediate_size( $attachment_id, $size, $bucket = null, Media_Library_Item $as3cf_item = null ) {
|
5482 |
+
if ( empty( $as3cf_item ) ) {
|
5483 |
+
$as3cf_item = Media_Library_Item::get_by_source_id( $attachment_id );
|
5484 |
+
}
|
5485 |
+
|
5486 |
+
if ( empty( $bucket ) ) {
|
5487 |
+
$bucket = empty( $as3cf_item ) ? null : $as3cf_item->bucket();
|
5488 |
+
}
|
5489 |
+
|
5490 |
+
if ( empty( $bucket ) ) {
|
5491 |
+
$bucket = $this->get_setting( 'bucket', null );
|
5492 |
+
}
|
5493 |
+
|
5494 |
+
$use_acl = apply_filters( 'as3cf_use_bucket_acls_for_intermediate_size', $this->get_setting( 'use-bucket-acls', true ), $attachment_id, $size, $bucket, $as3cf_item );
|
5495 |
+
$use_private_prefix = apply_filters( 'as3cf_enable_signed_urls_for_intermediate_size', $this->private_prefix_enabled(), $attachment_id, $size, $bucket, $as3cf_item );
|
5496 |
|
5497 |
+
// If signed custom URLs are in play, and we have a private object, usually you can not use ACLs.
|
5498 |
+
if ( $use_acl && $use_private_prefix && ! empty( $as3cf_item ) && $as3cf_item->is_private_size( $size ) ) {
|
5499 |
+
$use_acl = false;
|
5500 |
}
|
5501 |
|
5502 |
+
// Allow complete override if signed custom URLs and ACLs do play nice together some how, or other factors in play.
|
5503 |
+
return apply_filters( 'as3cf_use_acl_for_intermediate_size', $use_acl, $attachment_id, $size, $bucket, $as3cf_item );
|
5504 |
}
|
5505 |
|
5506 |
/**
|
5607 |
);
|
5608 |
$this->notices->add_notice( $message, $args );
|
5609 |
|
5610 |
+
if ( is_a( $this->get_storage_provider(), '\DeliciousBrains\WP_Offload_Media\Providers\Storage\AWS_Provider' ) && $this->get_storage_provider()->needs_access_keys() ) {
|
5611 |
// Have access keys been defined in still active AWS plugin's database settings?
|
5612 |
$aws_settings = get_site_option( 'aws_settings' );
|
5613 |
|
5676 |
|
5677 |
return $data;
|
5678 |
}
|
5679 |
+
|
5680 |
+
/**
|
5681 |
+
* Is there an upgrade in progress?
|
5682 |
+
*
|
5683 |
+
* @return bool
|
5684 |
+
*/
|
5685 |
+
public function is_upgrading() {
|
5686 |
+
return Upgrade::is_locked();
|
5687 |
+
}
|
5688 |
+
|
5689 |
+
/**
|
5690 |
+
* Do current settings allow for private prefix to be used?
|
5691 |
+
*
|
5692 |
+
* @return bool
|
5693 |
+
*/
|
5694 |
+
public function private_prefix_enabled() {
|
5695 |
+
if (
|
5696 |
+
$this->get_setting( 'enable-delivery-domain', false ) &&
|
5697 |
+
$this->get_setting( 'enable-signed-urls', false ) &&
|
5698 |
+
! empty( $this->get_setting( 'signed-urls-object-prefix' ) )
|
5699 |
+
) {
|
5700 |
+
return true;
|
5701 |
+
}
|
5702 |
+
|
5703 |
+
return false;
|
5704 |
+
}
|
5705 |
}
|
@@ -75,7 +75,7 @@ abstract class AS3CF_Filter {
|
|
75 |
$url = $this->get_url( $attachment['attachment_id'] );
|
76 |
|
77 |
if ( $url ) {
|
78 |
-
$value[ $key ]['file'] = $
|
79 |
}
|
80 |
}
|
81 |
|
@@ -501,7 +501,7 @@ abstract class AS3CF_Filter {
|
|
501 |
return false;
|
502 |
}
|
503 |
|
504 |
-
$base_url =
|
505 |
$basename = wp_basename( $base_url );
|
506 |
|
507 |
// Add full size URL
|
@@ -509,10 +509,10 @@ abstract class AS3CF_Filter {
|
|
509 |
|
510 |
// Add additional image size URLs
|
511 |
foreach ( $meta['sizes'] as $size ) {
|
512 |
-
$base_urls[] = str_replace( $basename,
|
513 |
}
|
514 |
|
515 |
-
$url =
|
516 |
|
517 |
if ( in_array( $url, $base_urls ) ) {
|
518 |
// Match found, return true
|
@@ -590,10 +590,10 @@ abstract class AS3CF_Filter {
|
|
590 |
return null;
|
591 |
}
|
592 |
|
593 |
-
$basename =
|
594 |
|
595 |
foreach ( $meta['sizes'] as $size => $file ) {
|
596 |
-
if ( $basename ===
|
597 |
return $size;
|
598 |
}
|
599 |
}
|
75 |
$url = $this->get_url( $attachment['attachment_id'] );
|
76 |
|
77 |
if ( $url ) {
|
78 |
+
$value[ $key ]['file'] = $url;
|
79 |
}
|
80 |
}
|
81 |
|
501 |
return false;
|
502 |
}
|
503 |
|
504 |
+
$base_url = AS3CF_Utils::encode_filename_in_path( AS3CF_Utils::reduce_url( $this->get_base_url( $attachment_id ) ) );
|
505 |
$basename = wp_basename( $base_url );
|
506 |
|
507 |
// Add full size URL
|
509 |
|
510 |
// Add additional image size URLs
|
511 |
foreach ( $meta['sizes'] as $size ) {
|
512 |
+
$base_urls[] = str_replace( $basename, AS3CF_Utils::encode_filename_in_path( $size['file'] ), $base_url );
|
513 |
}
|
514 |
|
515 |
+
$url = AS3CF_Utils::encode_filename_in_path( AS3CF_Utils::reduce_url( $url ) );
|
516 |
|
517 |
if ( in_array( $url, $base_urls ) ) {
|
518 |
// Match found, return true
|
590 |
return null;
|
591 |
}
|
592 |
|
593 |
+
$basename = AS3CF_Utils::encode_filename_in_path( wp_basename( $this->as3cf->maybe_remove_query_string( $url ) ) );
|
594 |
|
595 |
foreach ( $meta['sizes'] as $size => $file ) {
|
596 |
+
if ( $basename === AS3CF_Utils::encode_filename_in_path( $file['file'] ) ) {
|
597 |
return $size;
|
598 |
}
|
599 |
}
|
@@ -350,8 +350,7 @@ class AS3CF_Notices {
|
|
350 |
* @param string|bool $tab
|
351 |
*/
|
352 |
protected function maybe_show_notice( $notice, $dismissed_notices, $tab ) {
|
353 |
-
$
|
354 |
-
if ( $notice['only_show_in_settings'] && false === strpos( strval( $screen->id ), $this->as3cf->hook_suffix ) ) {
|
355 |
return;
|
356 |
}
|
357 |
|
350 |
* @param string|bool $tab
|
351 |
*/
|
352 |
protected function maybe_show_notice( $notice, $dismissed_notices, $tab ) {
|
353 |
+
if ( $notice['only_show_in_settings'] && ! $this->as3cf->our_screen() ) {
|
|
|
354 |
return;
|
355 |
}
|
356 |
|
@@ -117,6 +117,13 @@ abstract class AS3CF_Plugin_Base {
|
|
117 |
$saved_settings = get_site_option( static::SETTINGS_KEY );
|
118 |
$this->settings = $this->filter_settings( $saved_settings );
|
119 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
// If defined settings keys have changed since last time settings were saved to database, re-save to remove the new keys.
|
121 |
if ( ! empty( $saved_settings ) && ! empty( $this->defined_settings ) && ! empty( array_intersect_key( $saved_settings, $this->defined_settings ) ) ) {
|
122 |
$this->save_settings();
|
@@ -319,6 +326,24 @@ abstract class AS3CF_Plugin_Base {
|
|
319 |
return array();
|
320 |
}
|
321 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
322 |
/**
|
323 |
* Sanitize a setting value, maybe.
|
324 |
*
|
@@ -342,6 +367,19 @@ abstract class AS3CF_Plugin_Base {
|
|
342 |
}
|
343 |
} else {
|
344 |
$value = sanitize_text_field( $value );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
345 |
}
|
346 |
|
347 |
return $value;
|
117 |
$saved_settings = get_site_option( static::SETTINGS_KEY );
|
118 |
$this->settings = $this->filter_settings( $saved_settings );
|
119 |
|
120 |
+
// Now that we have merged database and defined settings, sanitize them before use.
|
121 |
+
if ( ! empty( $this->settings ) ) {
|
122 |
+
foreach ( $this->settings as $key => $val ) {
|
123 |
+
$this->settings[ $key ] = $this->sanitize_setting( $key, $val );
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
// If defined settings keys have changed since last time settings were saved to database, re-save to remove the new keys.
|
128 |
if ( ! empty( $saved_settings ) && ! empty( $this->defined_settings ) && ! empty( array_intersect_key( $saved_settings, $this->defined_settings ) ) ) {
|
129 |
$this->save_settings();
|
326 |
return array();
|
327 |
}
|
328 |
|
329 |
+
/**
|
330 |
+
* List of settings that should be treated as paths.
|
331 |
+
*
|
332 |
+
* @return array
|
333 |
+
*/
|
334 |
+
function get_path_format_settings() {
|
335 |
+
return array();
|
336 |
+
}
|
337 |
+
|
338 |
+
/**
|
339 |
+
* List of settings that should be treated as directory paths.
|
340 |
+
*
|
341 |
+
* @return array
|
342 |
+
*/
|
343 |
+
function get_prefix_format_settings() {
|
344 |
+
return array();
|
345 |
+
}
|
346 |
+
|
347 |
/**
|
348 |
* Sanitize a setting value, maybe.
|
349 |
*
|
367 |
}
|
368 |
} else {
|
369 |
$value = sanitize_text_field( $value );
|
370 |
+
|
371 |
+
// Make sure path setting is absolute and not just "/".
|
372 |
+
// But not on Windows as it can have various forms of path, e.g. C:\Sites and \\shared\sites.
|
373 |
+
if ( '/' === DIRECTORY_SEPARATOR && in_array( $key, $this->get_path_format_settings() ) ) {
|
374 |
+
$value = trim( AS3CF_Utils::unleadingslashit( $value ) );
|
375 |
+
$value = empty( $value ) ? '' : AS3CF_Utils::leadingslashit( $value );
|
376 |
+
}
|
377 |
+
|
378 |
+
// Make sure prefix setting is relative with trailing slash for visibility.
|
379 |
+
if ( in_array( $key, $this->get_prefix_format_settings() ) ) {
|
380 |
+
$value = trim( untrailingslashit( $value ) );
|
381 |
+
$value = empty( $value ) ? '' : AS3CF_Utils::trailingslash_prefix( $value );
|
382 |
+
}
|
383 |
}
|
384 |
|
385 |
return $value;
|
@@ -10,7 +10,7 @@
|
|
10 |
*/
|
11 |
|
12 |
use DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item;
|
13 |
-
use DeliciousBrains\WP_Offload_Media\Providers\
|
14 |
|
15 |
// Exit if accessed directly
|
16 |
if ( ! defined( 'ABSPATH' ) ) {
|
@@ -101,6 +101,7 @@ class AS3CF_Plugin_Compatibility {
|
|
101 |
* /wp-includes/class-wp-image-editor.php
|
102 |
*/
|
103 |
add_action( 'as3cf_pre_upload_attachment', array( $this, 'image_editor_remove_files' ), 10, 3 );
|
|
|
104 |
add_filter( 'as3cf_get_attached_file', array( $this, 'image_editor_download_file' ), 10, 4 );
|
105 |
add_filter( 'as3cf_upload_attachment_local_files_to_remove', array( $this, 'image_editor_remove_original_image' ), 10, 3 );
|
106 |
add_filter( 'as3cf_get_attached_file', array( $this, 'customizer_crop_download_file' ), 10, 4 );
|
@@ -343,7 +344,7 @@ class AS3CF_Plugin_Compatibility {
|
|
343 |
$as3cf_item->source_id(),
|
344 |
$as3cf_item->source_path(),
|
345 |
wp_basename( $as3cf_item->original_source_path() ),
|
346 |
-
$as3cf_item->
|
347 |
$as3cf_item->id()
|
348 |
);
|
349 |
|
@@ -369,7 +370,7 @@ class AS3CF_Plugin_Compatibility {
|
|
369 |
}
|
370 |
|
371 |
/**
|
372 |
-
* Allow the WordPress Image Editor to edit files that have been copied to
|
373 |
* but removed from the local server, by copying them back temporarily
|
374 |
*
|
375 |
* @param string $url
|
@@ -396,12 +397,12 @@ class AS3CF_Plugin_Compatibility {
|
|
396 |
$as3cf_item->provider(),
|
397 |
$as3cf_item->region(),
|
398 |
$as3cf_item->bucket(),
|
399 |
-
|
400 |
$as3cf_item->is_private(),
|
401 |
$as3cf_item->source_id(),
|
402 |
$as3cf_item->source_path(),
|
403 |
wp_basename( $as3cf_item->original_source_path() ),
|
404 |
-
$as3cf_item->
|
405 |
$as3cf_item->id()
|
406 |
);
|
407 |
$orig_file = dirname( $file ) . '/' . $original_filename;
|
@@ -413,7 +414,7 @@ class AS3CF_Plugin_Compatibility {
|
|
413 |
if ( $provider_file = $this->copy_provider_file_to_server( $as3cf_item, $file ) ) {
|
414 |
// Return the file if successfully downloaded from bucket.
|
415 |
return $provider_file;
|
416 |
-
}
|
417 |
}
|
418 |
|
419 |
$action = filter_input( INPUT_GET, 'action' ) ?: filter_input( INPUT_POST, 'action' );
|
@@ -425,7 +426,7 @@ class AS3CF_Plugin_Compatibility {
|
|
425 |
if ( $provider_file = $this->copy_provider_file_to_server( $as3cf_item, $file ) ) {
|
426 |
// Return the file if successfully downloaded from bucket.
|
427 |
return $provider_file;
|
428 |
-
}
|
429 |
}
|
430 |
}
|
431 |
}
|
@@ -586,11 +587,13 @@ class AS3CF_Plugin_Compatibility {
|
|
586 |
* @return string|bool File if downloaded, false on failure
|
587 |
*/
|
588 |
public function copy_provider_file_to_server( Media_Library_Item $as3cf_item, $file ) {
|
|
|
|
|
589 |
// Make sure the directory exists
|
590 |
$dir = dirname( $file );
|
591 |
if ( ! wp_mkdir_p( $dir ) ) {
|
592 |
$error_message = sprintf( __( 'The local directory %s does not exist and could not be created.', 'amazon-s3-and-cloudfront' ), $dir );
|
593 |
-
AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from the bucket: %s', 'amazon-s3-and-cloudfront' ), $as3cf_item->
|
594 |
|
595 |
return false;
|
596 |
}
|
@@ -598,11 +601,11 @@ class AS3CF_Plugin_Compatibility {
|
|
598 |
try {
|
599 |
$this->as3cf->get_provider_client( $as3cf_item->region(), true )->get_object( array(
|
600 |
'Bucket' => $as3cf_item->bucket(),
|
601 |
-
'Key' => $as3cf_item->
|
602 |
'SaveAs' => $file,
|
603 |
) );
|
604 |
} catch ( Exception $e ) {
|
605 |
-
AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from the bucket: %s', 'amazon-s3-and-cloudfront' ), $as3cf_item->
|
606 |
|
607 |
return false;
|
608 |
}
|
@@ -615,7 +618,7 @@ class AS3CF_Plugin_Compatibility {
|
|
615 |
*
|
616 |
* @param string $region
|
617 |
*
|
618 |
-
* @return
|
619 |
* @throws Exception
|
620 |
*/
|
621 |
protected function register_stream_wrapper( $region ) {
|
@@ -658,7 +661,7 @@ class AS3CF_Plugin_Compatibility {
|
|
658 |
$client = $this->register_stream_wrapper( $as3cf_item->region() );
|
659 |
|
660 |
if ( ! empty( $client ) ) {
|
661 |
-
return $client->prepare_stream_wrapper_file( $as3cf_item->region(), $as3cf_item->bucket(), $as3cf_item->
|
662 |
}
|
663 |
|
664 |
return $url;
|
@@ -683,12 +686,12 @@ class AS3CF_Plugin_Compatibility {
|
|
683 |
) {
|
684 |
// Ensure each filename is encoded the same way as URL, slightly fixed up for wp_basename() manipulation compatibility.
|
685 |
if ( ! empty( $data['file'] ) ) {
|
686 |
-
$data['file'] =
|
687 |
}
|
688 |
|
689 |
if ( ! empty( $data['sizes'] ) ) {
|
690 |
$data['sizes'] = array_map( function ( $size ) {
|
691 |
-
$size['file'] =
|
692 |
|
693 |
return $size;
|
694 |
}, $data['sizes'] );
|
@@ -813,9 +816,9 @@ class AS3CF_Plugin_Compatibility {
|
|
813 |
return $image_meta;
|
814 |
}
|
815 |
|
816 |
-
$image_basename =
|
817 |
|
818 |
-
if ( false === strpos(
|
819 |
// Not the correct attachment, abort
|
820 |
return $image_meta;
|
821 |
}
|
@@ -828,7 +831,7 @@ class AS3CF_Plugin_Compatibility {
|
|
828 |
// Ensure each size filename is encoded the same way as URL.
|
829 |
if ( ! empty( $image_meta['sizes'] ) ) {
|
830 |
$image_meta['sizes'] = array_map( function ( $size ) {
|
831 |
-
$size['file'] =
|
832 |
|
833 |
return $size;
|
834 |
}, $image_meta['sizes'] );
|
10 |
*/
|
11 |
|
12 |
use DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item;
|
13 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Storage\Storage_Provider;
|
14 |
|
15 |
// Exit if accessed directly
|
16 |
if ( ! defined( 'ABSPATH' ) ) {
|
101 |
* /wp-includes/class-wp-image-editor.php
|
102 |
*/
|
103 |
add_action( 'as3cf_pre_upload_attachment', array( $this, 'image_editor_remove_files' ), 10, 3 );
|
104 |
+
add_filter( 'as3cf_get_attached_file_noop', array( $this, 'image_editor_download_file' ), 10, 4 );
|
105 |
add_filter( 'as3cf_get_attached_file', array( $this, 'image_editor_download_file' ), 10, 4 );
|
106 |
add_filter( 'as3cf_upload_attachment_local_files_to_remove', array( $this, 'image_editor_remove_original_image' ), 10, 3 );
|
107 |
add_filter( 'as3cf_get_attached_file', array( $this, 'customizer_crop_download_file' ), 10, 4 );
|
344 |
$as3cf_item->source_id(),
|
345 |
$as3cf_item->source_path(),
|
346 |
wp_basename( $as3cf_item->original_source_path() ),
|
347 |
+
$as3cf_item->extra_info(),
|
348 |
$as3cf_item->id()
|
349 |
);
|
350 |
|
370 |
}
|
371 |
|
372 |
/**
|
373 |
+
* Allow the WordPress Image Editor to edit files that have been copied to provider
|
374 |
* but removed from the local server, by copying them back temporarily
|
375 |
*
|
376 |
* @param string $url
|
397 |
$as3cf_item->provider(),
|
398 |
$as3cf_item->region(),
|
399 |
$as3cf_item->bucket(),
|
400 |
+
$as3cf_item->normalized_path_dir() . $original_filename,
|
401 |
$as3cf_item->is_private(),
|
402 |
$as3cf_item->source_id(),
|
403 |
$as3cf_item->source_path(),
|
404 |
wp_basename( $as3cf_item->original_source_path() ),
|
405 |
+
$as3cf_item->extra_info(),
|
406 |
$as3cf_item->id()
|
407 |
);
|
408 |
$orig_file = dirname( $file ) . '/' . $original_filename;
|
414 |
if ( $provider_file = $this->copy_provider_file_to_server( $as3cf_item, $file ) ) {
|
415 |
// Return the file if successfully downloaded from bucket.
|
416 |
return $provider_file;
|
417 |
+
}
|
418 |
}
|
419 |
|
420 |
$action = filter_input( INPUT_GET, 'action' ) ?: filter_input( INPUT_POST, 'action' );
|
426 |
if ( $provider_file = $this->copy_provider_file_to_server( $as3cf_item, $file ) ) {
|
427 |
// Return the file if successfully downloaded from bucket.
|
428 |
return $provider_file;
|
429 |
+
}
|
430 |
}
|
431 |
}
|
432 |
}
|
587 |
* @return string|bool File if downloaded, false on failure
|
588 |
*/
|
589 |
public function copy_provider_file_to_server( Media_Library_Item $as3cf_item, $file ) {
|
590 |
+
$filename = wp_basename( $file );
|
591 |
+
|
592 |
// Make sure the directory exists
|
593 |
$dir = dirname( $file );
|
594 |
if ( ! wp_mkdir_p( $dir ) ) {
|
595 |
$error_message = sprintf( __( 'The local directory %s does not exist and could not be created.', 'amazon-s3-and-cloudfront' ), $dir );
|
596 |
+
AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from the bucket: %s', 'amazon-s3-and-cloudfront' ), $as3cf_item->key( $filename ), $error_message ) );
|
597 |
|
598 |
return false;
|
599 |
}
|
601 |
try {
|
602 |
$this->as3cf->get_provider_client( $as3cf_item->region(), true )->get_object( array(
|
603 |
'Bucket' => $as3cf_item->bucket(),
|
604 |
+
'Key' => $as3cf_item->key( $filename ),
|
605 |
'SaveAs' => $file,
|
606 |
) );
|
607 |
} catch ( Exception $e ) {
|
608 |
+
AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from the bucket: %s', 'amazon-s3-and-cloudfront' ), $as3cf_item->key( $filename ), $e->getMessage() ) );
|
609 |
|
610 |
return false;
|
611 |
}
|
618 |
*
|
619 |
* @param string $region
|
620 |
*
|
621 |
+
* @return Storage_Provider|null
|
622 |
* @throws Exception
|
623 |
*/
|
624 |
protected function register_stream_wrapper( $region ) {
|
661 |
$client = $this->register_stream_wrapper( $as3cf_item->region() );
|
662 |
|
663 |
if ( ! empty( $client ) ) {
|
664 |
+
return $client->prepare_stream_wrapper_file( $as3cf_item->region(), $as3cf_item->bucket(), $as3cf_item->key() );
|
665 |
}
|
666 |
|
667 |
return $url;
|
686 |
) {
|
687 |
// Ensure each filename is encoded the same way as URL, slightly fixed up for wp_basename() manipulation compatibility.
|
688 |
if ( ! empty( $data['file'] ) ) {
|
689 |
+
$data['file'] = AS3CF_Utils::encode_filename_in_path( $data['file'] );
|
690 |
}
|
691 |
|
692 |
if ( ! empty( $data['sizes'] ) ) {
|
693 |
$data['sizes'] = array_map( function ( $size ) {
|
694 |
+
$size['file'] = AS3CF_Utils::encode_filename_in_path( $size['file'] );
|
695 |
|
696 |
return $size;
|
697 |
}, $data['sizes'] );
|
816 |
return $image_meta;
|
817 |
}
|
818 |
|
819 |
+
$image_basename = AS3CF_Utils::encode_filename_in_path( wp_basename( $image_meta['file'] ) );
|
820 |
|
821 |
+
if ( false === strpos( AS3CF_Utils::encode_filename_in_path( $as3cf_item->path() ), $image_basename ) ) {
|
822 |
// Not the correct attachment, abort
|
823 |
return $image_meta;
|
824 |
}
|
831 |
// Ensure each size filename is encoded the same way as URL.
|
832 |
if ( ! empty( $image_meta['sizes'] ) ) {
|
833 |
$image_meta['sizes'] = array_map( function ( $size ) {
|
834 |
+
$size['file'] = AS3CF_Utils::encode_filename_in_path( $size['file'] );
|
835 |
|
836 |
return $size;
|
837 |
}, $image_meta['sizes'] );
|
@@ -8,9 +8,9 @@
|
|
8 |
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
9 |
*/
|
10 |
|
11 |
-
// Exit if accessed directly
|
12 |
use DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item;
|
13 |
|
|
|
14 |
if ( ! defined( 'ABSPATH' ) ) {
|
15 |
exit;
|
16 |
}
|
@@ -45,7 +45,40 @@ if ( ! class_exists( 'AS3CF_Utils' ) ) {
|
|
45 |
* @return string
|
46 |
*/
|
47 |
public static function trailingslash_prefix( $string ) {
|
48 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
}
|
50 |
|
51 |
/**
|
@@ -267,10 +300,9 @@ if ( ! class_exists( 'AS3CF_Utils' ) ) {
|
|
267 |
* @return array
|
268 |
*/
|
269 |
public static function get_attachment_edited_keys( $attachment_id, Media_Library_Item $as3cf_item ) {
|
270 |
-
$
|
271 |
-
$paths
|
272 |
-
|
273 |
-
return array( 'Key' => $prefix . wp_basename( $path ) );
|
274 |
}, $paths );
|
275 |
|
276 |
return $paths;
|
@@ -574,5 +606,107 @@ if ( ! class_exists( 'AS3CF_Utils' ) ) {
|
|
574 |
|
575 |
return $paths;
|
576 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
577 |
}
|
578 |
}
|
8 |
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
9 |
*/
|
10 |
|
|
|
11 |
use DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item;
|
12 |
|
13 |
+
// Exit if accessed directly
|
14 |
if ( ! defined( 'ABSPATH' ) ) {
|
15 |
exit;
|
16 |
}
|
45 |
* @return string
|
46 |
*/
|
47 |
public static function trailingslash_prefix( $string ) {
|
48 |
+
return static::unleadingslashit( trailingslashit( trim( $string ) ) );
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Ensure string has a leading slash, like in absolute paths.
|
53 |
+
*
|
54 |
+
* @param $string
|
55 |
+
*
|
56 |
+
* @return string
|
57 |
+
*/
|
58 |
+
public static function leadingslashit( $string ) {
|
59 |
+
return '/' . static::unleadingslashit( $string );
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Ensure string has no leading slash, like in relative paths.
|
64 |
+
*
|
65 |
+
* @param $string
|
66 |
+
*
|
67 |
+
* @return string
|
68 |
+
*/
|
69 |
+
public static function unleadingslashit( $string ) {
|
70 |
+
return ltrim( trim( $string ), '/\\' );
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Ensure string has a leading and trailing slash, like in absolute directory paths.
|
75 |
+
*
|
76 |
+
* @param $string
|
77 |
+
*
|
78 |
+
* @return string
|
79 |
+
*/
|
80 |
+
public static function leadingtrailingslashit( $string ) {
|
81 |
+
return static::leadingslashit( trailingslashit( trim( $string ) ) );
|
82 |
}
|
83 |
|
84 |
/**
|
300 |
* @return array
|
301 |
*/
|
302 |
public static function get_attachment_edited_keys( $attachment_id, Media_Library_Item $as3cf_item ) {
|
303 |
+
$paths = self::get_attachment_edited_file_paths( $attachment_id );
|
304 |
+
$paths = array_map( function ( $path ) use ( $as3cf_item ) {
|
305 |
+
return array( 'Key' => $as3cf_item->key( wp_basename( $path ) ) );
|
|
|
306 |
}, $paths );
|
307 |
|
308 |
return $paths;
|
606 |
|
607 |
return $paths;
|
608 |
}
|
609 |
+
|
610 |
+
/**
|
611 |
+
* Convert dimensions to size
|
612 |
+
*
|
613 |
+
* @param int $attachment_id
|
614 |
+
* @param array $dimensions
|
615 |
+
*
|
616 |
+
* @return null|string
|
617 |
+
*/
|
618 |
+
public static function convert_dimensions_to_size_name( $attachment_id, $dimensions ) {
|
619 |
+
$w = ( isset( $dimensions[0] ) && $dimensions[0] > 0 ) ? $dimensions[0] : 1;
|
620 |
+
$h = ( isset( $dimensions[1] ) && $dimensions[1] > 0 ) ? $dimensions[1] : 1;
|
621 |
+
$original_aspect_ratio = $w / $h;
|
622 |
+
$meta = wp_get_attachment_metadata( $attachment_id );
|
623 |
+
|
624 |
+
if ( ! isset( $meta['sizes'] ) || empty( $meta['sizes'] ) ) {
|
625 |
+
return null;
|
626 |
+
}
|
627 |
+
|
628 |
+
$sizes = $meta['sizes'];
|
629 |
+
uasort( $sizes, function ( $a, $b ) {
|
630 |
+
// Order by image area
|
631 |
+
return ( $a['width'] * $a['height'] ) - ( $b['width'] * $b['height'] );
|
632 |
+
} );
|
633 |
+
|
634 |
+
$nearest_matches = array();
|
635 |
+
|
636 |
+
foreach ( $sizes as $size => $value ) {
|
637 |
+
if ( $w > $value['width'] || $h > $value['height'] ) {
|
638 |
+
continue;
|
639 |
+
}
|
640 |
+
|
641 |
+
$aspect_ratio = $value['width'] / $value['height'];
|
642 |
+
|
643 |
+
if ( $aspect_ratio === $original_aspect_ratio ) {
|
644 |
+
return $size;
|
645 |
+
}
|
646 |
+
|
647 |
+
$nearest_matches[] = $size;
|
648 |
+
}
|
649 |
+
|
650 |
+
// Return nearest match
|
651 |
+
if ( ! empty( $nearest_matches ) ) {
|
652 |
+
return $nearest_matches[0];
|
653 |
+
}
|
654 |
+
|
655 |
+
return null;
|
656 |
+
}
|
657 |
+
|
658 |
+
/**
|
659 |
+
* Maybe convert size to string
|
660 |
+
*
|
661 |
+
* @param int $attachment_id
|
662 |
+
* @param mixed $size
|
663 |
+
*
|
664 |
+
* @return null|string
|
665 |
+
*/
|
666 |
+
public static function maybe_convert_size_to_string( $attachment_id, $size ) {
|
667 |
+
if ( is_array( $size ) ) {
|
668 |
+
return static::convert_dimensions_to_size_name( $attachment_id, $size );
|
669 |
+
}
|
670 |
+
|
671 |
+
return $size;
|
672 |
+
}
|
673 |
+
|
674 |
+
/**
|
675 |
+
* Encode file names according to RFC 3986 when generating urls
|
676 |
+
* As per Amazon https://forums.aws.amazon.com/thread.jspa?threadID=55746#jive-message-244233
|
677 |
+
*
|
678 |
+
* @param string $file
|
679 |
+
*
|
680 |
+
* @return string Encoded filename
|
681 |
+
*/
|
682 |
+
public static function encode_filename_in_path( $file ) {
|
683 |
+
$url = parse_url( $file );
|
684 |
+
|
685 |
+
if ( ! isset( $url['path'] ) ) {
|
686 |
+
// Can't determine path, return original
|
687 |
+
return $file;
|
688 |
+
}
|
689 |
+
|
690 |
+
if ( isset( $url['query'] ) ) {
|
691 |
+
// Manually strip query string, as passing $url['path'] to basename results in corrupt � characters
|
692 |
+
$file_name = wp_basename( str_replace( '?' . $url['query'], '', $file ) );
|
693 |
+
} else {
|
694 |
+
$file_name = wp_basename( $file );
|
695 |
+
}
|
696 |
+
|
697 |
+
if ( false !== strpos( $file_name, '%' ) ) {
|
698 |
+
// File name already encoded, return original
|
699 |
+
return $file;
|
700 |
+
}
|
701 |
+
|
702 |
+
$encoded_file_name = rawurlencode( $file_name );
|
703 |
+
|
704 |
+
if ( $file_name === $encoded_file_name ) {
|
705 |
+
// File name doesn't need encoding, return original
|
706 |
+
return $file;
|
707 |
+
}
|
708 |
+
|
709 |
+
return str_replace( $file_name, $encoded_file_name, $file );
|
710 |
+
}
|
711 |
}
|
712 |
}
|
@@ -27,6 +27,8 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
|
|
27 |
// Widgets
|
28 |
add_filter( 'widget_form_callback', array( $this, 'filter_widget_display' ), 10, 2 );
|
29 |
add_filter( 'widget_display_callback', array( $this, 'filter_widget_display' ), 10, 2 );
|
|
|
|
|
30 |
}
|
31 |
|
32 |
/**
|
@@ -200,35 +202,19 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
|
|
200 |
* @return bool|int
|
201 |
*/
|
202 |
protected function get_attachment_id_from_url( $url ) {
|
203 |
-
|
204 |
-
|
205 |
-
$full_url = AS3CF_Utils::remove_scheme( AS3CF_Utils::remove_size_from_filename( $url ) );
|
206 |
-
|
207 |
-
if ( isset( $this->query_cache[ $full_url ] ) ) {
|
208 |
-
// ID already cached, return
|
209 |
-
return $this->query_cache[ $full_url ];
|
210 |
-
}
|
211 |
-
|
212 |
-
$path = AS3CF_Utils::decode_filename_in_path( ltrim( str_replace( $this->get_bare_upload_base_urls(), '', $full_url ), '/' ) );
|
213 |
-
|
214 |
-
$sql = $wpdb->prepare( "
|
215 |
-
SELECT post_id FROM {$wpdb->postmeta}
|
216 |
-
WHERE meta_key = %s
|
217 |
-
AND meta_value = %s
|
218 |
-
", '_wp_attached_file', $path );
|
219 |
-
|
220 |
-
$result = $wpdb->get_var( $sql );
|
221 |
-
|
222 |
-
if ( is_null( $result ) ) {
|
223 |
-
// Attachment ID not found, return false
|
224 |
-
$this->query_cache[ $full_url ] = false;
|
225 |
|
|
|
226 |
return false;
|
227 |
}
|
228 |
|
229 |
-
|
|
|
|
|
|
|
|
|
230 |
|
231 |
-
return
|
232 |
}
|
233 |
|
234 |
/**
|
@@ -249,11 +235,22 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
|
|
249 |
$urls = array( $urls );
|
250 |
}
|
251 |
|
|
|
252 |
$paths = array();
|
253 |
$full_urls = array();
|
254 |
|
|
|
255 |
foreach ( $urls as $url ) {
|
256 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
|
258 |
if ( isset( $this->query_cache[ $full_url ] ) ) {
|
259 |
// ID already cached, use it.
|
@@ -296,9 +293,9 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
|
|
296 |
}
|
297 |
|
298 |
// No more attachment IDs found, set remaining results as false.
|
299 |
-
if ( count( $
|
300 |
-
foreach ( $full_urls as $full_url => $
|
301 |
-
foreach ( $
|
302 |
if ( ! array_key_exists( $url, $results ) ) {
|
303 |
$this->query_cache[ $full_url ] = false;
|
304 |
$results[ $url ] = false;
|
@@ -330,7 +327,7 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
|
|
330 |
* @return string
|
331 |
*/
|
332 |
protected function normalize_replace_value( $url ) {
|
333 |
-
return
|
334 |
}
|
335 |
|
336 |
/**
|
@@ -374,4 +371,42 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
|
|
374 |
|
375 |
return $content;
|
376 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
377 |
}
|
27 |
// Widgets
|
28 |
add_filter( 'widget_form_callback', array( $this, 'filter_widget_display' ), 10, 2 );
|
29 |
add_filter( 'widget_display_callback', array( $this, 'filter_widget_display' ), 10, 2 );
|
30 |
+
// Edit Media page
|
31 |
+
add_filter( 'set_url_scheme', array( $this, 'set_url_scheme' ), 10, 3 );
|
32 |
}
|
33 |
|
34 |
/**
|
202 |
* @return bool|int
|
203 |
*/
|
204 |
protected function get_attachment_id_from_url( $url ) {
|
205 |
+
$results = $this->get_attachment_ids_from_urls( array( $url ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
|
207 |
+
if ( empty( $results ) ) {
|
208 |
return false;
|
209 |
}
|
210 |
|
211 |
+
foreach ( $results as $result ) {
|
212 |
+
if ( $result ) {
|
213 |
+
return $result;
|
214 |
+
}
|
215 |
+
}
|
216 |
|
217 |
+
return false;
|
218 |
}
|
219 |
|
220 |
/**
|
235 |
$urls = array( $urls );
|
236 |
}
|
237 |
|
238 |
+
$query_set = array();
|
239 |
$paths = array();
|
240 |
$full_urls = array();
|
241 |
|
242 |
+
// Quickly parse given URLs to add versions without size as we should lookup with size info first as that could be the "full" size.
|
243 |
foreach ( $urls as $url ) {
|
244 |
+
$query_set[] = $url;
|
245 |
+
$size_removed = AS3CF_Utils::remove_size_from_filename( $url );
|
246 |
+
|
247 |
+
if ( $url !== $size_removed ) {
|
248 |
+
$query_set[] = $size_removed;
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
+
foreach ( $query_set as $url ) {
|
253 |
+
$full_url = AS3CF_Utils::remove_scheme( $url );
|
254 |
|
255 |
if ( isset( $this->query_cache[ $full_url ] ) ) {
|
256 |
// ID already cached, use it.
|
293 |
}
|
294 |
|
295 |
// No more attachment IDs found, set remaining results as false.
|
296 |
+
if ( count( $query_set ) !== count( $results ) ) {
|
297 |
+
foreach ( $full_urls as $full_url => $schema_urls ) {
|
298 |
+
foreach ( $schema_urls as $url ) {
|
299 |
if ( ! array_key_exists( $url, $results ) ) {
|
300 |
$this->query_cache[ $full_url ] = false;
|
301 |
$results[ $url ] = false;
|
327 |
* @return string
|
328 |
*/
|
329 |
protected function normalize_replace_value( $url ) {
|
330 |
+
return AS3CF_Utils::encode_filename_in_path( $url );
|
331 |
}
|
332 |
|
333 |
/**
|
371 |
|
372 |
return $content;
|
373 |
}
|
374 |
+
|
375 |
+
/**
|
376 |
+
* Might need to re-fix remote URL's schema if WordPress core has substituted in HTTP but HTTPS is required.
|
377 |
+
*
|
378 |
+
* @param string $url
|
379 |
+
* @param string $scheme
|
380 |
+
* @param string $orig_scheme
|
381 |
+
*
|
382 |
+
* @return string
|
383 |
+
*/
|
384 |
+
public function set_url_scheme( $url, $scheme, $orig_scheme ) {
|
385 |
+
if (
|
386 |
+
$this->as3cf->get_setting( 'force-https' ) &&
|
387 |
+
$this->should_filter_content() &&
|
388 |
+
! $this->url_needs_replacing( $url ) &&
|
389 |
+
'http' === $scheme && empty( $orig_scheme )
|
390 |
+
) {
|
391 |
+
// Check that it's one of ours and not external.
|
392 |
+
$parts = AS3CF_Utils::parse_url( $url );
|
393 |
+
|
394 |
+
if ( empty( $parts['scheme'] ) || empty( $parts['host'] ) || 'http' !== $parts['scheme'] ) {
|
395 |
+
return $url;
|
396 |
+
}
|
397 |
+
|
398 |
+
$ours = false;
|
399 |
+
if ( $this->as3cf->get_setting( 'enable-delivery-domain' ) && $this->as3cf->get_setting( 'delivery-domain', '' ) === $parts['host'] ) {
|
400 |
+
$ours = true;
|
401 |
+
} elseif ( false !== strpos( $parts['host'], $this->as3cf->get_storage_provider()->get_domain() ) ) {
|
402 |
+
$ours = true;
|
403 |
+
}
|
404 |
+
|
405 |
+
if ( $ours ) {
|
406 |
+
return substr_replace( $url, 'https', 0, 4 );
|
407 |
+
}
|
408 |
+
}
|
409 |
+
|
410 |
+
return $url;
|
411 |
+
}
|
412 |
}
|
@@ -113,8 +113,28 @@ class AS3CF_S3_To_Local extends AS3CF_Filter {
|
|
113 |
* @return bool|int
|
114 |
*/
|
115 |
public function get_attachment_id_from_url( $url ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
$full_url = AS3CF_Utils::remove_size_from_filename( $url );
|
117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
// Result for URL already cached in request whether found or not, return it.
|
119 |
if ( isset( $this->query_cache[ $full_url ] ) ) {
|
120 |
return $this->query_cache[ $full_url ];
|
@@ -160,7 +180,7 @@ class AS3CF_S3_To_Local extends AS3CF_Filter {
|
|
160 |
* @return string
|
161 |
*/
|
162 |
protected function normalize_find_value( $url ) {
|
163 |
-
return
|
164 |
}
|
165 |
|
166 |
/**
|
113 |
* @return bool|int
|
114 |
*/
|
115 |
public function get_attachment_id_from_url( $url ) {
|
116 |
+
// Result for sized URL already cached in request, return it.
|
117 |
+
if ( isset( $this->query_cache[ $url ] ) ) {
|
118 |
+
return $this->query_cache[ $url ];
|
119 |
+
}
|
120 |
+
|
121 |
+
$post_id = Media_Library_Item::get_source_id_by_remote_url( $url );
|
122 |
+
|
123 |
+
if ( $post_id ) {
|
124 |
+
$this->query_cache[ $url ] = $post_id;
|
125 |
+
|
126 |
+
return $post_id;
|
127 |
+
}
|
128 |
+
|
129 |
$full_url = AS3CF_Utils::remove_size_from_filename( $url );
|
130 |
|
131 |
+
// If we've already tried to find this URL above because it didn't have a size suffix, cache and return.
|
132 |
+
if ( $url === $full_url ) {
|
133 |
+
$this->query_cache[ $url ] = $post_id;
|
134 |
+
|
135 |
+
return $post_id;
|
136 |
+
}
|
137 |
+
|
138 |
// Result for URL already cached in request whether found or not, return it.
|
139 |
if ( isset( $this->query_cache[ $full_url ] ) ) {
|
140 |
return $this->query_cache[ $full_url ];
|
180 |
* @return string
|
181 |
*/
|
182 |
protected function normalize_find_value( $url ) {
|
183 |
+
return AS3CF_Utils::encode_filename_in_path( $url );
|
184 |
}
|
185 |
|
186 |
/**
|
@@ -485,7 +485,7 @@ abstract class Item {
|
|
485 |
'bucket' => '%s',
|
486 |
'path' => '%s',
|
487 |
'original_path' => '%s',
|
488 |
-
'is_private' => '%
|
489 |
'source_type' => '%s',
|
490 |
'source_id' => '%d',
|
491 |
'source_path' => '%s',
|
@@ -775,7 +775,7 @@ abstract class Item {
|
|
775 |
*
|
776 |
* @return array
|
777 |
*/
|
778 |
-
|
779 |
return unserialize( $this->extra_info );
|
780 |
}
|
781 |
|
@@ -787,7 +787,7 @@ abstract class Item {
|
|
787 |
public function normalized_path_dir() {
|
788 |
$directory = dirname( $this->path );
|
789 |
|
790 |
-
return ( '.' === $directory ) ? '' :
|
791 |
}
|
792 |
|
793 |
/**
|
@@ -840,6 +840,11 @@ abstract class Item {
|
|
840 |
public static function get_source_id_by_remote_url( $url ) {
|
841 |
global $wpdb;
|
842 |
|
|
|
|
|
|
|
|
|
|
|
843 |
$parts = AS3CF_Utils::parse_url( $url );
|
844 |
$path = AS3CF_Utils::decode_filename_in_path( ltrim( $parts['path'], '/' ) );
|
845 |
|
@@ -847,6 +852,25 @@ abstract class Item {
|
|
847 |
if ( false !== strpos( $path, '/' ) ) {
|
848 |
$path = explode( '/', $path );
|
849 |
array_shift( $path );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
850 |
$path = implode( '/', $path );
|
851 |
}
|
852 |
|
@@ -865,11 +889,7 @@ abstract class Item {
|
|
865 |
return false;
|
866 |
}
|
867 |
|
868 |
-
//
|
869 |
-
if ( 1 === count( $results ) ) {
|
870 |
-
return $results[0]->source_id;
|
871 |
-
}
|
872 |
-
|
873 |
$path = ltrim( $parts['path'], '/' );
|
874 |
|
875 |
foreach ( $results as $result ) {
|
@@ -882,6 +902,11 @@ abstract class Item {
|
|
882 |
$match_path = $path;
|
883 |
}
|
884 |
|
|
|
|
|
|
|
|
|
|
|
885 |
// Exact match, return ID.
|
886 |
if ( $as3cf_item->path() === $match_path || $as3cf_item->original_path() === $match_path ) {
|
887 |
return $as3cf_item->source_id();
|
485 |
'bucket' => '%s',
|
486 |
'path' => '%s',
|
487 |
'original_path' => '%s',
|
488 |
+
'is_private' => '%d',
|
489 |
'source_type' => '%s',
|
490 |
'source_id' => '%d',
|
491 |
'source_path' => '%s',
|
775 |
*
|
776 |
* @return array
|
777 |
*/
|
778 |
+
public function extra_info() {
|
779 |
return unserialize( $this->extra_info );
|
780 |
}
|
781 |
|
787 |
public function normalized_path_dir() {
|
788 |
$directory = dirname( $this->path );
|
789 |
|
790 |
+
return ( '.' === $directory ) ? '' : AS3CF_Utils::trailingslash_prefix( $directory );
|
791 |
}
|
792 |
|
793 |
/**
|
840 |
public static function get_source_id_by_remote_url( $url ) {
|
841 |
global $wpdb;
|
842 |
|
843 |
+
/**
|
844 |
+
* @var Amazon_S3_And_CloudFront|\Amazon_S3_And_CloudFront_Pro $as3cf
|
845 |
+
*/
|
846 |
+
global $as3cf;
|
847 |
+
|
848 |
$parts = AS3CF_Utils::parse_url( $url );
|
849 |
$path = AS3CF_Utils::decode_filename_in_path( ltrim( $parts['path'], '/' ) );
|
850 |
|
852 |
if ( false !== strpos( $path, '/' ) ) {
|
853 |
$path = explode( '/', $path );
|
854 |
array_shift( $path );
|
855 |
+
|
856 |
+
// If private prefix enabled, check if first segment and remove it as path/original_path do not include it.
|
857 |
+
// We can't check every possible private prefix as each item may have a unique private prefix.
|
858 |
+
// The only way to do that is with some fancy SQL, but that's not feasible as this particular
|
859 |
+
// SQL query is already troublesome on some sites with badly behaved themes/plugins.
|
860 |
+
if ( count( $path ) && $as3cf->get_delivery_provider()->use_signed_urls_key_file() ) {
|
861 |
+
// We have to be able to handle multi-segment private prefixes such as "private/downloads/".
|
862 |
+
$private_prefixes = explode( '/', untrailingslashit( $as3cf->get_setting( 'signed-urls-object-prefix' ) ) );
|
863 |
+
|
864 |
+
foreach ( $private_prefixes as $private_prefix ) {
|
865 |
+
if ( $private_prefix === $path[0] ) {
|
866 |
+
array_shift( $path );
|
867 |
+
} else {
|
868 |
+
// As soon as we don't have a match stop looking.
|
869 |
+
break;
|
870 |
+
}
|
871 |
+
}
|
872 |
+
}
|
873 |
+
|
874 |
$path = implode( '/', $path );
|
875 |
}
|
876 |
|
889 |
return false;
|
890 |
}
|
891 |
|
892 |
+
// Regardless of whether 1 or many items found, must validate match.
|
|
|
|
|
|
|
|
|
893 |
$path = ltrim( $parts['path'], '/' );
|
894 |
|
895 |
foreach ( $results as $result ) {
|
902 |
$match_path = $path;
|
903 |
}
|
904 |
|
905 |
+
// If item's private prefix matches first segment of URL path, remove it from URL path before checking match.
|
906 |
+
if ( ! empty( $as3cf_item->private_prefix() ) && 0 === strpos( $match_path, $as3cf_item->private_prefix() ) ) {
|
907 |
+
$match_path = ltrim( substr_replace( $match_path, '', 0, strlen( $as3cf_item->private_prefix() ) ), '/' );
|
908 |
+
}
|
909 |
+
|
910 |
// Exact match, return ID.
|
911 |
if ( $as3cf_item->path() === $match_path || $as3cf_item->original_path() === $match_path ) {
|
912 |
return $as3cf_item->source_id();
|
@@ -4,6 +4,7 @@ namespace DeliciousBrains\WP_Offload_Media\Items;
|
|
4 |
|
5 |
use Amazon_S3_And_CloudFront;
|
6 |
use WP_Error;
|
|
|
7 |
|
8 |
class Media_Library_Item extends Item {
|
9 |
private static $attachment_counts = array();
|
@@ -20,32 +21,43 @@ class Media_Library_Item extends Item {
|
|
20 |
* @param int $source_id ID that source has.
|
21 |
* @param string $source_path Path that source uses, could be relative or absolute depending on source.
|
22 |
* @param string $original_filename An optional filename with no path that was previously used for the item.
|
23 |
-
* @param array $
|
|
|
|
|
|
|
|
|
|
|
24 |
* @param null $id Optional Item record ID.
|
25 |
*/
|
26 |
-
public function __construct( $provider, $region, $bucket, $path, $is_private, $source_id, $source_path, $original_filename = null, $
|
27 |
// For Media Library items, the source path should be relative to the Media Library's uploads directory.
|
28 |
$uploads = wp_upload_dir();
|
29 |
|
30 |
if ( false === $uploads['error'] && 0 === strpos( $source_path, $uploads['basedir'] ) ) {
|
31 |
-
$source_path =
|
32 |
}
|
33 |
|
34 |
-
|
35 |
-
|
36 |
-
*/
|
37 |
|
38 |
// Ensure re-hydration is clean.
|
39 |
-
if ( ! empty( $
|
40 |
-
|
41 |
-
|
|
|
|
|
|
|
|
|
42 |
|
43 |
-
|
44 |
-
$private_sizes
|
|
|
|
|
45 |
}
|
46 |
|
47 |
$extra_info = array(
|
48 |
-
'private_sizes'
|
|
|
49 |
);
|
50 |
|
51 |
parent::__construct( $provider, $region, $bucket, $path, $is_private, $source_id, $source_path, $original_filename, $extra_info, $id );
|
@@ -82,6 +94,40 @@ class Media_Library_Item extends Item {
|
|
82 |
return $as3cf_item;
|
83 |
}
|
84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
/**
|
86 |
* Get absolute file paths associated with source item.
|
87 |
*
|
@@ -104,6 +150,15 @@ class Media_Library_Item extends Item {
|
|
104 |
$extra_info = $this->extra_info();
|
105 |
|
106 |
if ( ! empty( $extra_info['private_sizes'] ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
return $extra_info['private_sizes'];
|
108 |
}
|
109 |
|
@@ -118,13 +173,28 @@ class Media_Library_Item extends Item {
|
|
118 |
* @return bool
|
119 |
*/
|
120 |
public function is_private_size( $size ) {
|
121 |
-
if ( (
|
122 |
return $this->is_private();
|
123 |
}
|
124 |
|
125 |
return in_array( $size, $this->private_sizes() );
|
126 |
}
|
127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
/**
|
129 |
* Count attachments on current site.
|
130 |
*
|
@@ -151,21 +221,20 @@ class Media_Library_Item extends Item {
|
|
151 |
// We want to count distinct relative Media Library paths
|
152 |
// and ensure type is also attachment as other post types can use the same _wp_attached_file postmeta key.
|
153 |
$sql = "
|
154 |
-
SELECT COUNT(DISTINCT p.`ID`) total, COUNT(DISTINCT i.`id`) offloaded
|
155 |
-
FROM " . $wpdb->
|
156 |
-
|
157 |
LEFT OUTER JOIN " . static::items_table() . " AS i ON p.`ID` = i.`source_id` AND i.`source_type` = 'media-library'
|
158 |
-
WHERE
|
159 |
";
|
160 |
|
161 |
$result = $wpdb->get_row( $sql, ARRAY_A );
|
162 |
|
163 |
-
$result['not_offloaded']
|
164 |
-
$result['not_offloaded_paths'] = max( 0, $result['total_paths'] - $result['offloaded_paths'] );
|
165 |
|
166 |
ksort( $result );
|
167 |
|
168 |
-
set_site_transient( $transient_key, $result,
|
169 |
|
170 |
// One way or another we've skipped the transient.
|
171 |
self::$attachment_count_skips[ $transient_key ] = true;
|
@@ -222,7 +291,7 @@ class Media_Library_Item extends Item {
|
|
222 |
$ignored_mime_types = apply_filters( 'as3cf_ignored_mime_types', array() );
|
223 |
if ( is_array( $ignored_mime_types ) && ! empty( $ignored_mime_types ) ) {
|
224 |
$ignored_mime_types = array_map( 'sanitize_text_field', $ignored_mime_types );
|
225 |
-
$sql .=
|
226 |
}
|
227 |
|
228 |
if ( ! $count ) {
|
@@ -266,7 +335,7 @@ class Media_Library_Item extends Item {
|
|
266 |
|
267 |
$sql = '
|
268 |
SELECT DISTINCT items.*
|
269 |
-
FROM ' . static::items_table() . ' AS items
|
270 |
WHERE items.source_type = %s
|
271 |
';
|
272 |
|
@@ -279,14 +348,14 @@ class Media_Library_Item extends Item {
|
|
279 |
}
|
280 |
|
281 |
if ( $exact_match ) {
|
282 |
-
$sql .=
|
283 |
-
$sql .=
|
284 |
} else {
|
285 |
$likes = array_map( function ( $path ) {
|
286 |
$ext = '.' . pathinfo( $path, PATHINFO_EXTENSION );
|
287 |
$path = substr_replace( $path, '%', -strlen( $ext ) );
|
288 |
|
289 |
-
return
|
290 |
}, $paths );
|
291 |
|
292 |
$sql .= ' AND (' . join( ' OR ', $likes ) . ')';
|
@@ -345,7 +414,7 @@ class Media_Library_Item extends Item {
|
|
345 |
$result->post_id,
|
346 |
$this->source_path(),
|
347 |
wp_basename( $this->original_source_path() ),
|
348 |
-
$this->
|
349 |
);
|
350 |
$as3cf_item->save();
|
351 |
}
|
@@ -401,7 +470,7 @@ class Media_Library_Item extends Item {
|
|
401 |
|
402 |
if ( ! empty( $provider_object ) && is_array( $provider_object ) && ! empty( $provider_object['bucket'] ) && ! empty( $provider_object['key'] ) ) {
|
403 |
$provider_object = array_merge( array(
|
404 |
-
'provider' => Amazon_S3_And_CloudFront::
|
405 |
), $provider_object );
|
406 |
} else {
|
407 |
return false;
|
4 |
|
5 |
use Amazon_S3_And_CloudFront;
|
6 |
use WP_Error;
|
7 |
+
use AS3CF_Utils;
|
8 |
|
9 |
class Media_Library_Item extends Item {
|
10 |
private static $attachment_counts = array();
|
21 |
* @param int $source_id ID that source has.
|
22 |
* @param string $source_path Path that source uses, could be relative or absolute depending on source.
|
23 |
* @param string $original_filename An optional filename with no path that was previously used for the item.
|
24 |
+
* @param array $extra_info An optional associative array of extra data to be associated with the item.
|
25 |
+
* Recognised keys:
|
26 |
+
* 'private_sizes' => ['thumbnail', 'medium', ...]
|
27 |
+
* 'private_prefix' => 'private/'
|
28 |
+
* For backwards compatibility, if a simple array is supplied it is treated as
|
29 |
+
* private thumbnail sizes that should be private objects in the bucket.
|
30 |
* @param null $id Optional Item record ID.
|
31 |
*/
|
32 |
+
public function __construct( $provider, $region, $bucket, $path, $is_private, $source_id, $source_path, $original_filename = null, $extra_info = array(), $id = null ) {
|
33 |
// For Media Library items, the source path should be relative to the Media Library's uploads directory.
|
34 |
$uploads = wp_upload_dir();
|
35 |
|
36 |
if ( false === $uploads['error'] && 0 === strpos( $source_path, $uploads['basedir'] ) ) {
|
37 |
+
$source_path = AS3CF_Utils::unleadingslashit( substr( $source_path, strlen( $uploads['basedir'] ) ) );
|
38 |
}
|
39 |
|
40 |
+
$private_sizes = array();
|
41 |
+
$private_prefix = '';
|
|
|
42 |
|
43 |
// Ensure re-hydration is clean.
|
44 |
+
if ( ! empty( $extra_info ) && is_array( $extra_info ) ) {
|
45 |
+
if ( isset( $extra_info['private_sizes'] ) ) {
|
46 |
+
$private_sizes = $extra_info['private_sizes'];
|
47 |
+
}
|
48 |
+
if ( isset( $extra_info['private_prefix'] ) ) {
|
49 |
+
$private_prefix = $extra_info['private_prefix'];
|
50 |
+
}
|
51 |
|
52 |
+
// Compatibility fallback for if just an array of private sizes is supplied.
|
53 |
+
if ( ! isset( $extra_info['private_sizes'] ) && ! isset( $extra_info['private_prefix'] ) ) {
|
54 |
+
$private_sizes = $extra_info;
|
55 |
+
}
|
56 |
}
|
57 |
|
58 |
$extra_info = array(
|
59 |
+
'private_sizes' => $private_sizes,
|
60 |
+
'private_prefix' => $private_prefix,
|
61 |
);
|
62 |
|
63 |
parent::__construct( $provider, $region, $bucket, $path, $is_private, $source_id, $source_path, $original_filename, $extra_info, $id );
|
94 |
return $as3cf_item;
|
95 |
}
|
96 |
|
97 |
+
/**
|
98 |
+
* Full key (path) for given file that belongs to offloaded attachment.
|
99 |
+
*
|
100 |
+
* If no filename given, full sized path returned.
|
101 |
+
* Path is prepended with private prefix if size associated with filename is private,
|
102 |
+
* and a private prefix has been assigned to offload.
|
103 |
+
*
|
104 |
+
* @param string|null $filename
|
105 |
+
*
|
106 |
+
* @return string
|
107 |
+
*/
|
108 |
+
public function key( $filename = null ) {
|
109 |
+
// Public full path.
|
110 |
+
if ( empty( $filename ) && empty( $this->private_prefix() ) ) {
|
111 |
+
return parent::path();
|
112 |
+
}
|
113 |
+
|
114 |
+
if ( empty( $filename ) ) {
|
115 |
+
$filename = wp_basename( parent::path() );
|
116 |
+
}
|
117 |
+
|
118 |
+
if ( ! empty( $this->private_prefix() ) ) {
|
119 |
+
$size = \AS3CF_Utils::get_intermediate_size_from_filename( $this->source_id(), $filename );
|
120 |
+
|
121 |
+
// Private path.
|
122 |
+
if ( $this->is_private_size( $size ) ) {
|
123 |
+
return $this->private_prefix() . $this->normalized_path_dir() . $filename;
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
// Public path.
|
128 |
+
return $this->normalized_path_dir() . $filename;
|
129 |
+
}
|
130 |
+
|
131 |
/**
|
132 |
* Get absolute file paths associated with source item.
|
133 |
*
|
150 |
$extra_info = $this->extra_info();
|
151 |
|
152 |
if ( ! empty( $extra_info['private_sizes'] ) ) {
|
153 |
+
// There was an issue with class re-hydration that meant empty private sizes embedded itself inside its key.
|
154 |
+
if (
|
155 |
+
isset( $extra_info['private_sizes']['private_sizes'] ) &&
|
156 |
+
is_array( $extra_info['private_sizes']['private_sizes'] ) &&
|
157 |
+
empty( $extra_info['private_sizes']['private_sizes'] )
|
158 |
+
) {
|
159 |
+
unset( $extra_info['private_sizes']['private_sizes'] );
|
160 |
+
}
|
161 |
+
|
162 |
return $extra_info['private_sizes'];
|
163 |
}
|
164 |
|
173 |
* @return bool
|
174 |
*/
|
175 |
public function is_private_size( $size ) {
|
176 |
+
if ( empty( $size ) || in_array( $size, array( 'full', 'original' ) ) ) {
|
177 |
return $this->is_private();
|
178 |
}
|
179 |
|
180 |
return in_array( $size, $this->private_sizes() );
|
181 |
}
|
182 |
|
183 |
+
/**
|
184 |
+
* Get the private prefix for attachment's private objects.
|
185 |
+
*
|
186 |
+
* @return string
|
187 |
+
*/
|
188 |
+
public function private_prefix() {
|
189 |
+
$extra_info = $this->extra_info();
|
190 |
+
|
191 |
+
if ( ! empty( $extra_info['private_prefix'] ) ) {
|
192 |
+
return \AS3CF_Utils::trailingslash_prefix( $extra_info['private_prefix'] );
|
193 |
+
}
|
194 |
+
|
195 |
+
return '';
|
196 |
+
}
|
197 |
+
|
198 |
/**
|
199 |
* Count attachments on current site.
|
200 |
*
|
221 |
// We want to count distinct relative Media Library paths
|
222 |
// and ensure type is also attachment as other post types can use the same _wp_attached_file postmeta key.
|
223 |
$sql = "
|
224 |
+
SELECT COUNT(DISTINCT p.`ID`) total, COUNT(DISTINCT i.`id`) offloaded
|
225 |
+
FROM " . $wpdb->posts . " AS p
|
226 |
+
STRAIGHT_JOIN " . $wpdb->postmeta . " AS m ON p.ID = m.post_id AND m.`meta_key` = '_wp_attached_file'
|
227 |
LEFT OUTER JOIN " . static::items_table() . " AS i ON p.`ID` = i.`source_id` AND i.`source_type` = 'media-library'
|
228 |
+
WHERE p.`post_type` = 'attachment'
|
229 |
";
|
230 |
|
231 |
$result = $wpdb->get_row( $sql, ARRAY_A );
|
232 |
|
233 |
+
$result['not_offloaded'] = max( $result['total'] - $result['offloaded'], 0 );
|
|
|
234 |
|
235 |
ksort( $result );
|
236 |
|
237 |
+
set_site_transient( $transient_key, $result, 5 * MINUTE_IN_SECONDS );
|
238 |
|
239 |
// One way or another we've skipped the transient.
|
240 |
self::$attachment_count_skips[ $transient_key ] = true;
|
291 |
$ignored_mime_types = apply_filters( 'as3cf_ignored_mime_types', array() );
|
292 |
if ( is_array( $ignored_mime_types ) && ! empty( $ignored_mime_types ) ) {
|
293 |
$ignored_mime_types = array_map( 'sanitize_text_field', $ignored_mime_types );
|
294 |
+
$sql .= " AND posts.post_mime_type NOT IN ('" . implode( "','", $ignored_mime_types ) . "')";
|
295 |
}
|
296 |
|
297 |
if ( ! $count ) {
|
335 |
|
336 |
$sql = '
|
337 |
SELECT DISTINCT items.*
|
338 |
+
FROM ' . static::items_table() . ' AS items USE INDEX (uidx_source_path, uidx_original_source_path)
|
339 |
WHERE items.source_type = %s
|
340 |
';
|
341 |
|
348 |
}
|
349 |
|
350 |
if ( $exact_match ) {
|
351 |
+
$sql .= " AND (items.source_path IN ('" . join( "','", $paths ) . "')";
|
352 |
+
$sql .= " OR items.original_source_path IN ('" . join( "','", $paths ) . "'))";
|
353 |
} else {
|
354 |
$likes = array_map( function ( $path ) {
|
355 |
$ext = '.' . pathinfo( $path, PATHINFO_EXTENSION );
|
356 |
$path = substr_replace( $path, '%', -strlen( $ext ) );
|
357 |
|
358 |
+
return "items.source_path LIKE '" . $path . "' OR items.original_source_path LIKE '" . $path . "'";
|
359 |
}, $paths );
|
360 |
|
361 |
$sql .= ' AND (' . join( ' OR ', $likes ) . ')';
|
414 |
$result->post_id,
|
415 |
$this->source_path(),
|
416 |
wp_basename( $this->original_source_path() ),
|
417 |
+
$this->extra_info()
|
418 |
);
|
419 |
$as3cf_item->save();
|
420 |
}
|
470 |
|
471 |
if ( ! empty( $provider_object ) && is_array( $provider_object ) && ! empty( $provider_object['bucket'] ) && ! empty( $provider_object['key'] ) ) {
|
472 |
$provider_object = array_merge( array(
|
473 |
+
'provider' => Amazon_S3_And_CloudFront::get_default_storage_provider(),
|
474 |
), $provider_object );
|
475 |
} else {
|
476 |
return false;
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
|
4 |
+
|
5 |
+
class Another_CDN extends Delivery_Provider {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @var string
|
9 |
+
*/
|
10 |
+
protected static $provider_name = 'Another';
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @var string
|
14 |
+
*/
|
15 |
+
protected static $provider_short_name = 'Another';
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Used in filters and settings.
|
19 |
+
*
|
20 |
+
* @var string
|
21 |
+
*/
|
22 |
+
protected static $provider_key_name = 'another';
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
+
protected static $service_name = 'CDN';
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
protected static $service_short_name = 'CDN';
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Used in filters and settings.
|
36 |
+
*
|
37 |
+
* @var string
|
38 |
+
*/
|
39 |
+
protected static $service_key_name = 'cdn';
|
40 |
+
|
41 |
+
/**
|
42 |
+
* A short description of what features the delivery provider enables.
|
43 |
+
*
|
44 |
+
* @return string
|
45 |
+
*/
|
46 |
+
public function features_description() {
|
47 |
+
return __( 'Fast, No Private Media', 'amazon-s3-and-cloudfront' );
|
48 |
+
}
|
49 |
+
}
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
|
4 |
+
|
5 |
+
class AWS_CloudFront extends Delivery_Provider {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Which storage providers does the delivery provider support, empty means all.
|
9 |
+
*
|
10 |
+
* @var array
|
11 |
+
*/
|
12 |
+
protected static $supported_storage_providers = array(
|
13 |
+
'aws',
|
14 |
+
);
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var string
|
18 |
+
*/
|
19 |
+
protected static $provider_name = 'Amazon Web Services';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
protected static $provider_short_name = 'AWS';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Used in filters and settings.
|
28 |
+
*
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
protected static $provider_key_name = 'aws';
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
protected static $service_name = 'CloudFront';
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @var string
|
40 |
+
*/
|
41 |
+
protected static $service_short_name = 'CloudFront';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Used in filters and settings.
|
45 |
+
*
|
46 |
+
* @var string
|
47 |
+
*/
|
48 |
+
protected static $service_key_name = 'cloudfront';
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Optional override of "Provider Name" + "Service Name" for friendly name for service.
|
52 |
+
*
|
53 |
+
* @var string
|
54 |
+
*/
|
55 |
+
protected static $provider_service_name = 'Amazon CloudFront';
|
56 |
+
|
57 |
+
/**
|
58 |
+
* The slug for the service's quick start guide doc.
|
59 |
+
*
|
60 |
+
* @var string
|
61 |
+
*/
|
62 |
+
protected static $provider_service_quick_start_slug = 'amazon-cloudfront-quick-start-guide';
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @var string
|
66 |
+
*/
|
67 |
+
protected $default_domain = 'cloudfront.net';
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @var string
|
71 |
+
*/
|
72 |
+
protected $console_url = 'https://console.aws.amazon.com/cloudfront/home';
|
73 |
+
|
74 |
+
/**
|
75 |
+
* AWS_CloudFront constructor.
|
76 |
+
*
|
77 |
+
* @param \AS3CF_Plugin_Base $as3cf
|
78 |
+
*/
|
79 |
+
public function __construct( \AS3CF_Plugin_Base $as3cf ) {
|
80 |
+
parent::__construct( $as3cf );
|
81 |
+
|
82 |
+
$this->disable_csm();
|
83 |
+
|
84 |
+
// Autoloader.
|
85 |
+
require_once $as3cf->get_plugin_sdks_dir_path() . '/Aws3/aws-autoloader.php';
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Disable AWS CSM which tries to check ~/.aws/config causing issues if open_basedir in effect.
|
90 |
+
*
|
91 |
+
* @see https://github.com/aws/aws-sdk-php/issues/1659
|
92 |
+
*/
|
93 |
+
private function disable_csm() {
|
94 |
+
if ( apply_filters( 'as3cf_disable_aws_csm', true ) ) {
|
95 |
+
putenv( 'AWS_CSM_ENABLED=false' );
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* A short description of what features the delivery provider enables.
|
101 |
+
*
|
102 |
+
* @return string
|
103 |
+
*/
|
104 |
+
public function features_description() {
|
105 |
+
return sprintf(
|
106 |
+
__( 'Fast, Private Media Supported with <a href="%s" target="_blank">upgrade</a>', 'amazon-s3-and-cloudfront' ),
|
107 |
+
$this->as3cf->dbrains_url( '/wp-offload-media/upgrade/', array(
|
108 |
+
'utm_campaign' => 'WP+Offload+S3',
|
109 |
+
) )
|
110 |
+
);
|
111 |
+
}
|
112 |
+
}
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
|
4 |
+
|
5 |
+
class Cloudflare extends Another_CDN {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Which storage providers does the delivery provider support, empty means all.
|
9 |
+
*
|
10 |
+
* @var array
|
11 |
+
*/
|
12 |
+
protected static $supported_storage_providers = array(
|
13 |
+
// TODO: Add 'do' after testing and documenting.
|
14 |
+
'aws',
|
15 |
+
);
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var string
|
19 |
+
*/
|
20 |
+
protected static $provider_name = 'Cloudflare';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
protected static $provider_short_name = 'Cloudflare';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Used in filters and settings.
|
29 |
+
*
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
protected static $provider_key_name = 'cloudflare';
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @var string
|
36 |
+
*/
|
37 |
+
protected static $service_name = 'CDN';
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var string
|
41 |
+
*/
|
42 |
+
protected static $service_short_name = 'CDN';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Used in filters and settings.
|
46 |
+
*
|
47 |
+
* @var string
|
48 |
+
*/
|
49 |
+
protected static $service_key_name = 'cdn';
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Optional override of "Provider Name" + "Service Name" for friendly name for service.
|
53 |
+
*
|
54 |
+
* @var string
|
55 |
+
*/
|
56 |
+
protected static $provider_service_name = 'Cloudflare';
|
57 |
+
|
58 |
+
/**
|
59 |
+
* @var string
|
60 |
+
*/
|
61 |
+
protected static $provider_service_quick_start_slug = 'cloudflare-setup';
|
62 |
+
}
|
@@ -0,0 +1,428 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
|
4 |
+
|
5 |
+
use AS3CF_Utils;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Items\Item;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Provider;
|
8 |
+
|
9 |
+
abstract class Delivery_Provider extends Provider {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @var string
|
13 |
+
*/
|
14 |
+
protected static $provider_service_name_setting_name = 'delivery-provider-service-name';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var bool
|
18 |
+
*/
|
19 |
+
protected static $delivery_domain_allowed = true;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Which storage providers does the delivery provider support, empty means all.
|
23 |
+
*
|
24 |
+
* @var array
|
25 |
+
*/
|
26 |
+
protected static $supported_storage_providers = array();
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
protected static $signed_urls_key_id_setting_name = 'signed-urls-key-id';
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
protected static $signed_urls_key_file_path_setting_name = 'signed-urls-key-file-path';
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @var string
|
40 |
+
*/
|
41 |
+
protected static $signed_urls_object_prefix_setting_name = 'signed-urls-object-prefix';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* If left empty, private signing key file not allowed.
|
45 |
+
*
|
46 |
+
* @var array
|
47 |
+
*/
|
48 |
+
protected static $signed_urls_key_id_constants = array();
|
49 |
+
|
50 |
+
/**
|
51 |
+
* If left empty, private signing key file not allowed.
|
52 |
+
*
|
53 |
+
* @var array
|
54 |
+
*/
|
55 |
+
protected static $signed_urls_key_file_path_constants = array();
|
56 |
+
|
57 |
+
/**
|
58 |
+
* If left empty, private signing key file not allowed.
|
59 |
+
*
|
60 |
+
* @var array
|
61 |
+
*/
|
62 |
+
protected static $signed_urls_object_prefix_constants = array();
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Does the delivery provider allow for setting a custom delivery domain?
|
66 |
+
*
|
67 |
+
* @return bool
|
68 |
+
*/
|
69 |
+
public static function delivery_domain_allowed() {
|
70 |
+
return static::$delivery_domain_allowed;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Does provider support given storage provider?
|
75 |
+
*
|
76 |
+
* @param string $storage_provider_key
|
77 |
+
*
|
78 |
+
* @return bool
|
79 |
+
*/
|
80 |
+
public function supports_storage( $storage_provider_key ) {
|
81 |
+
if ( empty( static::$supported_storage_providers ) || in_array( $storage_provider_key, static::$supported_storage_providers ) ) {
|
82 |
+
return true;
|
83 |
+
}
|
84 |
+
|
85 |
+
return false;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Title used in various places for the Signed URLs Key ID.
|
90 |
+
*
|
91 |
+
* @return string
|
92 |
+
*/
|
93 |
+
public static function signed_urls_key_id_name() {
|
94 |
+
return __( 'Signing Key ID', 'amazon-s3-and-cloudfront' );
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Description used in various places for the Signed URLs Key ID.
|
99 |
+
*
|
100 |
+
* @return string
|
101 |
+
*/
|
102 |
+
public static function signed_urls_key_id_description() {
|
103 |
+
return '';
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Title used in various places for the Signed URLs Key File Path.
|
108 |
+
*
|
109 |
+
* @return string
|
110 |
+
*/
|
111 |
+
public static function signed_urls_key_file_path_name() {
|
112 |
+
return __( 'Signing Key File Path', 'amazon-s3-and-cloudfront' );
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Description used in various places for the Signed URLs Key File Path.
|
117 |
+
*
|
118 |
+
* @return string
|
119 |
+
*/
|
120 |
+
public static function signed_urls_key_file_path_description() {
|
121 |
+
return '';
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Title used in various places for the Signed URLs Private Object Prefix.
|
126 |
+
*
|
127 |
+
* @return string
|
128 |
+
*/
|
129 |
+
public static function signed_urls_object_prefix_name() {
|
130 |
+
return __( 'Private Path', 'amazon-s3-and-cloudfront' );
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Description used in various places for the Signed URLs Private Object Prefix.
|
135 |
+
*
|
136 |
+
* @return string
|
137 |
+
*/
|
138 |
+
public static function signed_urls_object_prefix_description() {
|
139 |
+
return '';
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Is the provider able to use a private signing key file?
|
144 |
+
*
|
145 |
+
* @return bool
|
146 |
+
*/
|
147 |
+
public static function use_signed_urls_key_file_allowed() {
|
148 |
+
return ! empty( static::$signed_urls_key_id_constants ) && ! empty( static::$signed_urls_key_file_path_constants ) && ! empty( static::$signed_urls_object_prefix_constants );
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* If private signing key file allowed, returns first (preferred) key id constant that should be defined, otherwise blank.
|
153 |
+
*
|
154 |
+
* @return string
|
155 |
+
*/
|
156 |
+
public static function preferred_signed_urls_key_id_constant() {
|
157 |
+
if ( static::use_signed_urls_key_file_allowed() ) {
|
158 |
+
return static::$signed_urls_key_id_constants[0];
|
159 |
+
} else {
|
160 |
+
return '';
|
161 |
+
}
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* If private signing key file allowed, returns first (preferred) key file path constant that should be defined, otherwise blank.
|
166 |
+
*
|
167 |
+
* @return string
|
168 |
+
*/
|
169 |
+
public static function preferred_signed_urls_key_file_path_constant() {
|
170 |
+
if ( static::use_signed_urls_key_file_allowed() ) {
|
171 |
+
return static::$signed_urls_key_file_path_constants[0];
|
172 |
+
} else {
|
173 |
+
return '';
|
174 |
+
}
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* If private signing key file allowed, returns first (preferred) object prefix constant that should be defined, otherwise blank.
|
179 |
+
*
|
180 |
+
* @return string
|
181 |
+
*/
|
182 |
+
public static function preferred_signed_urls_object_prefix_constant() {
|
183 |
+
if ( static::use_signed_urls_key_file_allowed() ) {
|
184 |
+
return static::$signed_urls_object_prefix_constants[0];
|
185 |
+
} else {
|
186 |
+
return '';
|
187 |
+
}
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Check if private signing key id and file path set.
|
192 |
+
*
|
193 |
+
* @return bool
|
194 |
+
*/
|
195 |
+
public function use_signed_urls_key_file() {
|
196 |
+
if ( ! static::use_signed_urls_key_file_allowed() ) {
|
197 |
+
return false;
|
198 |
+
}
|
199 |
+
|
200 |
+
return $this->get_signed_urls_key_id() && $this->get_signed_urls_key_file_path() && $this->get_signed_urls_object_prefix();
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Get the private signing key id from a constant or the settings.
|
205 |
+
*
|
206 |
+
* Falls back to settings if constant is not defined.
|
207 |
+
*
|
208 |
+
* @return string
|
209 |
+
*/
|
210 |
+
public function get_signed_urls_key_id() {
|
211 |
+
if ( static::is_signed_urls_key_id_constant_defined() ) {
|
212 |
+
$constant = static::signed_urls_key_id_constant();
|
213 |
+
|
214 |
+
return $constant ? constant( $constant ) : '';
|
215 |
+
}
|
216 |
+
|
217 |
+
return $this->as3cf->get_core_setting( static::$signed_urls_key_id_setting_name );
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Get the private signing key file path from a constant or the settings.
|
222 |
+
*
|
223 |
+
* Falls back to settings if constant is not defined.
|
224 |
+
*
|
225 |
+
* @return string|bool
|
226 |
+
*/
|
227 |
+
public function get_signed_urls_key_file_path() {
|
228 |
+
if ( static::is_signed_urls_key_file_path_constant_defined() ) {
|
229 |
+
$constant = static::signed_urls_key_file_path_constant();
|
230 |
+
|
231 |
+
if ( $constant ) {
|
232 |
+
return $this->validate_signed_urls_key_file_path( constant( $constant ) );
|
233 |
+
} else {
|
234 |
+
// Constant defined but value is not a non-empty string.
|
235 |
+
return false;
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
return $this->validate_signed_urls_key_file_path( $this->as3cf->get_core_setting( static::$signed_urls_key_file_path_setting_name, false ) );
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Get the private signing object prefix from a constant or the settings.
|
244 |
+
*
|
245 |
+
* Falls back to settings if constant is not defined.
|
246 |
+
*
|
247 |
+
* @return string
|
248 |
+
*/
|
249 |
+
public function get_signed_urls_object_prefix() {
|
250 |
+
if ( static::is_signed_urls_object_prefix_constant_defined() ) {
|
251 |
+
$constant = static::signed_urls_object_prefix_constant();
|
252 |
+
|
253 |
+
return $constant ? constant( $constant ) : '';
|
254 |
+
}
|
255 |
+
|
256 |
+
return $this->as3cf->get_core_setting( static::$signed_urls_object_prefix_setting_name );
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Validate a private signing key file path to ensure it exists, is readable, and contains something.
|
261 |
+
*
|
262 |
+
* @param string $signed_urls_key_file_path
|
263 |
+
*
|
264 |
+
* @return bool|string
|
265 |
+
*/
|
266 |
+
public function validate_signed_urls_key_file_path( $signed_urls_key_file_path ) {
|
267 |
+
$notice_id = 'validate-signed-urls-key-file-path';
|
268 |
+
$this->as3cf->notices->remove_notice_by_id( $notice_id );
|
269 |
+
|
270 |
+
if ( empty( $signed_urls_key_file_path ) ) {
|
271 |
+
return false;
|
272 |
+
}
|
273 |
+
|
274 |
+
if ( ! file_exists( $signed_urls_key_file_path ) ) {
|
275 |
+
$this->as3cf->notices->add_notice( __( 'Given Signing Key File Path is invalid or could not be accessed.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
|
276 |
+
|
277 |
+
return false;
|
278 |
+
}
|
279 |
+
|
280 |
+
try {
|
281 |
+
$value = file_get_contents( $signed_urls_key_file_path );
|
282 |
+
|
283 |
+
// An exception isn't always thrown, so check value instead.
|
284 |
+
if ( empty( $value ) ) {
|
285 |
+
$this->as3cf->notices->add_notice( __( 'Could not read Signing Key File Path\'s contents.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
|
286 |
+
|
287 |
+
return false;
|
288 |
+
}
|
289 |
+
} catch ( \Exception $e ) {
|
290 |
+
$this->as3cf->notices->add_notice( __( 'Could not read Signing Key File Path\'s contents.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
|
291 |
+
|
292 |
+
return false;
|
293 |
+
}
|
294 |
+
|
295 |
+
// File exists and has contents.
|
296 |
+
return $signed_urls_key_file_path;
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Check if private signing key id constant is defined.
|
301 |
+
*
|
302 |
+
* @return bool
|
303 |
+
*/
|
304 |
+
public static function is_signed_urls_key_id_constant_defined() {
|
305 |
+
$constant = static::signed_urls_key_id_constant();
|
306 |
+
|
307 |
+
return $constant && constant( $constant );
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* Check if private signing key file path constant is defined, for speed, does not check validity of file path.
|
312 |
+
*
|
313 |
+
* @return bool
|
314 |
+
*/
|
315 |
+
public static function is_signed_urls_key_file_path_constant_defined() {
|
316 |
+
$constant = static::signed_urls_key_file_path_constant();
|
317 |
+
|
318 |
+
return $constant && constant( $constant );
|
319 |
+
}
|
320 |
+
|
321 |
+
/**
|
322 |
+
* Check if private signing object prefix constant is defined.
|
323 |
+
*
|
324 |
+
* @return bool
|
325 |
+
*/
|
326 |
+
public static function is_signed_urls_object_prefix_constant_defined() {
|
327 |
+
$constant = static::signed_urls_object_prefix_constant();
|
328 |
+
|
329 |
+
return $constant && constant( $constant );
|
330 |
+
}
|
331 |
+
|
332 |
+
/**
|
333 |
+
* Get the constant used to define the private signing key id.
|
334 |
+
*
|
335 |
+
* @return string|false Constant name if defined, otherwise false
|
336 |
+
*/
|
337 |
+
public static function signed_urls_key_id_constant() {
|
338 |
+
return AS3CF_Utils::get_first_defined_constant( static::$signed_urls_key_id_constants );
|
339 |
+
}
|
340 |
+
|
341 |
+
/**
|
342 |
+
* Get the constant used to define the private signing key file path.
|
343 |
+
*
|
344 |
+
* @return string|false Constant name if defined, otherwise false
|
345 |
+
*/
|
346 |
+
public static function signed_urls_key_file_path_constant() {
|
347 |
+
return AS3CF_Utils::get_first_defined_constant( static::$signed_urls_key_file_path_constants );
|
348 |
+
}
|
349 |
+
|
350 |
+
/**
|
351 |
+
* Get the constant used to define the private signing object prefix.
|
352 |
+
*
|
353 |
+
* @return string|false Constant name if defined, otherwise false
|
354 |
+
*/
|
355 |
+
public static function signed_urls_object_prefix_constant() {
|
356 |
+
return AS3CF_Utils::get_first_defined_constant( static::$signed_urls_object_prefix_constants );
|
357 |
+
}
|
358 |
+
|
359 |
+
/**
|
360 |
+
* Get a site specific file path example for a signed URL key file.
|
361 |
+
*
|
362 |
+
* @return string
|
363 |
+
*/
|
364 |
+
public static function signed_urls_key_file_path_placeholder() {
|
365 |
+
$filename = 'pk-12345678ABCDE.pem';
|
366 |
+
|
367 |
+
return dirname( ABSPATH ) . DIRECTORY_SEPARATOR . $filename;
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* Return a fully formed and potentially expiring signed URL for the given Item.
|
372 |
+
*
|
373 |
+
* @param Item $as3cf_item
|
374 |
+
* @param string $path The required bucket path, may differ from Item's path if image subsize etc.
|
375 |
+
* @param string $domain The domain to use for the URL if at all possible.
|
376 |
+
* @param string $scheme The scheme to be used if possible.
|
377 |
+
* @param array|null $headers Optional array of headers to be passed along to underlying requests.
|
378 |
+
*
|
379 |
+
* @return string
|
380 |
+
*/
|
381 |
+
public function get_url( Item $as3cf_item, $path, $domain, $scheme, $headers = array() ) {
|
382 |
+
$item_path = $this->as3cf->maybe_update_delivery_path( $path, $domain );
|
383 |
+
$item_path = AS3CF_Utils::encode_filename_in_path( $item_path );
|
384 |
+
|
385 |
+
return $scheme . '://' . $domain . '/' . $item_path;
|
386 |
+
}
|
387 |
+
|
388 |
+
/**
|
389 |
+
* Return a fully formed and expiring signed URL for the given Item.
|
390 |
+
*
|
391 |
+
* @param Item $as3cf_item
|
392 |
+
* @param string $path The required bucket path, may differ from Item's path if image subsize etc.
|
393 |
+
* @param string $domain The domain to use for the URL if at all possible.
|
394 |
+
* @param string $scheme The scheme to be used if possible.
|
395 |
+
* @param int $timestamp URL expires at the given time.
|
396 |
+
* @param array|null $headers Optional array of headers to be passed along to underlying requests.
|
397 |
+
*
|
398 |
+
* @return string
|
399 |
+
* @throws \Exception
|
400 |
+
*/
|
401 |
+
public function get_signed_url( Item $as3cf_item, $path, $domain, $scheme, $timestamp, $headers = array() ) {
|
402 |
+
/**
|
403 |
+
* This default implementation defers to the storage provider's signed URLs.
|
404 |
+
* Therefore we need to use a storage provider client instance for the item's region.
|
405 |
+
*/
|
406 |
+
if ( ! empty( $as3cf_item->region() ) && ( $this->as3cf->get_storage_provider()->region_required() || $this->as3cf->get_storage_provider()->get_default_region() !== $as3cf_item->region() ) ) {
|
407 |
+
$region = $this->as3cf->get_storage_provider()->sanitize_region( $as3cf_item->region() );
|
408 |
+
} else {
|
409 |
+
$region = '';
|
410 |
+
}
|
411 |
+
|
412 |
+
// Storage Provider may support signing custom domain, e.g. GCP.
|
413 |
+
if ( $this->as3cf->get_storage_provider()->get_domain() !== $domain ) {
|
414 |
+
$headers['BaseURL'] = $scheme . '://' . $domain;
|
415 |
+
}
|
416 |
+
|
417 |
+
return $this->as3cf->get_provider_client( $region )->get_object_url( $as3cf_item->bucket(), $path, $timestamp, $headers );
|
418 |
+
}
|
419 |
+
|
420 |
+
/**
|
421 |
+
* A short description of what features the delivery provider enables.
|
422 |
+
*
|
423 |
+
* TODO: Use properties to specify features list, allowing some to be derived from storage provider (e.g. GCP can be fast by default).
|
424 |
+
*
|
425 |
+
* @return string
|
426 |
+
*/
|
427 |
+
abstract public function features_description();
|
428 |
+
}
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
|
4 |
+
|
5 |
+
class DigitalOcean_Spaces_CDN extends Delivery_Provider {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Which storage providers does the delivery provider support, empty means all.
|
9 |
+
*
|
10 |
+
* @var array
|
11 |
+
*/
|
12 |
+
protected static $supported_storage_providers = array(
|
13 |
+
'do',
|
14 |
+
);
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var string
|
18 |
+
*/
|
19 |
+
protected static $provider_name = 'DigitalOcean';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
protected static $provider_short_name = 'DigitalOcean';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Used in filters and settings.
|
28 |
+
*
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
protected static $provider_key_name = 'do';
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
protected static $service_name = 'Spaces CDN';
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @var string
|
40 |
+
*/
|
41 |
+
protected static $service_short_name = 'Spaces CDN';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Used in filters and settings.
|
45 |
+
*
|
46 |
+
* @var string
|
47 |
+
*/
|
48 |
+
protected static $service_key_name = 'spaces-cdn';
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Optional override of "Provider Name" + "Service Name" for friendly name for service.
|
52 |
+
*
|
53 |
+
* @var string
|
54 |
+
*/
|
55 |
+
protected static $provider_service_name = 'DigitalOcean Spaces CDN';
|
56 |
+
|
57 |
+
/**
|
58 |
+
* The slug for the service's quick start guide doc.
|
59 |
+
*
|
60 |
+
* @var string
|
61 |
+
*/
|
62 |
+
protected static $provider_service_quick_start_slug = 'digitalocean-spaces-cdn-setup';
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @var string
|
66 |
+
*/
|
67 |
+
protected $default_domain = 'cdn.digitaloceanspaces.com';
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @var string
|
71 |
+
*/
|
72 |
+
protected $console_url = 'https://cloud.digitalocean.com/spaces/';
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @var string
|
76 |
+
*/
|
77 |
+
protected $console_url_prefix_param = '?path=';
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @inheritDoc
|
81 |
+
*/
|
82 |
+
public function features_description() {
|
83 |
+
return __( 'Fast, No Private Media', 'amazon-s3-and-cloudfront' );
|
84 |
+
}
|
85 |
+
}
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
|
4 |
+
|
5 |
+
class GCP_CDN extends Delivery_Provider {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Which storage providers does the delivery provider support, empty means all.
|
9 |
+
*
|
10 |
+
* @var array
|
11 |
+
*/
|
12 |
+
protected static $supported_storage_providers = array(
|
13 |
+
'gcp',
|
14 |
+
);
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var string
|
18 |
+
*/
|
19 |
+
protected static $provider_name = 'Google Cloud Platform';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
protected static $provider_short_name = 'GCP';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Used in filters and settings.
|
28 |
+
*
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
protected static $provider_key_name = 'gcp';
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
protected static $service_name = 'Cloud CDN';
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @var string
|
40 |
+
*/
|
41 |
+
protected static $service_short_name = 'Cloud CDN';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Used in filters and settings.
|
45 |
+
*
|
46 |
+
* @var string
|
47 |
+
*/
|
48 |
+
protected static $service_key_name = 'cdn';
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Optional override of "Provider Name" + "Service Name" for friendly name for service.
|
52 |
+
*
|
53 |
+
* @var string
|
54 |
+
*/
|
55 |
+
protected static $provider_service_name = 'GCP Cloud CDN';
|
56 |
+
|
57 |
+
/**
|
58 |
+
* The slug for the service's quick start guide doc.
|
59 |
+
*
|
60 |
+
* @var string
|
61 |
+
*/
|
62 |
+
protected static $provider_service_quick_start_slug = 'how-to-set-up-a-custom-domain-cdn-for-google-cloud-storage';
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @var string
|
66 |
+
*/
|
67 |
+
protected $console_url = 'https://console.cloud.google.com/net-services/cdn/list';
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @inheritDoc
|
71 |
+
*/
|
72 |
+
public function features_description() {
|
73 |
+
return __( 'Fast, Private Media Supported', 'amazon-s3-and-cloudfront' );
|
74 |
+
}
|
75 |
+
}
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
|
4 |
+
|
5 |
+
class KeyCDN extends Another_CDN {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Which storage providers does the delivery provider support, empty means all.
|
9 |
+
*
|
10 |
+
* @var array
|
11 |
+
*/
|
12 |
+
protected static $supported_storage_providers = array(
|
13 |
+
// TODO: Add 'aws' after testing and documenting.
|
14 |
+
'do',
|
15 |
+
);
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var string
|
19 |
+
*/
|
20 |
+
protected static $provider_name = 'KeyCDN';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
protected static $provider_short_name = 'KeyCDN';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Used in filters and settings.
|
29 |
+
*
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
protected static $provider_key_name = 'keycdn';
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @var string
|
36 |
+
*/
|
37 |
+
protected static $service_name = 'CDN';
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var string
|
41 |
+
*/
|
42 |
+
protected static $service_short_name = 'CDN';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Used in filters and settings.
|
46 |
+
*
|
47 |
+
* @var string
|
48 |
+
*/
|
49 |
+
protected static $service_key_name = 'cdn';
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Optional override of "Provider Name" + "Service Name" for friendly name for service.
|
53 |
+
*
|
54 |
+
* @var string
|
55 |
+
*/
|
56 |
+
protected static $provider_service_name = 'KeyCDN';
|
57 |
+
|
58 |
+
/**
|
59 |
+
* @var string
|
60 |
+
*/
|
61 |
+
protected static $provider_service_quick_start_slug = 'how-to-set-up-a-custom-domain-for-digitalocean-spaces-with-keycdn';
|
62 |
+
}
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class Other
|
7 |
+
*
|
8 |
+
* This is effectively dummy class that fulfils the requirements of a selectable "Other" default sub-option for Another CDN.
|
9 |
+
*
|
10 |
+
* @package DeliciousBrains\WP_Offload_Media\Providers\Delivery
|
11 |
+
*/
|
12 |
+
class Other extends Another_CDN {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Can the displayed provider service name be overridden by the user?
|
16 |
+
*
|
17 |
+
* @var bool
|
18 |
+
*/
|
19 |
+
protected static $provider_service_name_override_allowed = true;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
protected static $provider_name = 'Other';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
protected static $provider_short_name = 'Other';
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Used in filters and settings.
|
33 |
+
*
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
protected static $provider_key_name = 'other';
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @var string
|
40 |
+
*/
|
41 |
+
protected static $service_name = 'Unknown';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* @var string
|
45 |
+
*/
|
46 |
+
protected static $service_short_name = 'Unknown';
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Used in filters and settings.
|
50 |
+
*
|
51 |
+
* @var string
|
52 |
+
*/
|
53 |
+
protected static $service_key_name = 'unknown';
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Optional override of "Provider Name" + "Service Name" for friendly name for service.
|
57 |
+
*
|
58 |
+
* @var string
|
59 |
+
*/
|
60 |
+
protected static $provider_service_name = 'Other';
|
61 |
+
}
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
|
4 |
+
|
5 |
+
class StackPath extends Another_CDN {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Which storage providers does the delivery provider support, empty means all.
|
9 |
+
*
|
10 |
+
* @var array
|
11 |
+
*/
|
12 |
+
protected static $supported_storage_providers = array(
|
13 |
+
// TODO: Add 'do' after testing and documenting.
|
14 |
+
'aws',
|
15 |
+
);
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var string
|
19 |
+
*/
|
20 |
+
protected static $provider_name = 'StackPath';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
protected static $provider_short_name = 'StackPath';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Used in filters and settings.
|
29 |
+
*
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
protected static $provider_key_name = 'stackpath';
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @var string
|
36 |
+
*/
|
37 |
+
protected static $service_name = 'CDN';
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var string
|
41 |
+
*/
|
42 |
+
protected static $service_short_name = 'CDN';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Used in filters and settings.
|
46 |
+
*
|
47 |
+
* @var string
|
48 |
+
*/
|
49 |
+
protected static $service_key_name = 'cdn';
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Optional override of "Provider Name" + "Service Name" for friendly name for service.
|
53 |
+
*
|
54 |
+
* @var string
|
55 |
+
*/
|
56 |
+
protected static $provider_service_name = 'StackPath';
|
57 |
+
|
58 |
+
/**
|
59 |
+
* @var string
|
60 |
+
*/
|
61 |
+
protected static $provider_service_quick_start_slug = 'stackpath-setup';
|
62 |
+
}
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Delivery;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Items\Item;
|
6 |
+
|
7 |
+
class Storage extends Delivery_Provider {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @var bool
|
11 |
+
*/
|
12 |
+
protected static $delivery_domain_allowed = false;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
protected static $provider_name = 'Storage Provider';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var string
|
21 |
+
*/
|
22 |
+
protected static $provider_short_name = 'Storage';
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Used in filters and settings.
|
26 |
+
*
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
protected static $provider_key_name = 'storage';
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @var string
|
33 |
+
*/
|
34 |
+
protected static $service_name = 'Bucket';
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @var string
|
38 |
+
*/
|
39 |
+
protected static $service_short_name = 'Bucket';
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Used in filters and settings.
|
43 |
+
*
|
44 |
+
* @var string
|
45 |
+
*/
|
46 |
+
protected static $service_key_name = 'bucket';
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Returns the full name for the provider.
|
50 |
+
*
|
51 |
+
* @return string
|
52 |
+
*/
|
53 |
+
public static function get_provider_name() {
|
54 |
+
/** @var \Amazon_S3_And_CloudFront $as3cf */
|
55 |
+
global $as3cf;
|
56 |
+
|
57 |
+
return $as3cf->get_storage_provider()->get_provider_name();
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Returns the full name for the service.
|
62 |
+
*
|
63 |
+
* @return string
|
64 |
+
*/
|
65 |
+
public static function get_service_name() {
|
66 |
+
/** @var \Amazon_S3_And_CloudFront $as3cf */
|
67 |
+
global $as3cf;
|
68 |
+
|
69 |
+
return $as3cf->get_storage_provider()->get_service_name();
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Returns the full name for the provider and service for display.
|
74 |
+
*
|
75 |
+
* @param bool $override_allowed Not used.
|
76 |
+
*
|
77 |
+
* @return string
|
78 |
+
*/
|
79 |
+
public static function get_provider_service_name( $override_allowed = true ) {
|
80 |
+
/** @var \Amazon_S3_And_CloudFront $as3cf */
|
81 |
+
global $as3cf;
|
82 |
+
|
83 |
+
return $as3cf->get_storage_provider()->get_provider_service_name();
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* A short description of what features the delivery provider enables.
|
88 |
+
*
|
89 |
+
* @return string
|
90 |
+
*/
|
91 |
+
public function features_description() {
|
92 |
+
return __( 'Slow, Private Media Supported', 'amazon-s3-and-cloudfront' );
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* @inheritDoc
|
97 |
+
*/
|
98 |
+
public function get_url( Item $as3cf_item, $path, $domain, $scheme, $headers = array() ) {
|
99 |
+
$domain = $this->as3cf->get_storage_provider()->get_url_domain( $as3cf_item->bucket(), $as3cf_item->region() );
|
100 |
+
|
101 |
+
return parent::get_url( $as3cf_item, $path, $domain, $scheme, $headers );
|
102 |
+
}
|
103 |
+
}
|
@@ -3,21 +3,26 @@
|
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Providers;
|
4 |
|
5 |
use AS3CF_Plugin_Base;
|
6 |
-
use
|
7 |
-
use AS3CF_Utils;
|
8 |
-
use Exception;
|
9 |
|
10 |
abstract class Provider {
|
11 |
|
12 |
/**
|
13 |
* @var \Amazon_S3_And_CloudFront|\Amazon_S3_And_CloudFront_Pro
|
14 |
*/
|
15 |
-
|
16 |
|
17 |
/**
|
18 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
*/
|
20 |
-
|
21 |
|
22 |
/**
|
23 |
* @var string
|
@@ -67,72 +72,6 @@ abstract class Provider {
|
|
67 |
*/
|
68 |
protected static $provider_service_quick_start_slug = 'quick-start-guide';
|
69 |
|
70 |
-
/**
|
71 |
-
* @var string
|
72 |
-
*/
|
73 |
-
protected static $access_key_id_setting_name = 'access-key-id';
|
74 |
-
|
75 |
-
/**
|
76 |
-
* @var string
|
77 |
-
*/
|
78 |
-
protected static $secret_access_key_setting_name = 'secret-access-key';
|
79 |
-
|
80 |
-
/**
|
81 |
-
* @var string
|
82 |
-
*/
|
83 |
-
protected static $use_server_roles_setting_name = 'use-server-roles';
|
84 |
-
|
85 |
-
/**
|
86 |
-
* @var string
|
87 |
-
*/
|
88 |
-
protected static $key_file_setting_name = 'key-file';
|
89 |
-
|
90 |
-
/**
|
91 |
-
* @var string
|
92 |
-
*/
|
93 |
-
protected static $key_file_path_setting_name = 'key-file-path';
|
94 |
-
|
95 |
-
/**
|
96 |
-
* If left empty, access keys not allowed.
|
97 |
-
*
|
98 |
-
* @var array
|
99 |
-
*/
|
100 |
-
protected static $access_key_id_constants = array();
|
101 |
-
|
102 |
-
/**
|
103 |
-
* @var array
|
104 |
-
*/
|
105 |
-
protected static $secret_access_key_constants = array();
|
106 |
-
|
107 |
-
/**
|
108 |
-
* If left empty, server roles not allowed.
|
109 |
-
*
|
110 |
-
* @var array
|
111 |
-
*/
|
112 |
-
protected static $use_server_roles_constants = array();
|
113 |
-
|
114 |
-
/**
|
115 |
-
* If left empty, key file not allowed.
|
116 |
-
*
|
117 |
-
* @var array
|
118 |
-
*/
|
119 |
-
protected static $key_file_path_constants = array();
|
120 |
-
|
121 |
-
/**
|
122 |
-
* @var array
|
123 |
-
*/
|
124 |
-
protected $regions = array();
|
125 |
-
|
126 |
-
/**
|
127 |
-
* @var bool
|
128 |
-
*/
|
129 |
-
protected $region_required = false;
|
130 |
-
|
131 |
-
/**
|
132 |
-
* @var string
|
133 |
-
*/
|
134 |
-
protected $default_region = '';
|
135 |
-
|
136 |
/**
|
137 |
* @var string
|
138 |
*/
|
@@ -153,7 +92,7 @@ abstract class Provider {
|
|
153 |
*
|
154 |
* @param AS3CF_Plugin_Base $as3cf
|
155 |
*/
|
156 |
-
public function __construct(
|
157 |
$this->as3cf = $as3cf;
|
158 |
}
|
159 |
|
@@ -176,338 +115,69 @@ abstract class Provider {
|
|
176 |
}
|
177 |
|
178 |
/**
|
179 |
-
* Returns the
|
180 |
-
*
|
181 |
-
* @return string
|
182 |
-
*/
|
183 |
-
public static function get_service_key_name() {
|
184 |
-
return static::$provider_key_name;
|
185 |
-
}
|
186 |
-
|
187 |
-
/**
|
188 |
-
* Returns the full name for the provider and service for display.
|
189 |
*
|
190 |
* @return string
|
191 |
*/
|
192 |
-
public static function
|
193 |
-
|
194 |
-
return static::$provider_service_name;
|
195 |
-
}
|
196 |
-
|
197 |
-
return static::$provider_name . ' ' . static::$service_name;
|
198 |
-
}
|
199 |
-
|
200 |
-
/**
|
201 |
-
* Returns the slug for the service's quick start guide doc.
|
202 |
-
*
|
203 |
-
* @return string
|
204 |
-
*/
|
205 |
-
public static function get_provider_service_quick_start_slug() {
|
206 |
-
return static::$provider_service_quick_start_slug;
|
207 |
-
}
|
208 |
-
|
209 |
-
/**
|
210 |
-
* Is the provider able to use access keys?
|
211 |
-
*
|
212 |
-
* @return bool
|
213 |
-
*/
|
214 |
-
public static function use_access_keys_allowed() {
|
215 |
-
return ! empty( static::$access_key_id_constants );
|
216 |
}
|
217 |
|
218 |
/**
|
219 |
-
*
|
220 |
-
*
|
221 |
-
* Keys are needed if we are not using server roles or not defined/set yet.
|
222 |
-
*
|
223 |
-
* @return bool
|
224 |
-
*/
|
225 |
-
public function needs_access_keys() {
|
226 |
-
if ( $this->use_server_roles() ) {
|
227 |
-
return false;
|
228 |
-
}
|
229 |
-
|
230 |
-
if ( static::use_key_file() ) {
|
231 |
-
return false;
|
232 |
-
}
|
233 |
-
|
234 |
-
return ! $this->are_access_keys_set();
|
235 |
-
}
|
236 |
-
|
237 |
-
/**
|
238 |
-
* Check if both access key id & secret are present.
|
239 |
-
*
|
240 |
-
* @return bool
|
241 |
-
*/
|
242 |
-
public function are_access_keys_set() {
|
243 |
-
return $this->get_access_key_id() && $this->get_secret_access_key();
|
244 |
-
}
|
245 |
-
|
246 |
-
/**
|
247 |
-
* Get the access key from a constant or the settings.
|
248 |
-
*
|
249 |
-
* Falls back to settings only if neither constant is defined.
|
250 |
-
*
|
251 |
-
* @return string
|
252 |
-
*/
|
253 |
-
public function get_access_key_id() {
|
254 |
-
if ( static::is_any_access_key_constant_defined() ) {
|
255 |
-
$constant = static::access_key_id_constant();
|
256 |
-
|
257 |
-
return $constant ? constant( $constant ) : '';
|
258 |
-
}
|
259 |
-
|
260 |
-
return $this->as3cf->get_core_setting( static::$access_key_id_setting_name );
|
261 |
-
}
|
262 |
-
|
263 |
-
/**
|
264 |
-
* Get the secret access key from a constant or the settings.
|
265 |
-
*
|
266 |
-
* Falls back to settings only if neither constant is defined.
|
267 |
*
|
268 |
* @return string
|
269 |
*/
|
270 |
-
public function
|
271 |
-
|
272 |
-
$constant = static::secret_access_key_constant();
|
273 |
-
|
274 |
-
return $constant ? constant( $constant ) : '';
|
275 |
-
}
|
276 |
-
|
277 |
-
return $this->as3cf->get_core_setting( static::$secret_access_key_setting_name );
|
278 |
-
}
|
279 |
-
|
280 |
-
/**
|
281 |
-
* Check if any access key (id or secret, prefixed or not) is defined.
|
282 |
-
*
|
283 |
-
* @return bool
|
284 |
-
*/
|
285 |
-
public static function is_any_access_key_constant_defined() {
|
286 |
-
return static::access_key_id_constant() || static::secret_access_key_constant();
|
287 |
-
}
|
288 |
-
|
289 |
-
/**
|
290 |
-
* Get the constant used to define the access key id.
|
291 |
-
*
|
292 |
-
* @return string|false Constant name if defined, otherwise false
|
293 |
-
*/
|
294 |
-
public static function access_key_id_constant() {
|
295 |
-
return AS3CF_Utils::get_first_defined_constant( static::$access_key_id_constants );
|
296 |
-
}
|
297 |
-
|
298 |
-
/**
|
299 |
-
* Get the constant used to define the secret access key.
|
300 |
-
*
|
301 |
-
* @return string|false Constant name if defined, otherwise false
|
302 |
-
*/
|
303 |
-
public static function secret_access_key_constant() {
|
304 |
-
return AS3CF_Utils::get_first_defined_constant( static::$secret_access_key_constants );
|
305 |
}
|
306 |
|
307 |
/**
|
308 |
-
*
|
309 |
*
|
310 |
-
* @
|
311 |
-
*/
|
312 |
-
public static function use_server_roles_allowed() {
|
313 |
-
return ! empty( static::$use_server_roles_constants );
|
314 |
-
}
|
315 |
-
|
316 |
-
/**
|
317 |
-
* If server roles allowed, returns first (preferred) constant that should be defined, otherwise blank.
|
318 |
*
|
319 |
* @return string
|
320 |
*/
|
321 |
-
public static function
|
322 |
-
if ( static
|
323 |
-
|
324 |
} else {
|
325 |
-
|
326 |
}
|
327 |
-
}
|
328 |
|
329 |
-
|
330 |
-
|
331 |
-
*
|
332 |
-
* @see http://docs.aws.amazon.com/aws-sdk-php/guide/latest/credentials.html#instance-profile-credentials
|
333 |
-
*
|
334 |
-
* @return bool
|
335 |
-
*/
|
336 |
-
public function use_server_roles() {
|
337 |
-
if ( ! static::use_server_roles_allowed() ) {
|
338 |
-
return false;
|
339 |
-
}
|
340 |
-
|
341 |
-
if ( static::use_server_roles_constant() ) {
|
342 |
-
$constant = static::use_server_roles_constant();
|
343 |
-
|
344 |
-
return $constant ? constant( $constant ) : false;
|
345 |
-
}
|
346 |
-
|
347 |
-
return $this->as3cf->get_core_setting( static::$use_server_roles_setting_name, false );
|
348 |
-
}
|
349 |
-
|
350 |
-
/**
|
351 |
-
* Get the constant used to enable the use of IAM roles.
|
352 |
-
*
|
353 |
-
* @return string|false Constant name if defined, otherwise false
|
354 |
-
*/
|
355 |
-
public static function use_server_roles_constant() {
|
356 |
-
return AS3CF_Utils::get_first_defined_constant( static::$use_server_roles_constants );
|
357 |
-
}
|
358 |
-
|
359 |
-
/**
|
360 |
-
* Is the provider able to use a key file?
|
361 |
-
*
|
362 |
-
* @return bool
|
363 |
-
*/
|
364 |
-
public static function use_key_file_allowed() {
|
365 |
-
return ! empty( static::$key_file_path_constants );
|
366 |
-
}
|
367 |
-
|
368 |
-
/**
|
369 |
-
* If key file allowed, returns first (preferred) constant that should be defined, otherwise blank.
|
370 |
-
*
|
371 |
-
* @return string
|
372 |
-
*/
|
373 |
-
public static function preferred_key_file_path_constant() {
|
374 |
-
if ( static::use_key_file_allowed() ) {
|
375 |
-
return static::$key_file_path_constants[0];
|
376 |
} else {
|
377 |
-
|
378 |
-
|
379 |
-
}
|
380 |
-
|
381 |
-
/**
|
382 |
-
* Check if either key file path or key file set.
|
383 |
-
*
|
384 |
-
* @return bool
|
385 |
-
*/
|
386 |
-
public function use_key_file() {
|
387 |
-
if ( ! static::use_key_file_allowed() ) {
|
388 |
-
return false;
|
389 |
-
}
|
390 |
-
|
391 |
-
return $this->get_key_file_path() || $this->get_key_file();
|
392 |
-
}
|
393 |
-
|
394 |
-
/**
|
395 |
-
* Get the key file contents from settings.
|
396 |
-
*
|
397 |
-
* @return array|bool
|
398 |
-
*/
|
399 |
-
public function get_key_file() {
|
400 |
-
$key_file = $this->as3cf->get_core_setting( static::$key_file_setting_name, false );
|
401 |
-
|
402 |
-
return $key_file;
|
403 |
-
}
|
404 |
|
405 |
-
|
406 |
-
* Get the key file path from a constant or the settings.
|
407 |
-
*
|
408 |
-
* Falls back to settings if constant is not defined.
|
409 |
-
*
|
410 |
-
* @return string|bool
|
411 |
-
*/
|
412 |
-
public function get_key_file_path() {
|
413 |
-
if ( static::is_key_file_path_constant_defined() ) {
|
414 |
-
$constant = static::key_file_path_constant();
|
415 |
|
416 |
-
if ( $
|
417 |
-
return $
|
418 |
} else {
|
419 |
-
|
420 |
-
return false;
|
421 |
-
}
|
422 |
-
}
|
423 |
-
|
424 |
-
return $this->validate_key_file_path( $this->as3cf->get_core_setting( static::$key_file_path_setting_name, false ) );
|
425 |
-
}
|
426 |
-
|
427 |
-
/**
|
428 |
-
* Validate a key file path to ensure it exists, is readable, and contains JSON.
|
429 |
-
*
|
430 |
-
* @param string $key_file_path
|
431 |
-
*
|
432 |
-
* @return bool|string
|
433 |
-
*/
|
434 |
-
public function validate_key_file_path( $key_file_path ) {
|
435 |
-
$notice_id = 'validate-key-file-path';
|
436 |
-
$this->as3cf->notices->remove_notice_by_id( $notice_id );
|
437 |
-
|
438 |
-
if ( empty( $key_file_path ) ) {
|
439 |
-
return false;
|
440 |
-
}
|
441 |
-
|
442 |
-
if ( ! file_exists( $key_file_path ) ) {
|
443 |
-
$this->as3cf->notices->add_notice( __( 'Given Key File Path is invalid or could not be accessed.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
|
444 |
-
|
445 |
-
return false;
|
446 |
-
}
|
447 |
-
|
448 |
-
try {
|
449 |
-
$value = file_get_contents( $key_file_path );
|
450 |
-
|
451 |
-
// An exception isn't always thrown, so check value instead.
|
452 |
-
if ( empty( $value ) ) {
|
453 |
-
$this->as3cf->notices->add_notice( __( 'Could not read Key File Path\'s contents.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
|
454 |
-
|
455 |
-
return false;
|
456 |
}
|
457 |
-
} catch ( \Exception $e ) {
|
458 |
-
$this->as3cf->notices->add_notice( __( 'Could not read Key File Path\'s contents.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
|
459 |
-
|
460 |
-
return false;
|
461 |
}
|
462 |
-
|
463 |
-
$value = json_decode( $value, true );
|
464 |
-
|
465 |
-
if ( empty( $value ) ) {
|
466 |
-
$this->as3cf->notices->add_notice( __( 'Given Key File Path does not contain valid JSON.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
|
467 |
-
|
468 |
-
return false;
|
469 |
-
}
|
470 |
-
|
471 |
-
// File exists and looks like JSON.
|
472 |
-
return $key_file_path;
|
473 |
}
|
474 |
|
475 |
/**
|
476 |
-
*
|
477 |
*
|
478 |
* @return bool
|
479 |
*/
|
480 |
-
public static function
|
481 |
-
|
482 |
-
|
483 |
-
return $constant && constant( $constant );
|
484 |
-
}
|
485 |
-
|
486 |
-
/**
|
487 |
-
* Get the constant used to define the key file path.
|
488 |
-
*
|
489 |
-
* @return string|false Constant name if defined, otherwise false
|
490 |
-
*/
|
491 |
-
public static function key_file_path_constant() {
|
492 |
-
return AS3CF_Utils::get_first_defined_constant( static::$key_file_path_constants );
|
493 |
}
|
494 |
|
495 |
/**
|
496 |
-
* Returns the
|
497 |
-
*
|
498 |
-
* @return string
|
499 |
-
*/
|
500 |
-
public function region_required() {
|
501 |
-
return $this->region_required;
|
502 |
-
}
|
503 |
-
|
504 |
-
/**
|
505 |
-
* Returns the Provider's default region slug.
|
506 |
*
|
507 |
* @return string
|
508 |
*/
|
509 |
-
public function
|
510 |
-
return
|
511 |
}
|
512 |
|
513 |
/**
|
@@ -520,501 +190,4 @@ abstract class Provider {
|
|
520 |
public function get_domain() {
|
521 |
return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_domain', $this->default_domain );
|
522 |
}
|
523 |
-
|
524 |
-
/**
|
525 |
-
* Returns an array of valid region slugs and names.
|
526 |
-
*
|
527 |
-
* @return array Keys are region slug, values their name
|
528 |
-
*/
|
529 |
-
public function get_regions() {
|
530 |
-
$regions = apply_filters( static::$provider_key_name . '_get_regions', $this->regions ); // Backwards compatibility, e.g. 'aws_get_regions'.
|
531 |
-
|
532 |
-
return apply_filters( 'as3cf_' . static::$provider_key_name . '_get_regions', $regions );
|
533 |
-
}
|
534 |
-
|
535 |
-
/**
|
536 |
-
* Returns readable region name.
|
537 |
-
*
|
538 |
-
* @param string $region
|
539 |
-
* @param bool $with_key
|
540 |
-
*
|
541 |
-
* @return string
|
542 |
-
*/
|
543 |
-
public function get_region_name( $region = '', $with_key = false ) {
|
544 |
-
if ( empty( $region ) && ! $this->region_required() ) {
|
545 |
-
$region = $this->get_default_region();
|
546 |
-
}
|
547 |
-
|
548 |
-
$regions = $this->get_regions();
|
549 |
-
|
550 |
-
$region_name = empty( $regions[ $region ] ) ? '' : $regions[ $region ];
|
551 |
-
|
552 |
-
if ( $with_key ) {
|
553 |
-
$region_name .= empty( $region_name ) ? $region : ' (' . $region . ')';
|
554 |
-
}
|
555 |
-
|
556 |
-
return $region_name;
|
557 |
-
}
|
558 |
-
|
559 |
-
/**
|
560 |
-
* Is given region key valid for provider?
|
561 |
-
*
|
562 |
-
* @param string $region
|
563 |
-
*
|
564 |
-
* @return bool
|
565 |
-
*/
|
566 |
-
public function is_region_valid( $region ) {
|
567 |
-
return in_array( trim( $region ), array_keys( $this->get_regions() ) );
|
568 |
-
}
|
569 |
-
|
570 |
-
/**
|
571 |
-
* Instantiate a new service client for the provider.
|
572 |
-
*
|
573 |
-
* @param array $args Options for required region/endpoint
|
574 |
-
*
|
575 |
-
* @throws Exception
|
576 |
-
*/
|
577 |
-
private function _init_client( Array $args ) {
|
578 |
-
if ( $this->needs_access_keys() ) {
|
579 |
-
throw new Exception( sprintf( __( 'You must first <a href="%s">set your access keys</a>.', 'amazon-s3-and-cloudfront' ), $this->as3cf->get_plugin_page_url() . '#settings' ) );
|
580 |
-
}
|
581 |
-
|
582 |
-
if ( is_null( $this->client ) ) {
|
583 |
-
// There's no extra client authentication config required when using server roles.
|
584 |
-
if ( ! $this->use_server_roles() ) {
|
585 |
-
// Some providers can supply Key File contents or Key File Path.
|
586 |
-
if ( static::use_key_file() ) {
|
587 |
-
// Key File contents take precedence over Key File Path.
|
588 |
-
if ( static::get_key_file() ) {
|
589 |
-
$args = array_merge( array(
|
590 |
-
'keyFile' => static::get_key_file(),
|
591 |
-
), $args );
|
592 |
-
} else {
|
593 |
-
$args = array_merge( array(
|
594 |
-
'keyFilePath' => static::get_key_file_path(),
|
595 |
-
), $args );
|
596 |
-
}
|
597 |
-
} else {
|
598 |
-
// Fall back is Access Keys.
|
599 |
-
$args = array_merge( array(
|
600 |
-
'credentials' => array(
|
601 |
-
'key' => $this->get_access_key_id(),
|
602 |
-
'secret' => $this->get_secret_access_key(),
|
603 |
-
),
|
604 |
-
), $args );
|
605 |
-
}
|
606 |
-
}
|
607 |
-
|
608 |
-
// Add credentials and given args to default client args and then let user override.
|
609 |
-
$args = array_merge( $this->default_client_args(), $args );
|
610 |
-
$args = apply_filters( 'as3cf_' . static::$provider_key_name . '_init_client_args', $this->init_client_args( $args ) );
|
611 |
-
$args = apply_filters( static::$provider_key_name . '_get_client_args', $args ); // Backwards compatibility, e.g. 'aws_get_client_args'.
|
612 |
-
|
613 |
-
$this->client = $this->init_client( $args );
|
614 |
-
}
|
615 |
-
}
|
616 |
-
|
617 |
-
/**
|
618 |
-
* Get the service client instance.
|
619 |
-
*
|
620 |
-
* @param array $args Options for required region/endpoint
|
621 |
-
* @param bool $force
|
622 |
-
*
|
623 |
-
* @return Provider
|
624 |
-
* @throws Exception
|
625 |
-
*/
|
626 |
-
public function get_client( Array $args, $force = false ) {
|
627 |
-
if ( true === $force ) {
|
628 |
-
$this->client = null;
|
629 |
-
}
|
630 |
-
|
631 |
-
$this->_init_client( $args );
|
632 |
-
|
633 |
-
$args = apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_client_args', $this->init_service_client_args( $args ) );
|
634 |
-
|
635 |
-
$this->client = $this->init_service_client( $args );
|
636 |
-
|
637 |
-
return $this;
|
638 |
-
}
|
639 |
-
|
640 |
-
/**
|
641 |
-
* Get object keys from multiple clients.
|
642 |
-
*
|
643 |
-
* @param array $regions
|
644 |
-
*
|
645 |
-
* @return array
|
646 |
-
*/
|
647 |
-
public static function get_keys_from_regions( Array $regions ) {
|
648 |
-
$keys = array();
|
649 |
-
|
650 |
-
foreach ( $regions as $region ) {
|
651 |
-
try {
|
652 |
-
/* @var $client Provider */
|
653 |
-
$client = $region['provider_client'];
|
654 |
-
$region_keys = $client->list_keys( $region['locations'] );
|
655 |
-
} catch ( \Exception $e ) {
|
656 |
-
AS3CF_Error::log( get_class( $e ) . ' exception caught when executing list_keys: ' . $e->getMessage() );
|
657 |
-
continue;
|
658 |
-
}
|
659 |
-
|
660 |
-
if ( ! empty( $region_keys ) ) {
|
661 |
-
foreach ( $region_keys as $attachment_id => $found_keys ) {
|
662 |
-
$keys[ $attachment_id ] = AS3CF_Utils::validate_attachment_keys( $attachment_id, $found_keys );
|
663 |
-
}
|
664 |
-
}
|
665 |
-
}
|
666 |
-
|
667 |
-
return $keys;
|
668 |
-
}
|
669 |
-
|
670 |
-
/**
|
671 |
-
* Generate a stream wrapper compatible URL
|
672 |
-
*
|
673 |
-
* @param string $region
|
674 |
-
* @param string $bucket
|
675 |
-
* @param string $key
|
676 |
-
*
|
677 |
-
* @return string
|
678 |
-
*/
|
679 |
-
public function prepare_stream_wrapper_file( $region, $bucket, $key ) {
|
680 |
-
$protocol = $this->get_stream_wrapper_protocol( $region );
|
681 |
-
|
682 |
-
return $protocol . '://' . $bucket . '/' . $key;
|
683 |
-
}
|
684 |
-
|
685 |
-
/**
|
686 |
-
* Get the region specific prefix for URL
|
687 |
-
*
|
688 |
-
* @param string $region
|
689 |
-
* @param null|int $expires
|
690 |
-
*
|
691 |
-
* @return string
|
692 |
-
*/
|
693 |
-
public function get_url_prefix( $region = '', $expires = null ) {
|
694 |
-
/**
|
695 |
-
* Region specific prefix for raw URL
|
696 |
-
*
|
697 |
-
* @param string $prefix
|
698 |
-
* @param string $region
|
699 |
-
* @param null|int $expires
|
700 |
-
*
|
701 |
-
* @return string
|
702 |
-
*/
|
703 |
-
return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_url_prefix', $this->url_prefix( $region, $expires ), $region, $expires );
|
704 |
-
}
|
705 |
-
|
706 |
-
/**
|
707 |
-
* Get the url domain for the files
|
708 |
-
*
|
709 |
-
* @param string $bucket
|
710 |
-
* @param string $region
|
711 |
-
* @param int $expires
|
712 |
-
* @param array $args Allows you to specify custom URL settings
|
713 |
-
* @param bool $preview When generating the URL preview sanitize certain output
|
714 |
-
*
|
715 |
-
* @return string
|
716 |
-
*/
|
717 |
-
public function get_url_domain( $bucket, $region = '', $expires = null, $args = array(), $preview = false ) {
|
718 |
-
if ( ! isset( $args['cloudfront'] ) ) {
|
719 |
-
$args['cloudfront'] = $this->as3cf->get_setting( 'cloudfront' );
|
720 |
-
}
|
721 |
-
|
722 |
-
if ( ! isset( $args['domain'] ) ) {
|
723 |
-
$args['domain'] = $this->as3cf->get_setting( 'domain' );
|
724 |
-
}
|
725 |
-
|
726 |
-
if ( ! isset( $args['force-https'] ) ) {
|
727 |
-
$args['force-https'] = $this->as3cf->use_ssl( $this->as3cf->get_setting( 'force-https' ) );
|
728 |
-
}
|
729 |
-
|
730 |
-
$prefix = $this->url_prefix( $region, $expires );
|
731 |
-
$domain = $this->get_domain();
|
732 |
-
$domain = empty( $prefix ) ? $domain : $prefix . '.' . $domain;
|
733 |
-
|
734 |
-
return apply_filters(
|
735 |
-
'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_url_domain',
|
736 |
-
$this->url_domain( $domain, $bucket, $region, $expires, $args, $preview ),
|
737 |
-
$bucket,
|
738 |
-
$region,
|
739 |
-
$expires,
|
740 |
-
$args,
|
741 |
-
$preview
|
742 |
-
);
|
743 |
-
}
|
744 |
-
|
745 |
-
/**
|
746 |
-
* Get the link to the bucket on the provider's console.
|
747 |
-
*
|
748 |
-
* @param string $bucket
|
749 |
-
* @param string $prefix
|
750 |
-
*
|
751 |
-
* @return string
|
752 |
-
*/
|
753 |
-
public function get_console_url( $bucket = '', $prefix = '' ) {
|
754 |
-
if ( '' !== $prefix ) {
|
755 |
-
$prefix = $this->get_console_url_prefix_param() . apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_prefix_value', $prefix );
|
756 |
-
}
|
757 |
-
|
758 |
-
$suffix = apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_suffix_param', $this->get_console_url_suffix_param( $bucket, $prefix ) );
|
759 |
-
|
760 |
-
return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url', $this->console_url ) . $bucket . $prefix . $suffix;
|
761 |
-
}
|
762 |
-
|
763 |
-
/**
|
764 |
-
* Get the prefix param to append to the link to the bucket on the provider's console.
|
765 |
-
*
|
766 |
-
* @return string
|
767 |
-
*/
|
768 |
-
public function get_console_url_prefix_param() {
|
769 |
-
return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_prefix_param', $this->console_url_prefix_param );
|
770 |
-
}
|
771 |
-
|
772 |
-
/**
|
773 |
-
* Returns default args array for the client.
|
774 |
-
*
|
775 |
-
* @return array
|
776 |
-
*/
|
777 |
-
abstract protected function default_client_args();
|
778 |
-
|
779 |
-
/**
|
780 |
-
* Process the args before instantiating a new client for the provider's SDK.
|
781 |
-
*
|
782 |
-
* @param array $args
|
783 |
-
*
|
784 |
-
* @return array
|
785 |
-
*/
|
786 |
-
abstract protected function init_client_args( Array $args );
|
787 |
-
|
788 |
-
/**
|
789 |
-
* Instantiate a new client for the provider's SDK.
|
790 |
-
*
|
791 |
-
* @param array $args
|
792 |
-
*/
|
793 |
-
abstract protected function init_client( Array $args );
|
794 |
-
|
795 |
-
/**
|
796 |
-
* Process the args before instantiating a new service specific client.
|
797 |
-
*
|
798 |
-
* @param array $args
|
799 |
-
*
|
800 |
-
* @return array
|
801 |
-
*/
|
802 |
-
abstract protected function init_service_client_args( Array $args );
|
803 |
-
|
804 |
-
/**
|
805 |
-
* Instantiate a new service specific client.
|
806 |
-
* Depending on SDK, may simply return client instantiated with `init_client`.
|
807 |
-
*
|
808 |
-
* @param array $args
|
809 |
-
*
|
810 |
-
* @return mixed
|
811 |
-
*/
|
812 |
-
abstract protected function init_service_client( Array $args );
|
813 |
-
|
814 |
-
/**
|
815 |
-
* Make sure region "slug" fits expected format.
|
816 |
-
*
|
817 |
-
* @param string $region
|
818 |
-
*
|
819 |
-
* @return string
|
820 |
-
*/
|
821 |
-
abstract public function sanitize_region( $region );
|
822 |
-
|
823 |
-
/**
|
824 |
-
* Create bucket.
|
825 |
-
*
|
826 |
-
* @param array $args
|
827 |
-
*/
|
828 |
-
abstract public function create_bucket( Array $args );
|
829 |
-
|
830 |
-
/**
|
831 |
-
* Check whether bucket exists.
|
832 |
-
*
|
833 |
-
* @param string $bucket
|
834 |
-
*
|
835 |
-
* @return bool
|
836 |
-
*/
|
837 |
-
abstract public function does_bucket_exist( $bucket );
|
838 |
-
|
839 |
-
/**
|
840 |
-
* Returns region for bucket.
|
841 |
-
*
|
842 |
-
* @param array $args
|
843 |
-
*
|
844 |
-
* @return string
|
845 |
-
*/
|
846 |
-
abstract public function get_bucket_location( Array $args );
|
847 |
-
|
848 |
-
/**
|
849 |
-
* List buckets.
|
850 |
-
*
|
851 |
-
* @param array $args
|
852 |
-
*
|
853 |
-
* @return array
|
854 |
-
*/
|
855 |
-
abstract public function list_buckets( Array $args = array() );
|
856 |
-
|
857 |
-
/**
|
858 |
-
* Check whether key exists in bucket.
|
859 |
-
*
|
860 |
-
* @param string $bucket
|
861 |
-
* @param string $key
|
862 |
-
* @param array $options
|
863 |
-
*
|
864 |
-
* @return bool
|
865 |
-
*/
|
866 |
-
abstract public function does_object_exist( $bucket, $key, Array $options = array() );
|
867 |
-
|
868 |
-
/**
|
869 |
-
* Get default "canned" ACL string.
|
870 |
-
*
|
871 |
-
* @return string
|
872 |
-
*/
|
873 |
-
abstract public function get_default_acl();
|
874 |
-
|
875 |
-
/**
|
876 |
-
* Get private "canned" ACL string.
|
877 |
-
*
|
878 |
-
* @return string
|
879 |
-
*/
|
880 |
-
abstract public function get_private_acl();
|
881 |
-
|
882 |
-
/**
|
883 |
-
* Download object, destination specified in args.
|
884 |
-
*
|
885 |
-
* @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#getobject
|
886 |
-
*
|
887 |
-
* @param array $args
|
888 |
-
*/
|
889 |
-
abstract public function get_object( Array $args );
|
890 |
-
|
891 |
-
/**
|
892 |
-
* Get object's URL.
|
893 |
-
*
|
894 |
-
* @param string $bucket
|
895 |
-
* @param string $key
|
896 |
-
* @param int $expires
|
897 |
-
* @param array $args
|
898 |
-
*
|
899 |
-
* @return string
|
900 |
-
*/
|
901 |
-
abstract public function get_object_url( $bucket, $key, $expires, Array $args = array() );
|
902 |
-
|
903 |
-
/**
|
904 |
-
* List objects.
|
905 |
-
*
|
906 |
-
* @param array $args
|
907 |
-
*
|
908 |
-
* @return array
|
909 |
-
*/
|
910 |
-
abstract public function list_objects( Array $args = array() );
|
911 |
-
|
912 |
-
/**
|
913 |
-
* Update the ACL for an object.
|
914 |
-
*
|
915 |
-
* @param array $args
|
916 |
-
*/
|
917 |
-
abstract public function update_object_acl( Array $args );
|
918 |
-
|
919 |
-
/**
|
920 |
-
* Upload file to bucket.
|
921 |
-
*
|
922 |
-
* @param array $args
|
923 |
-
*/
|
924 |
-
abstract public function upload_object( Array $args );
|
925 |
-
|
926 |
-
/**
|
927 |
-
* Delete object from bucket.
|
928 |
-
*
|
929 |
-
* @param array $args
|
930 |
-
*/
|
931 |
-
abstract public function delete_object( Array $args );
|
932 |
-
|
933 |
-
/**
|
934 |
-
* Delete multiple objects from bucket.
|
935 |
-
*
|
936 |
-
* @param array $args
|
937 |
-
*/
|
938 |
-
abstract public function delete_objects( Array $args );
|
939 |
-
|
940 |
-
/**
|
941 |
-
* Returns arrays of found keys for given bucket and prefix locations, retaining given array's integer based index.
|
942 |
-
*
|
943 |
-
* @param array $locations Array with attachment ID as key and Bucket and Prefix in an associative array as values.
|
944 |
-
*
|
945 |
-
* @return array
|
946 |
-
*/
|
947 |
-
abstract public function list_keys( Array $locations );
|
948 |
-
|
949 |
-
/**
|
950 |
-
* Copies objects into current bucket from another bucket hosted with provider.
|
951 |
-
*
|
952 |
-
* @param array $items
|
953 |
-
*
|
954 |
-
* @return array Failures with elements Key and Message
|
955 |
-
*/
|
956 |
-
abstract public function copy_objects( Array $items );
|
957 |
-
|
958 |
-
/**
|
959 |
-
* Generate the stream wrapper protocol
|
960 |
-
*
|
961 |
-
* @param string $region
|
962 |
-
*
|
963 |
-
* @return string
|
964 |
-
*/
|
965 |
-
abstract protected function get_stream_wrapper_protocol( $region );
|
966 |
-
|
967 |
-
/**
|
968 |
-
* Register a stream wrapper for specific region.
|
969 |
-
*
|
970 |
-
* @param string $region
|
971 |
-
*
|
972 |
-
* @return bool
|
973 |
-
*/
|
974 |
-
abstract public function register_stream_wrapper( $region );
|
975 |
-
|
976 |
-
/**
|
977 |
-
* Check that a bucket and key can be written to.
|
978 |
-
*
|
979 |
-
* @param string $bucket
|
980 |
-
* @param string $key
|
981 |
-
* @param string $file_contents
|
982 |
-
*
|
983 |
-
* @return bool|string Error message on unexpected exception
|
984 |
-
*/
|
985 |
-
abstract public function can_write( $bucket, $key, $file_contents );
|
986 |
-
|
987 |
-
/**
|
988 |
-
* Get the region specific prefix for raw URL
|
989 |
-
*
|
990 |
-
* @param string $region
|
991 |
-
* @param null|int $expires
|
992 |
-
*
|
993 |
-
* @return string
|
994 |
-
*/
|
995 |
-
abstract protected function url_prefix( $region = '', $expires = null );
|
996 |
-
|
997 |
-
/**
|
998 |
-
* Get the url domain for the files
|
999 |
-
*
|
1000 |
-
* @param string $domain Likely prefixed with region
|
1001 |
-
* @param string $bucket
|
1002 |
-
* @param string $region
|
1003 |
-
* @param int $expires
|
1004 |
-
* @param array $args Allows you to specify custom URL settings
|
1005 |
-
* @param bool $preview When generating the URL preview sanitize certain output
|
1006 |
-
*
|
1007 |
-
* @return string
|
1008 |
-
*/
|
1009 |
-
abstract protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array(), $preview = false );
|
1010 |
-
|
1011 |
-
/**
|
1012 |
-
* Get the suffix param to append to the link to the bucket on the provider's console.
|
1013 |
-
*
|
1014 |
-
* @param string $bucket
|
1015 |
-
* @param string $prefix
|
1016 |
-
*
|
1017 |
-
* @return string
|
1018 |
-
*/
|
1019 |
-
abstract protected function get_console_url_suffix_param( $bucket = '', $prefix = '' );
|
1020 |
}
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Providers;
|
4 |
|
5 |
use AS3CF_Plugin_Base;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Items\Item;
|
|
|
|
|
7 |
|
8 |
abstract class Provider {
|
9 |
|
10 |
/**
|
11 |
* @var \Amazon_S3_And_CloudFront|\Amazon_S3_And_CloudFront_Pro
|
12 |
*/
|
13 |
+
protected $as3cf;
|
14 |
|
15 |
/**
|
16 |
+
* Can the displayed provider service name be overridden by the user?
|
17 |
+
*
|
18 |
+
* @var bool
|
19 |
+
*/
|
20 |
+
protected static $provider_service_name_override_allowed = false;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var string
|
24 |
*/
|
25 |
+
protected static $provider_service_name_setting_name = 'provider-service-name';
|
26 |
|
27 |
/**
|
28 |
* @var string
|
72 |
*/
|
73 |
protected static $provider_service_quick_start_slug = 'quick-start-guide';
|
74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
/**
|
76 |
* @var string
|
77 |
*/
|
92 |
*
|
93 |
* @param AS3CF_Plugin_Base $as3cf
|
94 |
*/
|
95 |
+
public function __construct( AS3CF_Plugin_Base $as3cf ) {
|
96 |
$this->as3cf = $as3cf;
|
97 |
}
|
98 |
|
115 |
}
|
116 |
|
117 |
/**
|
118 |
+
* Returns the full name for the service.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
*
|
120 |
* @return string
|
121 |
*/
|
122 |
+
public static function get_service_name() {
|
123 |
+
return static::$service_name;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
}
|
125 |
|
126 |
/**
|
127 |
+
* Returns the key friendly name for the service.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
*
|
129 |
* @return string
|
130 |
*/
|
131 |
+
public static function get_service_key_name() {
|
132 |
+
return static::$service_key_name;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
}
|
134 |
|
135 |
/**
|
136 |
+
* Returns the full name for the provider and service for display.
|
137 |
*
|
138 |
+
* @param bool $override_allowed Use override if available? Defaults to true.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
*
|
140 |
* @return string
|
141 |
*/
|
142 |
+
public static function get_provider_service_name( $override_allowed = true ) {
|
143 |
+
if ( ! empty( static::$provider_service_name ) ) {
|
144 |
+
$result = static::$provider_service_name;
|
145 |
} else {
|
146 |
+
$result = static::$provider_name . ' ' . static::$service_name;
|
147 |
}
|
|
|
148 |
|
149 |
+
if ( false === $override_allowed || false === static::provider_service_name_override_allowed() ) {
|
150 |
+
return $result;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
} else {
|
152 |
+
/** @var \Amazon_S3_And_CloudFront $as3cf */
|
153 |
+
global $as3cf;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
|
155 |
+
$override = stripslashes( $as3cf->get_setting( static::$provider_service_name_setting_name ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
|
157 |
+
if ( empty( $override ) ) {
|
158 |
+
return $result;
|
159 |
} else {
|
160 |
+
return $override;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
}
|
|
|
|
|
|
|
|
|
162 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
}
|
164 |
|
165 |
/**
|
166 |
+
* Can the displayed provider service name be overridden by the user?
|
167 |
*
|
168 |
* @return bool
|
169 |
*/
|
170 |
+
public static function provider_service_name_override_allowed() {
|
171 |
+
return static::$provider_service_name_override_allowed;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
}
|
173 |
|
174 |
/**
|
175 |
+
* Returns the slug for the service's quick start guide doc.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
*
|
177 |
* @return string
|
178 |
*/
|
179 |
+
public static function get_provider_service_quick_start_slug() {
|
180 |
+
return static::$provider_service_quick_start_slug;
|
181 |
}
|
182 |
|
183 |
/**
|
190 |
public function get_domain() {
|
191 |
return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_domain', $this->default_domain );
|
192 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
}
|
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace DeliciousBrains\WP_Offload_Media\Providers;
|
4 |
|
5 |
use AS3CF_Utils;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandPool;
|
@@ -8,9 +8,9 @@ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
|
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception;
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3Client;
|
10 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sdk;
|
11 |
-
use DeliciousBrains\WP_Offload_Media\Providers\Streams\AWS_S3_Stream_Wrapper;
|
12 |
|
13 |
-
class AWS_Provider extends
|
14 |
|
15 |
/**
|
16 |
* @var Sdk
|
@@ -97,6 +97,11 @@ class AWS_Provider extends Provider {
|
|
97 |
'AWS_USE_EC2_IAM_ROLE',
|
98 |
);
|
99 |
|
|
|
|
|
|
|
|
|
|
|
100 |
/**
|
101 |
* @var array
|
102 |
*/
|
@@ -106,18 +111,23 @@ class AWS_Provider extends Provider {
|
|
106 |
'us-west-1' => 'US West (N. California)',
|
107 |
'us-west-2' => 'US West (Oregon)',
|
108 |
'ca-central-1' => 'Canada (Central)',
|
|
|
|
|
109 |
'ap-south-1' => 'Asia Pacific (Mumbai)',
|
110 |
'ap-northeast-2' => 'Asia Pacific (Seoul)',
|
111 |
-
|
112 |
'ap-southeast-1' => 'Asia Pacific (Singapore)',
|
113 |
'ap-southeast-2' => 'Asia Pacific (Sydney)',
|
114 |
'ap-northeast-1' => 'Asia Pacific (Tokyo)',
|
115 |
-
|
116 |
-
|
117 |
'eu-central-1' => 'EU (Frankfurt)',
|
118 |
'eu-west-1' => 'EU (Ireland)',
|
119 |
'eu-west-2' => 'EU (London)',
|
|
|
120 |
'eu-west-3' => 'EU (Paris)',
|
|
|
|
|
121 |
'sa-east-1' => 'South America (Sao Paulo)',
|
122 |
);
|
123 |
|
@@ -134,19 +144,26 @@ class AWS_Provider extends Provider {
|
|
134 |
/**
|
135 |
* @var string
|
136 |
*/
|
137 |
-
protected $console_url = 'https://console.aws.amazon.com/s3/
|
138 |
|
139 |
/**
|
140 |
* @var string
|
141 |
*/
|
142 |
-
protected $console_url_prefix_param = '
|
143 |
|
144 |
const API_VERSION = '2006-03-01';
|
145 |
const SIGNATURE_VERSION = 'v4';
|
146 |
|
147 |
-
const
|
148 |
const PRIVATE_ACL = 'private';
|
149 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
/**
|
151 |
* AWS_Provider constructor.
|
152 |
*
|
@@ -161,6 +178,41 @@ class AWS_Provider extends Provider {
|
|
161 |
require_once $as3cf->get_plugin_sdks_dir_path() . '/Aws3/aws-autoloader.php';
|
162 |
}
|
163 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
/**
|
165 |
* Disable AWS CSM which tries to check ~/.aws/config causing issues if open_basedir in effect.
|
166 |
*
|
@@ -192,7 +244,7 @@ class AWS_Provider extends Provider {
|
|
192 |
*
|
193 |
* @return array
|
194 |
*/
|
195 |
-
protected function init_client_args(
|
196 |
return $args;
|
197 |
}
|
198 |
|
@@ -201,7 +253,7 @@ class AWS_Provider extends Provider {
|
|
201 |
*
|
202 |
* @param array $args
|
203 |
*/
|
204 |
-
protected function init_client(
|
205 |
$this->aws_client = new Sdk( $args );
|
206 |
}
|
207 |
|
@@ -212,7 +264,7 @@ class AWS_Provider extends Provider {
|
|
212 |
*
|
213 |
* @return array
|
214 |
*/
|
215 |
-
protected function init_service_client_args(
|
216 |
return $args;
|
217 |
}
|
218 |
|
@@ -223,7 +275,7 @@ class AWS_Provider extends Provider {
|
|
223 |
*
|
224 |
* @return S3Client
|
225 |
*/
|
226 |
-
protected function init_service_client(
|
227 |
if ( empty( $args['region'] ) || $args['region'] === $this->default_region ) {
|
228 |
$this->s3_client = $this->aws_client->createMultiRegionS3( $args );
|
229 |
} else {
|
@@ -266,7 +318,7 @@ class AWS_Provider extends Provider {
|
|
266 |
*
|
267 |
* @param array $args
|
268 |
*/
|
269 |
-
public function create_bucket(
|
270 |
if ( ! empty( $args['LocationConstraint'] ) ) {
|
271 |
$args['CreateBucketConfiguration']['LocationConstraint'] = $args['LocationConstraint'];
|
272 |
unset( $args['LocationConstraint'] );
|
@@ -293,7 +345,7 @@ class AWS_Provider extends Provider {
|
|
293 |
*
|
294 |
* @return string
|
295 |
*/
|
296 |
-
public function get_bucket_location(
|
297 |
$location = $this->s3_client->getBucketLocation( $args );
|
298 |
$region = empty( $location['LocationConstraint'] ) ? '' : $location['LocationConstraint'];
|
299 |
|
@@ -307,7 +359,7 @@ class AWS_Provider extends Provider {
|
|
307 |
*
|
308 |
* @return array
|
309 |
*/
|
310 |
-
public function list_buckets(
|
311 |
return $this->s3_client->listBuckets( $args )->toArray();
|
312 |
}
|
313 |
|
@@ -320,17 +372,17 @@ class AWS_Provider extends Provider {
|
|
320 |
*
|
321 |
* @return bool
|
322 |
*/
|
323 |
-
public function does_object_exist( $bucket, $key,
|
324 |
return $this->s3_client->doesObjectExist( $bucket, $key, $options );
|
325 |
}
|
326 |
|
327 |
/**
|
328 |
-
* Get
|
329 |
*
|
330 |
* @return string
|
331 |
*/
|
332 |
-
public function
|
333 |
-
return static::
|
334 |
}
|
335 |
|
336 |
/**
|
@@ -342,6 +394,77 @@ class AWS_Provider extends Provider {
|
|
342 |
return static::PRIVATE_ACL;
|
343 |
}
|
344 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
345 |
/**
|
346 |
* Download object, destination specified in args.
|
347 |
*
|
@@ -349,7 +472,7 @@ class AWS_Provider extends Provider {
|
|
349 |
*
|
350 |
* @param array $args
|
351 |
*/
|
352 |
-
public function get_object(
|
353 |
$this->s3_client->getObject( $args );
|
354 |
}
|
355 |
|
@@ -358,12 +481,12 @@ class AWS_Provider extends Provider {
|
|
358 |
*
|
359 |
* @param string $bucket
|
360 |
* @param string $key
|
361 |
-
* @param int $
|
362 |
* @param array $args
|
363 |
*
|
364 |
* @return string
|
365 |
*/
|
366 |
-
public function get_object_url( $bucket, $key, $
|
367 |
$commandArgs = [ 'Bucket' => $bucket, 'Key' => $key ];
|
368 |
|
369 |
if ( ! empty( $args ) ) {
|
@@ -372,10 +495,10 @@ class AWS_Provider extends Provider {
|
|
372 |
|
373 |
$command = $this->s3_client->getCommand( 'GetObject', $commandArgs );
|
374 |
|
375 |
-
if ( empty( $
|
376 |
return (string) \DeliciousBrains\WP_Offload_Media\Aws3\Aws\serialize( $command )->getUri();
|
377 |
} else {
|
378 |
-
return (string) $this->s3_client->createPresignedRequest( $command, $
|
379 |
}
|
380 |
}
|
381 |
|
@@ -386,7 +509,7 @@ class AWS_Provider extends Provider {
|
|
386 |
*
|
387 |
* @return array
|
388 |
*/
|
389 |
-
public function list_objects(
|
390 |
return $this->s3_client->listObjects( $args )->toArray();
|
391 |
}
|
392 |
|
@@ -395,16 +518,27 @@ class AWS_Provider extends Provider {
|
|
395 |
*
|
396 |
* @param array $args
|
397 |
*/
|
398 |
-
public function update_object_acl(
|
399 |
$this->s3_client->putObjectAcl( $args );
|
400 |
}
|
401 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
402 |
/**
|
403 |
* Upload file to bucket.
|
404 |
*
|
405 |
* @param array $args
|
406 |
*/
|
407 |
-
public function upload_object(
|
408 |
$this->s3_client->putObject( $args );
|
409 |
}
|
410 |
|
@@ -413,7 +547,7 @@ class AWS_Provider extends Provider {
|
|
413 |
*
|
414 |
* @param array $args
|
415 |
*/
|
416 |
-
public function delete_object(
|
417 |
$this->s3_client->deleteObject( $args );
|
418 |
}
|
419 |
|
@@ -422,7 +556,7 @@ class AWS_Provider extends Provider {
|
|
422 |
*
|
423 |
* @param array $args
|
424 |
*/
|
425 |
-
public function delete_objects(
|
426 |
if ( ! isset( $args['Delete'] ) && isset( $args['Objects'] ) ) {
|
427 |
$args['Delete']['Objects'] = $args['Objects'];
|
428 |
unset( $args['Objects'] );
|
@@ -438,7 +572,7 @@ class AWS_Provider extends Provider {
|
|
438 |
*
|
439 |
* @return array
|
440 |
*/
|
441 |
-
public function list_keys(
|
442 |
$keys = array();
|
443 |
|
444 |
$commands = array_map( function ( $location ) {
|
@@ -473,29 +607,8 @@ class AWS_Provider extends Provider {
|
|
473 |
*
|
474 |
* @return array Failures with elements Key and Message
|
475 |
*/
|
476 |
-
public function copy_objects(
|
477 |
-
$
|
478 |
-
|
479 |
-
$commands = array_map( function ( $item ) {
|
480 |
-
return $this->s3_client->getCommand( 'CopyObject', $item );
|
481 |
-
}, $items );
|
482 |
-
|
483 |
-
$results = CommandPool::batch( $this->s3_client, $commands );
|
484 |
-
|
485 |
-
if ( ! empty( $results ) ) {
|
486 |
-
foreach ( $results as $result ) {
|
487 |
-
/* @var S3Exception $result */
|
488 |
-
if ( is_a( $result, 'DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception' ) ) {
|
489 |
-
$command = $result->getCommand()->toArray();
|
490 |
-
$failures[] = array(
|
491 |
-
'Key' => $command['Key'],
|
492 |
-
'Message' => $result->getAwsErrorMessage(),
|
493 |
-
);
|
494 |
-
}
|
495 |
-
}
|
496 |
-
}
|
497 |
-
|
498 |
-
return $failures;
|
499 |
}
|
500 |
|
501 |
/**
|
@@ -544,7 +657,6 @@ class AWS_Provider extends Provider {
|
|
544 |
'Bucket' => $bucket,
|
545 |
'Key' => $key,
|
546 |
'Body' => $file_contents,
|
547 |
-
'ACL' => self::DEFAULT_ACL,
|
548 |
) );
|
549 |
|
550 |
// delete it straight away if created
|
@@ -576,14 +688,7 @@ class AWS_Provider extends Provider {
|
|
576 |
$prefix = 's3';
|
577 |
|
578 |
if ( '' !== $region ) {
|
579 |
-
$
|
580 |
-
if ( 'eu-central-1' == $region && ! is_null( $expires ) ) {
|
581 |
-
// if we are creating a secure URL for a Frankfurt base file use the alternative delimiter
|
582 |
-
// http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
|
583 |
-
$delimiter = '.';
|
584 |
-
}
|
585 |
-
|
586 |
-
$prefix .= $delimiter . $region;
|
587 |
}
|
588 |
|
589 |
return $prefix;
|
@@ -592,26 +697,19 @@ class AWS_Provider extends Provider {
|
|
592 |
/**
|
593 |
* Get the url domain for the files
|
594 |
*
|
595 |
-
* @param string $domain
|
596 |
* @param string $bucket
|
597 |
* @param string $region
|
598 |
* @param int $expires
|
599 |
-
* @param array $args
|
600 |
-
* @param bool $preview When generating the URL preview sanitize certain output
|
601 |
*
|
602 |
* @return string
|
603 |
*/
|
604 |
-
protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array()
|
605 |
-
if ( '
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
}
|
610 |
-
|
611 |
-
$domain = $cloudfront;
|
612 |
-
} elseif ( 'virtual-host' === $args['domain'] ) {
|
613 |
-
$domain = $bucket;
|
614 |
-
} elseif ( 'path' === $args['domain'] || $args['force-https'] ) {
|
615 |
$domain = $domain . '/' . $bucket;
|
616 |
} else {
|
617 |
$domain = $bucket . '.' . $domain;
|
@@ -625,10 +723,11 @@ class AWS_Provider extends Provider {
|
|
625 |
*
|
626 |
* @param string $bucket
|
627 |
* @param string $prefix
|
|
|
628 |
*
|
629 |
* @return string
|
630 |
*/
|
631 |
-
protected function get_console_url_suffix_param( $bucket = '', $prefix = '' ) {
|
632 |
-
return '';
|
633 |
}
|
634 |
}
|
1 |
<?php
|
2 |
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Storage;
|
4 |
|
5 |
use AS3CF_Utils;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandPool;
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception;
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3Client;
|
10 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sdk;
|
11 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Storage\Streams\AWS_S3_Stream_Wrapper;
|
12 |
|
13 |
+
class AWS_Provider extends Storage_Provider {
|
14 |
|
15 |
/**
|
16 |
* @var Sdk
|
97 |
'AWS_USE_EC2_IAM_ROLE',
|
98 |
);
|
99 |
|
100 |
+
/**
|
101 |
+
* @var bool
|
102 |
+
*/
|
103 |
+
protected static $block_public_access_allowed = true;
|
104 |
+
|
105 |
/**
|
106 |
* @var array
|
107 |
*/
|
111 |
'us-west-1' => 'US West (N. California)',
|
112 |
'us-west-2' => 'US West (Oregon)',
|
113 |
'ca-central-1' => 'Canada (Central)',
|
114 |
+
'af-south-1' => 'Africa (Cape Town)',
|
115 |
+
'ap-east-1' => 'Asia Pacific (Hong Kong)',
|
116 |
'ap-south-1' => 'Asia Pacific (Mumbai)',
|
117 |
'ap-northeast-2' => 'Asia Pacific (Seoul)',
|
118 |
+
'ap-northeast-3' => 'Asia Pacific (Osaka-Local)',
|
119 |
'ap-southeast-1' => 'Asia Pacific (Singapore)',
|
120 |
'ap-southeast-2' => 'Asia Pacific (Sydney)',
|
121 |
'ap-northeast-1' => 'Asia Pacific (Tokyo)',
|
122 |
+
'cn-north-1' => 'China (Beijing)',
|
123 |
+
'cn-northwest-1' => 'China (Ningxia)',
|
124 |
'eu-central-1' => 'EU (Frankfurt)',
|
125 |
'eu-west-1' => 'EU (Ireland)',
|
126 |
'eu-west-2' => 'EU (London)',
|
127 |
+
'eu-south-1' => 'EU (Milan)',
|
128 |
'eu-west-3' => 'EU (Paris)',
|
129 |
+
'eu-north-1' => 'EU (Stockholm)',
|
130 |
+
'me-south-1' => 'Middle East (Bahrain)',
|
131 |
'sa-east-1' => 'South America (Sao Paulo)',
|
132 |
);
|
133 |
|
144 |
/**
|
145 |
* @var string
|
146 |
*/
|
147 |
+
protected $console_url = 'https://console.aws.amazon.com/s3/buckets/';
|
148 |
|
149 |
/**
|
150 |
* @var string
|
151 |
*/
|
152 |
+
protected $console_url_prefix_param = '/';
|
153 |
|
154 |
const API_VERSION = '2006-03-01';
|
155 |
const SIGNATURE_VERSION = 'v4';
|
156 |
|
157 |
+
const PUBLIC_ACL = 'public-read';
|
158 |
const PRIVATE_ACL = 'private';
|
159 |
|
160 |
+
/**
|
161 |
+
* Keeps track of Block Public Access state for buckets to save hitting API.
|
162 |
+
*
|
163 |
+
* @var array
|
164 |
+
*/
|
165 |
+
private $blocked_buckets = array();
|
166 |
+
|
167 |
/**
|
168 |
* AWS_Provider constructor.
|
169 |
*
|
178 |
require_once $as3cf->get_plugin_sdks_dir_path() . '/Aws3/aws-autoloader.php';
|
179 |
}
|
180 |
|
181 |
+
/**
|
182 |
+
* Run a command over a batch of items, returning any failures.
|
183 |
+
*
|
184 |
+
* @param string $command
|
185 |
+
* @param array $items
|
186 |
+
*
|
187 |
+
* @return array Failures with elements Key and Message
|
188 |
+
*
|
189 |
+
* NOTE: Only really useful for commands that take 'Key' as one of their args.
|
190 |
+
*/
|
191 |
+
private function batch_command( $command, array $items ) {
|
192 |
+
$failures = array();
|
193 |
+
|
194 |
+
$commands = array_map( function ( $item ) use ( $command ) {
|
195 |
+
return $this->s3_client->getCommand( $command, $item );
|
196 |
+
}, $items );
|
197 |
+
|
198 |
+
$results = CommandPool::batch( $this->s3_client, $commands );
|
199 |
+
|
200 |
+
if ( ! empty( $results ) ) {
|
201 |
+
foreach ( $results as $result ) {
|
202 |
+
/* @var S3Exception $result */
|
203 |
+
if ( is_a( $result, 'DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception' ) ) {
|
204 |
+
$failed_command = $result->getCommand()->toArray();
|
205 |
+
$failures[] = array(
|
206 |
+
'Key' => $failed_command['Key'],
|
207 |
+
'Message' => $result->getAwsErrorMessage(),
|
208 |
+
);
|
209 |
+
}
|
210 |
+
}
|
211 |
+
}
|
212 |
+
|
213 |
+
return $failures;
|
214 |
+
}
|
215 |
+
|
216 |
/**
|
217 |
* Disable AWS CSM which tries to check ~/.aws/config causing issues if open_basedir in effect.
|
218 |
*
|
244 |
*
|
245 |
* @return array
|
246 |
*/
|
247 |
+
protected function init_client_args( array $args ) {
|
248 |
return $args;
|
249 |
}
|
250 |
|
253 |
*
|
254 |
* @param array $args
|
255 |
*/
|
256 |
+
protected function init_client( array $args ) {
|
257 |
$this->aws_client = new Sdk( $args );
|
258 |
}
|
259 |
|
264 |
*
|
265 |
* @return array
|
266 |
*/
|
267 |
+
protected function init_service_client_args( array $args ) {
|
268 |
return $args;
|
269 |
}
|
270 |
|
275 |
*
|
276 |
* @return S3Client
|
277 |
*/
|
278 |
+
protected function init_service_client( array $args ) {
|
279 |
if ( empty( $args['region'] ) || $args['region'] === $this->default_region ) {
|
280 |
$this->s3_client = $this->aws_client->createMultiRegionS3( $args );
|
281 |
} else {
|
318 |
*
|
319 |
* @param array $args
|
320 |
*/
|
321 |
+
public function create_bucket( array $args ) {
|
322 |
if ( ! empty( $args['LocationConstraint'] ) ) {
|
323 |
$args['CreateBucketConfiguration']['LocationConstraint'] = $args['LocationConstraint'];
|
324 |
unset( $args['LocationConstraint'] );
|
345 |
*
|
346 |
* @return string
|
347 |
*/
|
348 |
+
public function get_bucket_location( array $args ) {
|
349 |
$location = $this->s3_client->getBucketLocation( $args );
|
350 |
$region = empty( $location['LocationConstraint'] ) ? '' : $location['LocationConstraint'];
|
351 |
|
359 |
*
|
360 |
* @return array
|
361 |
*/
|
362 |
+
public function list_buckets( array $args = array() ) {
|
363 |
return $this->s3_client->listBuckets( $args )->toArray();
|
364 |
}
|
365 |
|
372 |
*
|
373 |
* @return bool
|
374 |
*/
|
375 |
+
public function does_object_exist( $bucket, $key, array $options = array() ) {
|
376 |
return $this->s3_client->doesObjectExist( $bucket, $key, $options );
|
377 |
}
|
378 |
|
379 |
/**
|
380 |
+
* Get public "canned" ACL string.
|
381 |
*
|
382 |
* @return string
|
383 |
*/
|
384 |
+
public function get_public_acl() {
|
385 |
+
return static::PUBLIC_ACL;
|
386 |
}
|
387 |
|
388 |
/**
|
394 |
return static::PRIVATE_ACL;
|
395 |
}
|
396 |
|
397 |
+
/**
|
398 |
+
* Is public access to the given bucket prohibited?
|
399 |
+
*
|
400 |
+
* @param string $bucket
|
401 |
+
*
|
402 |
+
* @return bool|null
|
403 |
+
*
|
404 |
+
* Note: It's very possible that permissions don't allow the check, in which case default value is returned.
|
405 |
+
*/
|
406 |
+
public function public_access_blocked( $bucket ) {
|
407 |
+
if ( isset( $this->blocked_buckets[ $bucket ] ) ) {
|
408 |
+
return $this->blocked_buckets[ $bucket ];
|
409 |
+
}
|
410 |
+
|
411 |
+
$blocked = parent::public_access_blocked( $bucket );
|
412 |
+
|
413 |
+
try {
|
414 |
+
$result = $this->s3_client->getPublicAccessBlock( [ 'Bucket' => $bucket ] );
|
415 |
+
} catch ( \Exception $e ) {
|
416 |
+
// No policy defined at either bucket or account level, so no blocking happening.
|
417 |
+
if ( false !== strpos( $e->getMessage(), 'NoSuchPublicAccessBlockConfiguration' ) ) {
|
418 |
+
$blocked = false;
|
419 |
+
}
|
420 |
+
}
|
421 |
+
|
422 |
+
if ( ! empty( $result ) && ! empty( $result['PublicAccessBlockConfiguration'] ) ) {
|
423 |
+
$settings = $result['PublicAccessBlockConfiguration'];
|
424 |
+
if (
|
425 |
+
empty( $settings['BlockPublicAcls'] ) &&
|
426 |
+
empty( $settings['BlockPublicPolicy'] ) &&
|
427 |
+
empty( $settings['IgnorePublicAcls'] ) &&
|
428 |
+
empty( $settings['RestrictPublicBuckets'] ) ) {
|
429 |
+
$blocked = false;
|
430 |
+
} else {
|
431 |
+
$blocked = true;
|
432 |
+
}
|
433 |
+
}
|
434 |
+
|
435 |
+
$this->blocked_buckets[ $bucket ] = $blocked;
|
436 |
+
|
437 |
+
return $blocked;
|
438 |
+
}
|
439 |
+
|
440 |
+
/**
|
441 |
+
* Update the block public access setting for the given bucket.
|
442 |
+
*
|
443 |
+
* @param string $bucket
|
444 |
+
* @param bool $block
|
445 |
+
*/
|
446 |
+
public function block_public_access( $bucket, $block ) {
|
447 |
+
if ( empty( $bucket ) || ! is_bool( $block ) ) {
|
448 |
+
return;
|
449 |
+
}
|
450 |
+
|
451 |
+
$setting = array(
|
452 |
+
'Bucket' => $bucket,
|
453 |
+
'PublicAccessBlockConfiguration' => array(
|
454 |
+
'BlockPublicAcls' => $block,
|
455 |
+
'BlockPublicPolicy' => $block,
|
456 |
+
'IgnorePublicAcls' => $block,
|
457 |
+
'RestrictPublicBuckets' => $block,
|
458 |
+
),
|
459 |
+
);
|
460 |
+
|
461 |
+
$this->s3_client->putPublicAccessBlock( $setting );
|
462 |
+
|
463 |
+
unset( $this->blocked_buckets[ $bucket ] );
|
464 |
+
|
465 |
+
return;
|
466 |
+
}
|
467 |
+
|
468 |
/**
|
469 |
* Download object, destination specified in args.
|
470 |
*
|
472 |
*
|
473 |
* @param array $args
|
474 |
*/
|
475 |
+
public function get_object( array $args ) {
|
476 |
$this->s3_client->getObject( $args );
|
477 |
}
|
478 |
|
481 |
*
|
482 |
* @param string $bucket
|
483 |
* @param string $key
|
484 |
+
* @param int $timestamp
|
485 |
* @param array $args
|
486 |
*
|
487 |
* @return string
|
488 |
*/
|
489 |
+
public function get_object_url( $bucket, $key, $timestamp, array $args = array() ) {
|
490 |
$commandArgs = [ 'Bucket' => $bucket, 'Key' => $key ];
|
491 |
|
492 |
if ( ! empty( $args ) ) {
|
495 |
|
496 |
$command = $this->s3_client->getCommand( 'GetObject', $commandArgs );
|
497 |
|
498 |
+
if ( empty( $timestamp ) || ! is_int( $timestamp ) || $timestamp < 0 ) {
|
499 |
return (string) \DeliciousBrains\WP_Offload_Media\Aws3\Aws\serialize( $command )->getUri();
|
500 |
} else {
|
501 |
+
return (string) $this->s3_client->createPresignedRequest( $command, $timestamp )->getUri();
|
502 |
}
|
503 |
}
|
504 |
|
509 |
*
|
510 |
* @return array
|
511 |
*/
|
512 |
+
public function list_objects( array $args = array() ) {
|
513 |
return $this->s3_client->listObjects( $args )->toArray();
|
514 |
}
|
515 |
|
518 |
*
|
519 |
* @param array $args
|
520 |
*/
|
521 |
+
public function update_object_acl( array $args ) {
|
522 |
$this->s3_client->putObjectAcl( $args );
|
523 |
}
|
524 |
|
525 |
+
/**
|
526 |
+
* Update the ACL for multiple objects.
|
527 |
+
*
|
528 |
+
* @param array $items
|
529 |
+
*
|
530 |
+
* @return array Failures with elements Key and Message
|
531 |
+
*/
|
532 |
+
public function update_object_acls( array $items ) {
|
533 |
+
return $this->batch_command( 'PutObjectAcl', $items );
|
534 |
+
}
|
535 |
+
|
536 |
/**
|
537 |
* Upload file to bucket.
|
538 |
*
|
539 |
* @param array $args
|
540 |
*/
|
541 |
+
public function upload_object( array $args ) {
|
542 |
$this->s3_client->putObject( $args );
|
543 |
}
|
544 |
|
547 |
*
|
548 |
* @param array $args
|
549 |
*/
|
550 |
+
public function delete_object( array $args ) {
|
551 |
$this->s3_client->deleteObject( $args );
|
552 |
}
|
553 |
|
556 |
*
|
557 |
* @param array $args
|
558 |
*/
|
559 |
+
public function delete_objects( array $args ) {
|
560 |
if ( ! isset( $args['Delete'] ) && isset( $args['Objects'] ) ) {
|
561 |
$args['Delete']['Objects'] = $args['Objects'];
|
562 |
unset( $args['Objects'] );
|
572 |
*
|
573 |
* @return array
|
574 |
*/
|
575 |
+
public function list_keys( array $locations ) {
|
576 |
$keys = array();
|
577 |
|
578 |
$commands = array_map( function ( $location ) {
|
607 |
*
|
608 |
* @return array Failures with elements Key and Message
|
609 |
*/
|
610 |
+
public function copy_objects( array $items ) {
|
611 |
+
return $this->batch_command( 'CopyObject', $items );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
612 |
}
|
613 |
|
614 |
/**
|
657 |
'Bucket' => $bucket,
|
658 |
'Key' => $key,
|
659 |
'Body' => $file_contents,
|
|
|
660 |
) );
|
661 |
|
662 |
// delete it straight away if created
|
688 |
$prefix = 's3';
|
689 |
|
690 |
if ( '' !== $region ) {
|
691 |
+
$prefix .= '.' . $region;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
692 |
}
|
693 |
|
694 |
return $prefix;
|
697 |
/**
|
698 |
* Get the url domain for the files
|
699 |
*
|
700 |
+
* @param string $domain Likely prefixed with region
|
701 |
* @param string $bucket
|
702 |
* @param string $region
|
703 |
* @param int $expires
|
704 |
+
* @param array $args Allows you to specify custom URL settings
|
|
|
705 |
*
|
706 |
* @return string
|
707 |
*/
|
708 |
+
protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array() ) {
|
709 |
+
if ( apply_filters( 'as3cf_' . static::get_provider_key_name() . '_' . static::get_service_key_name() . '_bucket_in_path', false !== strpos( $bucket, '.' ) ) ) {
|
710 |
+
// TODO: This mode is going away, kinda, sorta, one day.
|
711 |
+
// TODO: When AWS sort out HTTPS for bucket in domain with dots we can remove this format.
|
712 |
+
// @see https://aws.amazon.com/blogs/aws/amazon-s3-path-deprecation-plan-the-rest-of-the-story/
|
|
|
|
|
|
|
|
|
|
|
|
|
713 |
$domain = $domain . '/' . $bucket;
|
714 |
} else {
|
715 |
$domain = $bucket . '.' . $domain;
|
723 |
*
|
724 |
* @param string $bucket
|
725 |
* @param string $prefix
|
726 |
+
* @param string $region
|
727 |
*
|
728 |
* @return string
|
729 |
*/
|
730 |
+
protected function get_console_url_suffix_param( $bucket = '', $prefix = '', $region = '' ) {
|
731 |
+
return empty( $region ) ? '' : '?region=' . $region;
|
732 |
}
|
733 |
}
|
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace DeliciousBrains\WP_Offload_Media\Providers;
|
4 |
|
5 |
class DigitalOcean_Provider extends AWS_Provider {
|
6 |
|
@@ -71,6 +71,11 @@ class DigitalOcean_Provider extends AWS_Provider {
|
|
71 |
*/
|
72 |
protected static $use_server_roles_constants = array();
|
73 |
|
|
|
|
|
|
|
|
|
|
|
74 |
/**
|
75 |
* @var array
|
76 |
*/
|
@@ -143,6 +148,17 @@ class DigitalOcean_Provider extends AWS_Provider {
|
|
143 |
return $args;
|
144 |
}
|
145 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
/**
|
147 |
* Create bucket.
|
148 |
*
|
1 |
<?php
|
2 |
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Storage;
|
4 |
|
5 |
class DigitalOcean_Provider extends AWS_Provider {
|
6 |
|
71 |
*/
|
72 |
protected static $use_server_roles_constants = array();
|
73 |
|
74 |
+
/**
|
75 |
+
* @var bool
|
76 |
+
*/
|
77 |
+
protected static $block_public_access_allowed = false;
|
78 |
+
|
79 |
/**
|
80 |
* @var array
|
81 |
*/
|
148 |
return $args;
|
149 |
}
|
150 |
|
151 |
+
/**
|
152 |
+
* Update the block public access setting for the given bucket.
|
153 |
+
*
|
154 |
+
* @param string $bucket
|
155 |
+
* @param bool $block
|
156 |
+
*/
|
157 |
+
public function block_public_access( $bucket, $block ) {
|
158 |
+
// DigitalOcean doesn't support this, so do nothing.
|
159 |
+
return;
|
160 |
+
}
|
161 |
+
|
162 |
/**
|
163 |
* Create bucket.
|
164 |
*
|
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace DeliciousBrains\WP_Offload_Media\Providers;
|
4 |
|
5 |
use AS3CF_Utils;
|
6 |
use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Core\Exception\GoogleException;
|
@@ -8,9 +8,9 @@ use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Core\ServiceBuilder;
|
|
8 |
use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\Bucket;
|
9 |
use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StorageClient;
|
10 |
use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StorageObject;
|
11 |
-
use DeliciousBrains\WP_Offload_Media\Providers\Streams\GCP_GCS_Stream_Wrapper;
|
12 |
|
13 |
-
class GCP_Provider extends
|
14 |
|
15 |
/**
|
16 |
* @var ServiceBuilder
|
@@ -97,18 +97,25 @@ class GCP_Provider extends Provider {
|
|
97 |
'us-east4' => 'Northern Virginia',
|
98 |
'us-west1' => 'Oregon',
|
99 |
'us-west2' => 'Los Angeles',
|
|
|
|
|
100 |
'southamerica-east1' => 'São Paulo',
|
101 |
'europe-north1' => 'Finland',
|
102 |
'europe-west1' => 'Belgium',
|
103 |
'europe-west2' => 'London',
|
104 |
'europe-west3' => 'Frankfurt',
|
105 |
'europe-west4' => 'Netherlands',
|
|
|
106 |
'asia-east1' => 'Taiwan',
|
107 |
'asia-east2' => 'Hong Kong',
|
108 |
'asia-northeast1' => 'Tokyo',
|
|
|
|
|
109 |
'asia-south1' => 'Mumbai',
|
110 |
'asia-southeast1' => 'Singapore',
|
111 |
'australia-southeast1' => 'Sydney',
|
|
|
|
|
112 |
);
|
113 |
|
114 |
/**
|
@@ -131,7 +138,7 @@ class GCP_Provider extends Provider {
|
|
131 |
*/
|
132 |
protected $console_url_prefix_param = '/';
|
133 |
|
134 |
-
const
|
135 |
const PRIVATE_ACL = 'projectPrivate';
|
136 |
|
137 |
/**
|
@@ -162,7 +169,7 @@ class GCP_Provider extends Provider {
|
|
162 |
*
|
163 |
* @return array
|
164 |
*/
|
165 |
-
protected function init_client_args(
|
166 |
return $args;
|
167 |
}
|
168 |
|
@@ -171,7 +178,7 @@ class GCP_Provider extends Provider {
|
|
171 |
*
|
172 |
* @param array $args
|
173 |
*/
|
174 |
-
protected function init_client(
|
175 |
$this->cloud = new ServiceBuilder( $args );
|
176 |
}
|
177 |
|
@@ -182,7 +189,7 @@ class GCP_Provider extends Provider {
|
|
182 |
*
|
183 |
* @return array
|
184 |
*/
|
185 |
-
protected function init_service_client_args(
|
186 |
return $args;
|
187 |
}
|
188 |
|
@@ -193,7 +200,7 @@ class GCP_Provider extends Provider {
|
|
193 |
*
|
194 |
* @return StorageClient
|
195 |
*/
|
196 |
-
protected function init_service_client(
|
197 |
$this->storage = $this->cloud->storage( $args );
|
198 |
|
199 |
return $this->storage;
|
@@ -222,7 +229,7 @@ class GCP_Provider extends Provider {
|
|
222 |
*
|
223 |
* @throws GoogleException
|
224 |
*/
|
225 |
-
public function create_bucket(
|
226 |
$name = '';
|
227 |
if ( ! empty( $args['Bucket'] ) ) {
|
228 |
$name = $args['Bucket'];
|
@@ -255,7 +262,7 @@ class GCP_Provider extends Provider {
|
|
255 |
*
|
256 |
* @return string
|
257 |
*/
|
258 |
-
public function get_bucket_location(
|
259 |
$info = $this->storage->bucket( $args['Bucket'] )->info();
|
260 |
$region = empty( $info['location'] ) ? '' : $info['location'];
|
261 |
|
@@ -270,7 +277,7 @@ class GCP_Provider extends Provider {
|
|
270 |
* @return array
|
271 |
* @throws GoogleException
|
272 |
*/
|
273 |
-
public function list_buckets(
|
274 |
$result = array();
|
275 |
|
276 |
$buckets = $this->storage->buckets( $args );
|
@@ -296,17 +303,17 @@ class GCP_Provider extends Provider {
|
|
296 |
*
|
297 |
* @return bool
|
298 |
*/
|
299 |
-
public function does_object_exist( $bucket, $key,
|
300 |
return $this->storage->bucket( $bucket )->object( $key )->exists( $options );
|
301 |
}
|
302 |
|
303 |
/**
|
304 |
-
* Get
|
305 |
*
|
306 |
* @return string
|
307 |
*/
|
308 |
-
public function
|
309 |
-
return static::
|
310 |
}
|
311 |
|
312 |
/**
|
@@ -326,7 +333,7 @@ class GCP_Provider extends Provider {
|
|
326 |
*
|
327 |
* @param array $args
|
328 |
*/
|
329 |
-
public function get_object(
|
330 |
$this->storage->bucket( $args['Bucket'] )->object( $args['Key'] )->downloadToFile( $args['SaveAs'] );
|
331 |
}
|
332 |
|
@@ -335,13 +342,13 @@ class GCP_Provider extends Provider {
|
|
335 |
*
|
336 |
* @param string $bucket
|
337 |
* @param string $key
|
338 |
-
* @param int $
|
339 |
* @param array $args
|
340 |
*
|
341 |
* @return string
|
342 |
*/
|
343 |
-
public function get_object_url( $bucket, $key, $
|
344 |
-
if ( empty( $
|
345 |
$info = $this->storage->bucket( $bucket )->object( $key )->info();
|
346 |
$link = empty( $info['selfLink'] ) ? '' : $info['selfLink'];
|
347 |
|
@@ -353,7 +360,7 @@ class GCP_Provider extends Provider {
|
|
353 |
$options['cname'] = $args['BaseURL'];
|
354 |
}
|
355 |
|
356 |
-
return $this->storage->bucket( $bucket )->object( $key )->signedUrl(
|
357 |
}
|
358 |
}
|
359 |
|
@@ -364,7 +371,7 @@ class GCP_Provider extends Provider {
|
|
364 |
*
|
365 |
* @return array
|
366 |
*/
|
367 |
-
public function list_objects(
|
368 |
$result = array();
|
369 |
|
370 |
$objects = $this->storage->bucket( $args['Bucket'] )->objects( $args['Prefix'] );
|
@@ -387,11 +394,42 @@ class GCP_Provider extends Provider {
|
|
387 |
* Update the ACL for an object.
|
388 |
*
|
389 |
* @param array $args
|
|
|
|
|
390 |
*/
|
391 |
-
public function update_object_acl(
|
|
|
|
|
|
|
|
|
392 |
$this->storage->bucket( $args['Bucket'] )->object( $args['Key'] )->update( array( 'predefinedAcl' => $args['ACL'] ) );
|
393 |
}
|
394 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
395 |
/**
|
396 |
* Upload file to bucket.
|
397 |
*
|
@@ -399,7 +437,7 @@ class GCP_Provider extends Provider {
|
|
399 |
*
|
400 |
* @throws \Exception
|
401 |
*/
|
402 |
-
public function upload_object(
|
403 |
if ( ! empty( $args['SourceFile'] ) ) {
|
404 |
$file = fopen( $args['SourceFile'], 'r' );
|
405 |
} elseif ( ! empty( $args['Body'] ) ) {
|
@@ -409,10 +447,13 @@ class GCP_Provider extends Provider {
|
|
409 |
}
|
410 |
|
411 |
$options = array(
|
412 |
-
'name'
|
413 |
-
'predefinedAcl' => $args['ACL'],
|
414 |
);
|
415 |
|
|
|
|
|
|
|
|
|
416 |
if ( ! empty( $args['ContentType'] ) ) {
|
417 |
$options['metadata']['contentType'] = $args['ContentType'];
|
418 |
}
|
@@ -431,7 +472,7 @@ class GCP_Provider extends Provider {
|
|
431 |
*
|
432 |
* @param array $args
|
433 |
*/
|
434 |
-
public function delete_object(
|
435 |
$this->storage->bucket( $args['Bucket'] )->object( $args['Key'] )->delete();
|
436 |
}
|
437 |
|
@@ -440,7 +481,7 @@ class GCP_Provider extends Provider {
|
|
440 |
*
|
441 |
* @param array $args
|
442 |
*/
|
443 |
-
public function delete_objects(
|
444 |
if ( isset( $args['Delete']['Objects'] ) ) {
|
445 |
$keys = $args['Delete']['Objects'];
|
446 |
} elseif ( isset( $args['Objects'] ) ) {
|
@@ -464,7 +505,7 @@ class GCP_Provider extends Provider {
|
|
464 |
*
|
465 |
* @return array
|
466 |
*/
|
467 |
-
public function list_keys(
|
468 |
$keys = array();
|
469 |
|
470 |
$results = array_map( function ( $location ) {
|
@@ -488,20 +529,23 @@ class GCP_Provider extends Provider {
|
|
488 |
*
|
489 |
* @return array Failures with elements Key and Message
|
490 |
*/
|
491 |
-
public function copy_objects(
|
492 |
$failures = array();
|
493 |
|
494 |
// Unfortunately the GCP PHP SDK does not have batch operations.
|
495 |
foreach ( $items as $item ) {
|
496 |
list( $bucket, $key ) = explode( '/', urldecode( $item['CopySource'] ), 2 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
497 |
try {
|
498 |
-
$this->storage->bucket( $bucket )->object( $key )->copy(
|
499 |
-
$item['Bucket'],
|
500 |
-
array(
|
501 |
-
'name' => $item['Key'],
|
502 |
-
'predefinedAcl' => $item['ACL'],
|
503 |
-
)
|
504 |
-
);
|
505 |
} catch ( \Exception $e ) {
|
506 |
$failures[] = array(
|
507 |
'Key' => $item['Key'],
|
@@ -562,7 +606,6 @@ class GCP_Provider extends Provider {
|
|
562 |
'Bucket' => $bucket,
|
563 |
'Key' => $key,
|
564 |
'Body' => $file_contents,
|
565 |
-
'ACL' => self::DEFAULT_ACL,
|
566 |
) );
|
567 |
|
568 |
// delete it straight away if created
|
@@ -578,6 +621,8 @@ class GCP_Provider extends Provider {
|
|
578 |
return $e->getMessage();
|
579 |
}
|
580 |
}
|
|
|
|
|
581 |
}
|
582 |
|
583 |
/**
|
@@ -595,25 +640,20 @@ class GCP_Provider extends Provider {
|
|
595 |
/**
|
596 |
* Get the url domain for the files
|
597 |
*
|
598 |
-
* @param string $domain
|
599 |
* @param string $bucket
|
600 |
* @param string $region
|
601 |
* @param int $expires
|
602 |
-
* @param array $args
|
603 |
-
* @param bool $preview When generating the URL preview sanitize certain output
|
604 |
*
|
605 |
* @return string
|
606 |
*/
|
607 |
-
protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array()
|
608 |
-
if ( '
|
609 |
-
$cloudfront = $args['cloudfront'];
|
610 |
-
if ( $preview ) {
|
611 |
-
$cloudfront = AS3CF_Utils::sanitize_custom_domain( $cloudfront );
|
612 |
-
}
|
613 |
-
|
614 |
-
$domain = $cloudfront;
|
615 |
-
} else {
|
616 |
$domain = $domain . '/' . $bucket;
|
|
|
|
|
|
|
617 |
}
|
618 |
|
619 |
return $domain;
|
@@ -624,10 +664,11 @@ class GCP_Provider extends Provider {
|
|
624 |
*
|
625 |
* @param string $bucket
|
626 |
* @param string $prefix
|
|
|
627 |
*
|
628 |
* @return string
|
629 |
*/
|
630 |
-
protected function get_console_url_suffix_param( $bucket = '', $prefix = '' ) {
|
631 |
if ( ! empty( $this->get_project_id() ) ) {
|
632 |
return '?project=' . $this->get_project_id();
|
633 |
}
|
1 |
<?php
|
2 |
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Storage;
|
4 |
|
5 |
use AS3CF_Utils;
|
6 |
use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Core\Exception\GoogleException;
|
8 |
use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\Bucket;
|
9 |
use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StorageClient;
|
10 |
use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StorageObject;
|
11 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Storage\Streams\GCP_GCS_Stream_Wrapper;
|
12 |
|
13 |
+
class GCP_Provider extends Storage_Provider {
|
14 |
|
15 |
/**
|
16 |
* @var ServiceBuilder
|
97 |
'us-east4' => 'Northern Virginia',
|
98 |
'us-west1' => 'Oregon',
|
99 |
'us-west2' => 'Los Angeles',
|
100 |
+
'us-west3' => 'Salt Lake City',
|
101 |
+
'us-west4' => 'Las Vegas',
|
102 |
'southamerica-east1' => 'São Paulo',
|
103 |
'europe-north1' => 'Finland',
|
104 |
'europe-west1' => 'Belgium',
|
105 |
'europe-west2' => 'London',
|
106 |
'europe-west3' => 'Frankfurt',
|
107 |
'europe-west4' => 'Netherlands',
|
108 |
+
'europe-west6' => 'Zürich',
|
109 |
'asia-east1' => 'Taiwan',
|
110 |
'asia-east2' => 'Hong Kong',
|
111 |
'asia-northeast1' => 'Tokyo',
|
112 |
+
'asia-northeast2' => 'Osaka',
|
113 |
+
'asia-northeast3' => 'Seoul',
|
114 |
'asia-south1' => 'Mumbai',
|
115 |
'asia-southeast1' => 'Singapore',
|
116 |
'australia-southeast1' => 'Sydney',
|
117 |
+
'eur4' => 'EUR4 (Finland/Netherlands Dual-Region)',
|
118 |
+
'nam4' => 'NAM4 (Iowa/South Carolina Dual-Region)',
|
119 |
);
|
120 |
|
121 |
/**
|
138 |
*/
|
139 |
protected $console_url_prefix_param = '/';
|
140 |
|
141 |
+
const PUBLIC_ACL = 'publicRead';
|
142 |
const PRIVATE_ACL = 'projectPrivate';
|
143 |
|
144 |
/**
|
169 |
*
|
170 |
* @return array
|
171 |
*/
|
172 |
+
protected function init_client_args( array $args ) {
|
173 |
return $args;
|
174 |
}
|
175 |
|
178 |
*
|
179 |
* @param array $args
|
180 |
*/
|
181 |
+
protected function init_client( array $args ) {
|
182 |
$this->cloud = new ServiceBuilder( $args );
|
183 |
}
|
184 |
|
189 |
*
|
190 |
* @return array
|
191 |
*/
|
192 |
+
protected function init_service_client_args( array $args ) {
|
193 |
return $args;
|
194 |
}
|
195 |
|
200 |
*
|
201 |
* @return StorageClient
|
202 |
*/
|
203 |
+
protected function init_service_client( array $args ) {
|
204 |
$this->storage = $this->cloud->storage( $args );
|
205 |
|
206 |
return $this->storage;
|
229 |
*
|
230 |
* @throws GoogleException
|
231 |
*/
|
232 |
+
public function create_bucket( array $args ) {
|
233 |
$name = '';
|
234 |
if ( ! empty( $args['Bucket'] ) ) {
|
235 |
$name = $args['Bucket'];
|
262 |
*
|
263 |
* @return string
|
264 |
*/
|
265 |
+
public function get_bucket_location( array $args ) {
|
266 |
$info = $this->storage->bucket( $args['Bucket'] )->info();
|
267 |
$region = empty( $info['location'] ) ? '' : $info['location'];
|
268 |
|
277 |
* @return array
|
278 |
* @throws GoogleException
|
279 |
*/
|
280 |
+
public function list_buckets( array $args = array() ) {
|
281 |
$result = array();
|
282 |
|
283 |
$buckets = $this->storage->buckets( $args );
|
303 |
*
|
304 |
* @return bool
|
305 |
*/
|
306 |
+
public function does_object_exist( $bucket, $key, array $options = array() ) {
|
307 |
return $this->storage->bucket( $bucket )->object( $key )->exists( $options );
|
308 |
}
|
309 |
|
310 |
/**
|
311 |
+
* Get public "canned" ACL string.
|
312 |
*
|
313 |
* @return string
|
314 |
*/
|
315 |
+
public function get_public_acl() {
|
316 |
+
return static::PUBLIC_ACL;
|
317 |
}
|
318 |
|
319 |
/**
|
333 |
*
|
334 |
* @param array $args
|
335 |
*/
|
336 |
+
public function get_object( array $args ) {
|
337 |
$this->storage->bucket( $args['Bucket'] )->object( $args['Key'] )->downloadToFile( $args['SaveAs'] );
|
338 |
}
|
339 |
|
342 |
*
|
343 |
* @param string $bucket
|
344 |
* @param string $key
|
345 |
+
* @param int $timestamp
|
346 |
* @param array $args
|
347 |
*
|
348 |
* @return string
|
349 |
*/
|
350 |
+
public function get_object_url( $bucket, $key, $timestamp, array $args = array() ) {
|
351 |
+
if ( empty( $timestamp ) || ! is_int( $timestamp ) || $timestamp < 0 ) {
|
352 |
$info = $this->storage->bucket( $bucket )->object( $key )->info();
|
353 |
$link = empty( $info['selfLink'] ) ? '' : $info['selfLink'];
|
354 |
|
360 |
$options['cname'] = $args['BaseURL'];
|
361 |
}
|
362 |
|
363 |
+
return $this->storage->bucket( $bucket )->object( $key )->signedUrl( $timestamp, $options );
|
364 |
}
|
365 |
}
|
366 |
|
371 |
*
|
372 |
* @return array
|
373 |
*/
|
374 |
+
public function list_objects( array $args = array() ) {
|
375 |
$result = array();
|
376 |
|
377 |
$objects = $this->storage->bucket( $args['Bucket'] )->objects( $args['Prefix'] );
|
394 |
* Update the ACL for an object.
|
395 |
*
|
396 |
* @param array $args
|
397 |
+
*
|
398 |
+
* @throws \Exception
|
399 |
*/
|
400 |
+
public function update_object_acl( array $args ) {
|
401 |
+
if ( empty( $args['ACL'] ) ) {
|
402 |
+
throw new \Exception( __METHOD__ . ' called without "ACL" arg.' );
|
403 |
+
}
|
404 |
+
|
405 |
$this->storage->bucket( $args['Bucket'] )->object( $args['Key'] )->update( array( 'predefinedAcl' => $args['ACL'] ) );
|
406 |
}
|
407 |
|
408 |
+
/**
|
409 |
+
* Update the ACL for multiple objects.
|
410 |
+
*
|
411 |
+
* @param array $items
|
412 |
+
*
|
413 |
+
* @return array Failures with elements Key and Message
|
414 |
+
*/
|
415 |
+
public function update_object_acls( array $items ) {
|
416 |
+
$failures = array();
|
417 |
+
|
418 |
+
// Unfortunately the GCP PHP SDK does not have batch operations.
|
419 |
+
foreach ( $items as $item ) {
|
420 |
+
try {
|
421 |
+
$this->update_object_acl( $item );
|
422 |
+
} catch ( \Exception $e ) {
|
423 |
+
$failures[] = array(
|
424 |
+
'Key' => $item['Key'],
|
425 |
+
'Message' => $e->getMessage(),
|
426 |
+
);
|
427 |
+
}
|
428 |
+
}
|
429 |
+
|
430 |
+
return $failures;
|
431 |
+
}
|
432 |
+
|
433 |
/**
|
434 |
* Upload file to bucket.
|
435 |
*
|
437 |
*
|
438 |
* @throws \Exception
|
439 |
*/
|
440 |
+
public function upload_object( array $args ) {
|
441 |
if ( ! empty( $args['SourceFile'] ) ) {
|
442 |
$file = fopen( $args['SourceFile'], 'r' );
|
443 |
} elseif ( ! empty( $args['Body'] ) ) {
|
447 |
}
|
448 |
|
449 |
$options = array(
|
450 |
+
'name' => $args['Key'],
|
|
|
451 |
);
|
452 |
|
453 |
+
if ( ! empty( $args['ACL'] ) ) {
|
454 |
+
$options['predefinedAcl'] = $args['ACL'];
|
455 |
+
}
|
456 |
+
|
457 |
if ( ! empty( $args['ContentType'] ) ) {
|
458 |
$options['metadata']['contentType'] = $args['ContentType'];
|
459 |
}
|
472 |
*
|
473 |
* @param array $args
|
474 |
*/
|
475 |
+
public function delete_object( array $args ) {
|
476 |
$this->storage->bucket( $args['Bucket'] )->object( $args['Key'] )->delete();
|
477 |
}
|
478 |
|
481 |
*
|
482 |
* @param array $args
|
483 |
*/
|
484 |
+
public function delete_objects( array $args ) {
|
485 |
if ( isset( $args['Delete']['Objects'] ) ) {
|
486 |
$keys = $args['Delete']['Objects'];
|
487 |
} elseif ( isset( $args['Objects'] ) ) {
|
505 |
*
|
506 |
* @return array
|
507 |
*/
|
508 |
+
public function list_keys( array $locations ) {
|
509 |
$keys = array();
|
510 |
|
511 |
$results = array_map( function ( $location ) {
|
529 |
*
|
530 |
* @return array Failures with elements Key and Message
|
531 |
*/
|
532 |
+
public function copy_objects( array $items ) {
|
533 |
$failures = array();
|
534 |
|
535 |
// Unfortunately the GCP PHP SDK does not have batch operations.
|
536 |
foreach ( $items as $item ) {
|
537 |
list( $bucket, $key ) = explode( '/', urldecode( $item['CopySource'] ), 2 );
|
538 |
+
|
539 |
+
$options = array(
|
540 |
+
'name' => $item['Key'],
|
541 |
+
);
|
542 |
+
|
543 |
+
if ( ! empty( $item['ACL'] ) ) {
|
544 |
+
$options['predefinedAcl'] = $item['ACL'];
|
545 |
+
}
|
546 |
+
|
547 |
try {
|
548 |
+
$this->storage->bucket( $bucket )->object( $key )->copy( $item['Bucket'], $options );
|
|
|
|
|
|
|
|
|
|
|
|
|
549 |
} catch ( \Exception $e ) {
|
550 |
$failures[] = array(
|
551 |
'Key' => $item['Key'],
|
606 |
'Bucket' => $bucket,
|
607 |
'Key' => $key,
|
608 |
'Body' => $file_contents,
|
|
|
609 |
) );
|
610 |
|
611 |
// delete it straight away if created
|
621 |
return $e->getMessage();
|
622 |
}
|
623 |
}
|
624 |
+
|
625 |
+
return false;
|
626 |
}
|
627 |
|
628 |
/**
|
640 |
/**
|
641 |
* Get the url domain for the files
|
642 |
*
|
643 |
+
* @param string $domain Likely prefixed with region
|
644 |
* @param string $bucket
|
645 |
* @param string $region
|
646 |
* @param int $expires
|
647 |
+
* @param array $args Allows you to specify custom URL settings
|
|
|
648 |
*
|
649 |
* @return string
|
650 |
*/
|
651 |
+
protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array() ) {
|
652 |
+
if ( apply_filters( 'as3cf_' . static::get_provider_key_name() . '_' . static::get_service_key_name() . '_bucket_in_path', false !== strpos( $bucket, '.' ) ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
653 |
$domain = $domain . '/' . $bucket;
|
654 |
+
} else {
|
655 |
+
// TODO: Is this mode allowed for GCS native URLs?
|
656 |
+
$domain = $bucket . '.' . $domain;
|
657 |
}
|
658 |
|
659 |
return $domain;
|
664 |
*
|
665 |
* @param string $bucket
|
666 |
* @param string $prefix
|
667 |
+
* @param string $region
|
668 |
*
|
669 |
* @return string
|
670 |
*/
|
671 |
+
protected function get_console_url_suffix_param( $bucket = '', $prefix = '', $region = '' ) {
|
672 |
if ( ! empty( $this->get_project_id() ) ) {
|
673 |
return '?project=' . $this->get_project_id();
|
674 |
}
|
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace DeliciousBrains\WP_Offload_Media\Providers;
|
4 |
|
5 |
use AS3CF_Error;
|
6 |
|
1 |
<?php
|
2 |
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Storage;
|
4 |
|
5 |
use AS3CF_Error;
|
6 |
|
@@ -0,0 +1,958 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Storage;
|
4 |
+
|
5 |
+
use Amazon_S3_And_CloudFront;
|
6 |
+
use AS3CF_Error;
|
7 |
+
use AS3CF_Utils;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Providers\Provider;
|
9 |
+
use Exception;
|
10 |
+
|
11 |
+
abstract class Storage_Provider extends Provider {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* @var
|
15 |
+
*/
|
16 |
+
private $client;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
protected static $access_key_id_setting_name = 'access-key-id';
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @var string
|
25 |
+
*/
|
26 |
+
protected static $secret_access_key_setting_name = 'secret-access-key';
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
protected static $use_server_roles_setting_name = 'use-server-roles';
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
protected static $key_file_setting_name = 'key-file';
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @var string
|
40 |
+
*/
|
41 |
+
protected static $key_file_path_setting_name = 'key-file-path';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* If left empty, access keys not allowed.
|
45 |
+
*
|
46 |
+
* @var array
|
47 |
+
*/
|
48 |
+
protected static $access_key_id_constants = array();
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @var array
|
52 |
+
*/
|
53 |
+
protected static $secret_access_key_constants = array();
|
54 |
+
|
55 |
+
/**
|
56 |
+
* If left empty, server roles not allowed.
|
57 |
+
*
|
58 |
+
* @var array
|
59 |
+
*/
|
60 |
+
protected static $use_server_roles_constants = array();
|
61 |
+
|
62 |
+
/**
|
63 |
+
* If left empty, key file not allowed.
|
64 |
+
*
|
65 |
+
* @var array
|
66 |
+
*/
|
67 |
+
protected static $key_file_path_constants = array();
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @var bool
|
71 |
+
*/
|
72 |
+
protected static $block_public_access_allowed = false;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @var array
|
76 |
+
*/
|
77 |
+
protected $regions = array();
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @var bool
|
81 |
+
*/
|
82 |
+
protected $region_required = false;
|
83 |
+
|
84 |
+
/**
|
85 |
+
* @var string
|
86 |
+
*/
|
87 |
+
protected $default_region = '';
|
88 |
+
|
89 |
+
/**
|
90 |
+
* @var string
|
91 |
+
*/
|
92 |
+
protected $default_domain = '';
|
93 |
+
|
94 |
+
/**
|
95 |
+
* @var string
|
96 |
+
*/
|
97 |
+
protected $console_url = '';
|
98 |
+
|
99 |
+
/**
|
100 |
+
* @var string
|
101 |
+
*/
|
102 |
+
protected $console_url_prefix_param = '';
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Is the provider able to use access keys?
|
106 |
+
*
|
107 |
+
* @return bool
|
108 |
+
*/
|
109 |
+
public static function use_access_keys_allowed() {
|
110 |
+
return ! empty( static::$access_key_id_constants );
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Whether or not access keys are needed.
|
115 |
+
*
|
116 |
+
* Keys are needed if we are not using server roles or not defined/set yet.
|
117 |
+
*
|
118 |
+
* @return bool
|
119 |
+
*/
|
120 |
+
public function needs_access_keys() {
|
121 |
+
if ( $this->use_server_roles() ) {
|
122 |
+
return false;
|
123 |
+
}
|
124 |
+
|
125 |
+
if ( static::use_key_file() ) {
|
126 |
+
return false;
|
127 |
+
}
|
128 |
+
|
129 |
+
return ! $this->are_access_keys_set();
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Check if both access key id & secret are present.
|
134 |
+
*
|
135 |
+
* @return bool
|
136 |
+
*/
|
137 |
+
public function are_access_keys_set() {
|
138 |
+
return $this->get_access_key_id() && $this->get_secret_access_key();
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Get the access key from a constant or the settings.
|
143 |
+
*
|
144 |
+
* Falls back to settings only if neither constant is defined.
|
145 |
+
*
|
146 |
+
* @return string
|
147 |
+
*/
|
148 |
+
public function get_access_key_id() {
|
149 |
+
if ( static::is_any_access_key_constant_defined() ) {
|
150 |
+
$constant = static::access_key_id_constant();
|
151 |
+
|
152 |
+
return $constant ? constant( $constant ) : '';
|
153 |
+
}
|
154 |
+
|
155 |
+
return $this->as3cf->get_core_setting( static::$access_key_id_setting_name );
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Get the secret access key from a constant or the settings.
|
160 |
+
*
|
161 |
+
* Falls back to settings only if neither constant is defined.
|
162 |
+
*
|
163 |
+
* @return string
|
164 |
+
*/
|
165 |
+
public function get_secret_access_key() {
|
166 |
+
if ( static::is_any_access_key_constant_defined() ) {
|
167 |
+
$constant = static::secret_access_key_constant();
|
168 |
+
|
169 |
+
return $constant ? constant( $constant ) : '';
|
170 |
+
}
|
171 |
+
|
172 |
+
return $this->as3cf->get_core_setting( static::$secret_access_key_setting_name );
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Check if any access key (id or secret, prefixed or not) is defined.
|
177 |
+
*
|
178 |
+
* @return bool
|
179 |
+
*/
|
180 |
+
public static function is_any_access_key_constant_defined() {
|
181 |
+
return static::access_key_id_constant() || static::secret_access_key_constant();
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Get the constant used to define the access key id.
|
186 |
+
*
|
187 |
+
* @return string|false Constant name if defined, otherwise false
|
188 |
+
*/
|
189 |
+
public static function access_key_id_constant() {
|
190 |
+
return AS3CF_Utils::get_first_defined_constant( static::$access_key_id_constants );
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Get the constant used to define the secret access key.
|
195 |
+
*
|
196 |
+
* @return string|false Constant name if defined, otherwise false
|
197 |
+
*/
|
198 |
+
public static function secret_access_key_constant() {
|
199 |
+
return AS3CF_Utils::get_first_defined_constant( static::$secret_access_key_constants );
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Is the provider able to use server roles?
|
204 |
+
*
|
205 |
+
* @return bool
|
206 |
+
*/
|
207 |
+
public static function use_server_roles_allowed() {
|
208 |
+
return ! empty( static::$use_server_roles_constants );
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* If server roles allowed, returns first (preferred) constant that should be defined, otherwise blank.
|
213 |
+
*
|
214 |
+
* @return string
|
215 |
+
*/
|
216 |
+
public static function preferred_use_server_roles_constant() {
|
217 |
+
if ( static::use_server_roles_allowed() ) {
|
218 |
+
return static::$use_server_roles_constants[0];
|
219 |
+
} else {
|
220 |
+
return '';
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* Allows the provider's client factory to use server roles instead of key/secret for credentials.
|
226 |
+
*
|
227 |
+
* @see http://docs.aws.amazon.com/aws-sdk-php/guide/latest/credentials.html#instance-profile-credentials
|
228 |
+
*
|
229 |
+
* @return bool
|
230 |
+
*/
|
231 |
+
public function use_server_roles() {
|
232 |
+
if ( ! static::use_server_roles_allowed() ) {
|
233 |
+
return false;
|
234 |
+
}
|
235 |
+
|
236 |
+
if ( static::use_server_roles_constant() ) {
|
237 |
+
$constant = static::use_server_roles_constant();
|
238 |
+
|
239 |
+
return $constant ? constant( $constant ) : false;
|
240 |
+
}
|
241 |
+
|
242 |
+
return $this->as3cf->get_core_setting( static::$use_server_roles_setting_name, false );
|
243 |
+
}
|
244 |
+
|
245 |
+
/**
|
246 |
+
* Get the constant used to enable the use of IAM roles.
|
247 |
+
*
|
248 |
+
* @return string|false Constant name if defined, otherwise false
|
249 |
+
*/
|
250 |
+
public static function use_server_roles_constant() {
|
251 |
+
return AS3CF_Utils::get_first_defined_constant( static::$use_server_roles_constants );
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Is the provider able to use a key file?
|
256 |
+
*
|
257 |
+
* @return bool
|
258 |
+
*/
|
259 |
+
public static function use_key_file_allowed() {
|
260 |
+
return ! empty( static::$key_file_path_constants );
|
261 |
+
}
|
262 |
+
|
263 |
+
/**
|
264 |
+
* If key file allowed, returns first (preferred) constant that should be defined, otherwise blank.
|
265 |
+
*
|
266 |
+
* @return string
|
267 |
+
*/
|
268 |
+
public static function preferred_key_file_path_constant() {
|
269 |
+
if ( static::use_key_file_allowed() ) {
|
270 |
+
return static::$key_file_path_constants[0];
|
271 |
+
} else {
|
272 |
+
return '';
|
273 |
+
}
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* Check if either key file path or key file set.
|
278 |
+
*
|
279 |
+
* @return bool
|
280 |
+
*/
|
281 |
+
public function use_key_file() {
|
282 |
+
if ( ! static::use_key_file_allowed() ) {
|
283 |
+
return false;
|
284 |
+
}
|
285 |
+
|
286 |
+
return $this->get_key_file_path() || $this->get_key_file();
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Get the key file contents from settings.
|
291 |
+
*
|
292 |
+
* @return array|bool
|
293 |
+
*/
|
294 |
+
public function get_key_file() {
|
295 |
+
$key_file = $this->as3cf->get_core_setting( static::$key_file_setting_name, false );
|
296 |
+
|
297 |
+
return $key_file;
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Get the key file path from a constant or the settings.
|
302 |
+
*
|
303 |
+
* Falls back to settings if constant is not defined.
|
304 |
+
*
|
305 |
+
* @return string|bool
|
306 |
+
*/
|
307 |
+
public function get_key_file_path() {
|
308 |
+
if ( static::is_key_file_path_constant_defined() ) {
|
309 |
+
$constant = static::key_file_path_constant();
|
310 |
+
|
311 |
+
if ( $constant ) {
|
312 |
+
return $this->validate_key_file_path( constant( $constant ) );
|
313 |
+
} else {
|
314 |
+
// Constant defined but value is not a non-empty string.
|
315 |
+
return false;
|
316 |
+
}
|
317 |
+
}
|
318 |
+
|
319 |
+
return $this->validate_key_file_path( $this->as3cf->get_core_setting( static::$key_file_path_setting_name, false ) );
|
320 |
+
}
|
321 |
+
|
322 |
+
/**
|
323 |
+
* Validate a key file path to ensure it exists, is readable, and contains JSON.
|
324 |
+
*
|
325 |
+
* @param string $key_file_path
|
326 |
+
*
|
327 |
+
* @return bool|string
|
328 |
+
*/
|
329 |
+
public function validate_key_file_path( $key_file_path ) {
|
330 |
+
$notice_id = 'validate-key-file-path';
|
331 |
+
$this->as3cf->notices->remove_notice_by_id( $notice_id );
|
332 |
+
|
333 |
+
if ( empty( $key_file_path ) ) {
|
334 |
+
return false;
|
335 |
+
}
|
336 |
+
|
337 |
+
if ( ! file_exists( $key_file_path ) ) {
|
338 |
+
$this->as3cf->notices->add_notice( __( 'Given Key File Path is invalid or could not be accessed.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
|
339 |
+
|
340 |
+
return false;
|
341 |
+
}
|
342 |
+
|
343 |
+
try {
|
344 |
+
$value = file_get_contents( $key_file_path );
|
345 |
+
|
346 |
+
// An exception isn't always thrown, so check value instead.
|
347 |
+
if ( empty( $value ) ) {
|
348 |
+
$this->as3cf->notices->add_notice( __( 'Could not read Key File Path\'s contents.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
|
349 |
+
|
350 |
+
return false;
|
351 |
+
}
|
352 |
+
} catch ( Exception $e ) {
|
353 |
+
$this->as3cf->notices->add_notice( __( 'Could not read Key File Path\'s contents.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
|
354 |
+
|
355 |
+
return false;
|
356 |
+
}
|
357 |
+
|
358 |
+
$value = json_decode( $value, true );
|
359 |
+
|
360 |
+
if ( empty( $value ) ) {
|
361 |
+
$this->as3cf->notices->add_notice( __( 'Given Key File Path does not contain valid JSON.', 'amazon-s3-and-cloudfront' ), array( 'type' => 'error', 'only_show_in_settings' => true, 'only_show_on_tab' => 'media', 'custom_id' => $notice_id ) );
|
362 |
+
|
363 |
+
return false;
|
364 |
+
}
|
365 |
+
|
366 |
+
// File exists and looks like JSON.
|
367 |
+
return $key_file_path;
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* Check if key file path constant is defined, for speed, does not check validity of file path.
|
372 |
+
*
|
373 |
+
* @return bool
|
374 |
+
*/
|
375 |
+
public static function is_key_file_path_constant_defined() {
|
376 |
+
$constant = static::key_file_path_constant();
|
377 |
+
|
378 |
+
return $constant && constant( $constant );
|
379 |
+
}
|
380 |
+
|
381 |
+
/**
|
382 |
+
* Get the constant used to define the key file path.
|
383 |
+
*
|
384 |
+
* @return string|false Constant name if defined, otherwise false
|
385 |
+
*/
|
386 |
+
public static function key_file_path_constant() {
|
387 |
+
return AS3CF_Utils::get_first_defined_constant( static::$key_file_path_constants );
|
388 |
+
}
|
389 |
+
|
390 |
+
/**
|
391 |
+
* Get default "canned" ACL string.
|
392 |
+
*
|
393 |
+
* @return string|null
|
394 |
+
*/
|
395 |
+
public function get_default_acl() {
|
396 |
+
return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_default_acl', $this->get_public_acl() );
|
397 |
+
}
|
398 |
+
|
399 |
+
/**
|
400 |
+
* Does provider have functionality to block direct public access to bucket?
|
401 |
+
*
|
402 |
+
* @return bool
|
403 |
+
*/
|
404 |
+
public static function block_public_access_allowed() {
|
405 |
+
return static::$block_public_access_allowed;
|
406 |
+
}
|
407 |
+
|
408 |
+
/**
|
409 |
+
* Is public access to the given bucket prohibited?
|
410 |
+
*
|
411 |
+
* @param string $bucket
|
412 |
+
*
|
413 |
+
* @return bool|null
|
414 |
+
*/
|
415 |
+
public function public_access_blocked( $bucket ) {
|
416 |
+
if ( static::block_public_access_allowed() ) {
|
417 |
+
return null; // Unknown until sub class overrides this function.
|
418 |
+
} else {
|
419 |
+
return false;
|
420 |
+
}
|
421 |
+
}
|
422 |
+
|
423 |
+
/**
|
424 |
+
* Update the block public access setting for the given bucket.
|
425 |
+
*
|
426 |
+
* @param string $bucket
|
427 |
+
* @param bool $block
|
428 |
+
*
|
429 |
+
* Note: Should be overridden and implemented as required.
|
430 |
+
*/
|
431 |
+
public function block_public_access( $bucket, $block ) {
|
432 |
+
return;
|
433 |
+
}
|
434 |
+
|
435 |
+
/**
|
436 |
+
* Returns the Provider's default region slug.
|
437 |
+
*
|
438 |
+
* @return string
|
439 |
+
*/
|
440 |
+
public function region_required() {
|
441 |
+
return $this->region_required;
|
442 |
+
}
|
443 |
+
|
444 |
+
/**
|
445 |
+
* Returns the Provider's default region slug.
|
446 |
+
*
|
447 |
+
* @return string
|
448 |
+
*/
|
449 |
+
public function get_default_region() {
|
450 |
+
return $this->default_region;
|
451 |
+
}
|
452 |
+
|
453 |
+
/**
|
454 |
+
* Returns an array of valid region slugs and names.
|
455 |
+
*
|
456 |
+
* @return array Keys are region slug, values their name
|
457 |
+
*/
|
458 |
+
public function get_regions() {
|
459 |
+
$regions = apply_filters( static::$provider_key_name . '_get_regions', $this->regions ); // Backwards compatibility, e.g. 'aws_get_regions'.
|
460 |
+
|
461 |
+
return apply_filters( 'as3cf_' . static::$provider_key_name . '_get_regions', $regions );
|
462 |
+
}
|
463 |
+
|
464 |
+
/**
|
465 |
+
* Returns readable region name.
|
466 |
+
*
|
467 |
+
* @param string $region
|
468 |
+
* @param bool $with_key
|
469 |
+
*
|
470 |
+
* @return string
|
471 |
+
*/
|
472 |
+
public function get_region_name( $region = '', $with_key = false ) {
|
473 |
+
if ( is_wp_error( $region ) ) {
|
474 |
+
return '';
|
475 |
+
}
|
476 |
+
if ( empty( $region ) && ! $this->region_required() ) {
|
477 |
+
$region = $this->get_default_region();
|
478 |
+
}
|
479 |
+
|
480 |
+
$regions = $this->get_regions();
|
481 |
+
|
482 |
+
$region_name = empty( $regions[ $region ] ) ? '' : $regions[ $region ];
|
483 |
+
|
484 |
+
if ( $with_key ) {
|
485 |
+
$region_name .= empty( $region_name ) ? $region : ' (' . $region . ')';
|
486 |
+
}
|
487 |
+
|
488 |
+
return $region_name;
|
489 |
+
}
|
490 |
+
|
491 |
+
/**
|
492 |
+
* Is given region key valid for provider?
|
493 |
+
*
|
494 |
+
* @param string $region
|
495 |
+
*
|
496 |
+
* @return bool
|
497 |
+
*/
|
498 |
+
public function is_region_valid( $region ) {
|
499 |
+
return in_array( trim( $region ), array_keys( $this->get_regions() ) );
|
500 |
+
}
|
501 |
+
|
502 |
+
/**
|
503 |
+
* Instantiate a new service client for the provider.
|
504 |
+
*
|
505 |
+
* @param array $args Options for required region/endpoint
|
506 |
+
*
|
507 |
+
* @throws Exception
|
508 |
+
*/
|
509 |
+
private function _init_client( array $args ) {
|
510 |
+
if ( $this->needs_access_keys() ) {
|
511 |
+
throw new Exception( sprintf( __( 'You must first <a href="%s">set your access keys</a>.', 'amazon-s3-and-cloudfront' ), $this->as3cf->get_plugin_page_url() . '#settings' ) );
|
512 |
+
}
|
513 |
+
|
514 |
+
if ( is_null( $this->client ) ) {
|
515 |
+
// There's no extra client authentication config required when using server roles.
|
516 |
+
if ( ! $this->use_server_roles() ) {
|
517 |
+
// Some providers can supply Key File contents or Key File Path.
|
518 |
+
if ( static::use_key_file() ) {
|
519 |
+
// Key File contents take precedence over Key File Path.
|
520 |
+
if ( static::get_key_file() ) {
|
521 |
+
$args = array_merge( array(
|
522 |
+
'keyFile' => static::get_key_file(),
|
523 |
+
), $args );
|
524 |
+
} else {
|
525 |
+
$args = array_merge( array(
|
526 |
+
'keyFilePath' => static::get_key_file_path(),
|
527 |
+
), $args );
|
528 |
+
}
|
529 |
+
} else {
|
530 |
+
// Fall back is Access Keys.
|
531 |
+
$args = array_merge( array(
|
532 |
+
'credentials' => array(
|
533 |
+
'key' => $this->get_access_key_id(),
|
534 |
+
'secret' => $this->get_secret_access_key(),
|
535 |
+
),
|
536 |
+
), $args );
|
537 |
+
}
|
538 |
+
}
|
539 |
+
|
540 |
+
// Add credentials and given args to default client args and then let user override.
|
541 |
+
$args = array_merge( $this->default_client_args(), $args );
|
542 |
+
$args = apply_filters( 'as3cf_' . static::$provider_key_name . '_init_client_args', $this->init_client_args( $args ) );
|
543 |
+
$args = apply_filters( static::$provider_key_name . '_get_client_args', $args ); // Backwards compatibility, e.g. 'aws_get_client_args'.
|
544 |
+
|
545 |
+
$this->client = $this->init_client( $args );
|
546 |
+
}
|
547 |
+
}
|
548 |
+
|
549 |
+
/**
|
550 |
+
* Get the service client instance.
|
551 |
+
*
|
552 |
+
* @param array $args Options for required region/endpoint
|
553 |
+
* @param bool $force
|
554 |
+
*
|
555 |
+
* @return Storage_Provider
|
556 |
+
* @throws Exception
|
557 |
+
*/
|
558 |
+
public function get_client( array $args, $force = false ) {
|
559 |
+
if ( true === $force ) {
|
560 |
+
$this->client = null;
|
561 |
+
}
|
562 |
+
|
563 |
+
$this->_init_client( $args );
|
564 |
+
|
565 |
+
$args = apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_client_args', $this->init_service_client_args( $args ) );
|
566 |
+
|
567 |
+
$this->client = $this->init_service_client( $args );
|
568 |
+
|
569 |
+
return $this;
|
570 |
+
}
|
571 |
+
|
572 |
+
/**
|
573 |
+
* Get object keys from multiple clients.
|
574 |
+
*
|
575 |
+
* @param array $regions
|
576 |
+
*
|
577 |
+
* @return array
|
578 |
+
*/
|
579 |
+
public static function get_keys_from_regions( array $regions ) {
|
580 |
+
$keys = array();
|
581 |
+
|
582 |
+
foreach ( $regions as $region ) {
|
583 |
+
try {
|
584 |
+
/* @var $client Storage_Provider */
|
585 |
+
$client = $region['provider_client'];
|
586 |
+
$region_keys = $client->list_keys( $region['locations'] );
|
587 |
+
} catch ( Exception $e ) {
|
588 |
+
AS3CF_Error::log( get_class( $e ) . ' exception caught when executing list_keys: ' . $e->getMessage() );
|
589 |
+
continue;
|
590 |
+
}
|
591 |
+
|
592 |
+
if ( ! empty( $region_keys ) ) {
|
593 |
+
foreach ( $region_keys as $attachment_id => $found_keys ) {
|
594 |
+
$keys[ $attachment_id ] = AS3CF_Utils::validate_attachment_keys( $attachment_id, $found_keys );
|
595 |
+
}
|
596 |
+
}
|
597 |
+
}
|
598 |
+
|
599 |
+
return $keys;
|
600 |
+
}
|
601 |
+
|
602 |
+
/**
|
603 |
+
* Generate a stream wrapper compatible URL
|
604 |
+
*
|
605 |
+
* @param string $region
|
606 |
+
* @param string $bucket
|
607 |
+
* @param string $key
|
608 |
+
*
|
609 |
+
* @return string
|
610 |
+
*/
|
611 |
+
public function prepare_stream_wrapper_file( $region, $bucket, $key ) {
|
612 |
+
$protocol = $this->get_stream_wrapper_protocol( $region );
|
613 |
+
|
614 |
+
return $protocol . '://' . $bucket . '/' . $key;
|
615 |
+
}
|
616 |
+
|
617 |
+
/**
|
618 |
+
* Get the region specific prefix for URL
|
619 |
+
*
|
620 |
+
* @param string $region
|
621 |
+
* @param null|int $expires
|
622 |
+
*
|
623 |
+
* @return string
|
624 |
+
*/
|
625 |
+
public function get_url_prefix( $region = '', $expires = null ) {
|
626 |
+
/**
|
627 |
+
* Region specific prefix for raw URL
|
628 |
+
*
|
629 |
+
* @param string $prefix
|
630 |
+
* @param string $region
|
631 |
+
* @param null|int $expires
|
632 |
+
*
|
633 |
+
* @return string
|
634 |
+
*/
|
635 |
+
return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_url_prefix', $this->url_prefix( $region, $expires ), $region, $expires );
|
636 |
+
}
|
637 |
+
|
638 |
+
/**
|
639 |
+
* Get the url domain for the files
|
640 |
+
*
|
641 |
+
* @param string $bucket
|
642 |
+
* @param string $region
|
643 |
+
* @param int $expires
|
644 |
+
*
|
645 |
+
* @return string
|
646 |
+
*/
|
647 |
+
public function get_url_domain( $bucket, $region = '', $expires = null ) {
|
648 |
+
$args = array(
|
649 |
+
'delivery-provider' => $this->as3cf->get_setting( 'delivery-provider' ),
|
650 |
+
'enable-delivery-domain' => $this->as3cf->get_setting( 'enable-delivery-domain' ),
|
651 |
+
'delivery-domain' => $this->as3cf->get_setting( 'delivery-domain' ),
|
652 |
+
'force-https' => $this->as3cf->use_ssl( $this->as3cf->get_setting( 'force-https' ) ),
|
653 |
+
);
|
654 |
+
|
655 |
+
// Backwards Compat.
|
656 |
+
$args['domain'] = $args['enable-delivery-domain'] && Amazon_S3_And_CloudFront::get_default_delivery_provider() !== $args['delivery-provider'] ? 'cloudfront' : 'path';
|
657 |
+
$args['cloudfront'] = $args['delivery-domain'];
|
658 |
+
|
659 |
+
$prefix = $this->url_prefix( $region, $expires );
|
660 |
+
$domain = $this->get_domain();
|
661 |
+
$domain = empty( $prefix ) ? $domain : $prefix . '.' . $domain;
|
662 |
+
|
663 |
+
return apply_filters(
|
664 |
+
'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_url_domain',
|
665 |
+
$this->url_domain( $domain, $bucket, $region, $expires, $args ),
|
666 |
+
$bucket,
|
667 |
+
$region,
|
668 |
+
$expires,
|
669 |
+
$args
|
670 |
+
);
|
671 |
+
}
|
672 |
+
|
673 |
+
/**
|
674 |
+
* Get the link to the bucket on the provider's console.
|
675 |
+
*
|
676 |
+
* @param string $bucket
|
677 |
+
* @param string $prefix
|
678 |
+
* @param string $region
|
679 |
+
*
|
680 |
+
* @return string
|
681 |
+
*/
|
682 |
+
public function get_console_url( $bucket = '', $prefix = '', $region = '' ) {
|
683 |
+
if ( '' !== $prefix ) {
|
684 |
+
$prefix = $this->get_console_url_prefix_param() . apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_prefix_value', $prefix );
|
685 |
+
}
|
686 |
+
|
687 |
+
$suffix = apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_suffix_param', $this->get_console_url_suffix_param( $bucket, $prefix, $region ) );
|
688 |
+
|
689 |
+
return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url', $this->console_url ) . $bucket . $prefix . $suffix;
|
690 |
+
}
|
691 |
+
|
692 |
+
/**
|
693 |
+
* Get the prefix param to append to the link to the bucket on the provider's console.
|
694 |
+
*
|
695 |
+
* @return string
|
696 |
+
*/
|
697 |
+
public function get_console_url_prefix_param() {
|
698 |
+
return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_prefix_param', $this->console_url_prefix_param );
|
699 |
+
}
|
700 |
+
|
701 |
+
/**
|
702 |
+
* Returns default args array for the client.
|
703 |
+
*
|
704 |
+
* @return array
|
705 |
+
*/
|
706 |
+
abstract protected function default_client_args();
|
707 |
+
|
708 |
+
/**
|
709 |
+
* Process the args before instantiating a new client for the provider's SDK.
|
710 |
+
*
|
711 |
+
* @param array $args
|
712 |
+
*
|
713 |
+
* @return array
|
714 |
+
*/
|
715 |
+
abstract protected function init_client_args( array $args );
|
716 |
+
|
717 |
+
/**
|
718 |
+
* Instantiate a new client for the provider's SDK.
|
719 |
+
*
|
720 |
+
* @param array $args
|
721 |
+
*/
|
722 |
+
abstract protected function init_client( array $args );
|
723 |
+
|
724 |
+
/**
|
725 |
+
* Process the args before instantiating a new service specific client.
|
726 |
+
*
|
727 |
+
* @param array $args
|
728 |
+
*
|
729 |
+
* @return array
|
730 |
+
*/
|
731 |
+
abstract protected function init_service_client_args( array $args );
|
732 |
+
|
733 |
+
/**
|
734 |
+
* Instantiate a new service specific client.
|
735 |
+
* Depending on SDK, may simply return client instantiated with `init_client`.
|
736 |
+
*
|
737 |
+
* @param array $args
|
738 |
+
*
|
739 |
+
* @return mixed
|
740 |
+
*/
|
741 |
+
abstract protected function init_service_client( array $args );
|
742 |
+
|
743 |
+
/**
|
744 |
+
* Make sure region "slug" fits expected format.
|
745 |
+
*
|
746 |
+
* @param string $region
|
747 |
+
*
|
748 |
+
* @return string
|
749 |
+
*/
|
750 |
+
abstract public function sanitize_region( $region );
|
751 |
+
|
752 |
+
/**
|
753 |
+
* Create bucket.
|
754 |
+
*
|
755 |
+
* @param array $args
|
756 |
+
*/
|
757 |
+
abstract public function create_bucket( array $args );
|
758 |
+
|
759 |
+
/**
|
760 |
+
* Check whether bucket exists.
|
761 |
+
*
|
762 |
+
* @param string $bucket
|
763 |
+
*
|
764 |
+
* @return bool
|
765 |
+
*/
|
766 |
+
abstract public function does_bucket_exist( $bucket );
|
767 |
+
|
768 |
+
/**
|
769 |
+
* Returns region for bucket.
|
770 |
+
*
|
771 |
+
* @param array $args
|
772 |
+
*
|
773 |
+
* @return string
|
774 |
+
*/
|
775 |
+
abstract public function get_bucket_location( array $args );
|
776 |
+
|
777 |
+
/**
|
778 |
+
* List buckets.
|
779 |
+
*
|
780 |
+
* @param array $args
|
781 |
+
*
|
782 |
+
* @return array
|
783 |
+
*/
|
784 |
+
abstract public function list_buckets( array $args = array() );
|
785 |
+
|
786 |
+
/**
|
787 |
+
* Check whether key exists in bucket.
|
788 |
+
*
|
789 |
+
* @param string $bucket
|
790 |
+
* @param string $key
|
791 |
+
* @param array $options
|
792 |
+
*
|
793 |
+
* @return bool
|
794 |
+
*/
|
795 |
+
abstract public function does_object_exist( $bucket, $key, array $options = array() );
|
796 |
+
|
797 |
+
/**
|
798 |
+
* Get public "canned" ACL string.
|
799 |
+
*
|
800 |
+
* @return string
|
801 |
+
*/
|
802 |
+
abstract public function get_public_acl();
|
803 |
+
|
804 |
+
/**
|
805 |
+
* Get private "canned" ACL string.
|
806 |
+
*
|
807 |
+
* @return string
|
808 |
+
*/
|
809 |
+
abstract public function get_private_acl();
|
810 |
+
|
811 |
+
/**
|
812 |
+
* Download object, destination specified in args.
|
813 |
+
*
|
814 |
+
* @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#getobject
|
815 |
+
*
|
816 |
+
* @param array $args
|
817 |
+
*/
|
818 |
+
abstract public function get_object( array $args );
|
819 |
+
|
820 |
+
/**
|
821 |
+
* Get object's URL.
|
822 |
+
*
|
823 |
+
* @param string $bucket
|
824 |
+
* @param string $key
|
825 |
+
* @param int $timestamp
|
826 |
+
* @param array $args
|
827 |
+
*
|
828 |
+
* @return string
|
829 |
+
*/
|
830 |
+
abstract public function get_object_url( $bucket, $key, $timestamp, array $args = array() );
|
831 |
+
|
832 |
+
/**
|
833 |
+
* List objects.
|
834 |
+
*
|
835 |
+
* @param array $args
|
836 |
+
*
|
837 |
+
* @return array
|
838 |
+
*/
|
839 |
+
abstract public function list_objects( array $args = array() );
|
840 |
+
|
841 |
+
/**
|
842 |
+
* Update the ACL for an object.
|
843 |
+
*
|
844 |
+
* @param array $args
|
845 |
+
*/
|
846 |
+
abstract public function update_object_acl( array $args );
|
847 |
+
|
848 |
+
/**
|
849 |
+
* Update the ACL for multiple objects.
|
850 |
+
*
|
851 |
+
* @param array $items
|
852 |
+
*
|
853 |
+
* @return array Failures with elements Key and Message
|
854 |
+
*/
|
855 |
+
abstract public function update_object_acls( array $items );
|
856 |
+
|
857 |
+
/**
|
858 |
+
* Upload file to bucket.
|
859 |
+
*
|
860 |
+
* @param array $args
|
861 |
+
*/
|
862 |
+
abstract public function upload_object( array $args );
|
863 |
+
|
864 |
+
/**
|
865 |
+
* Delete object from bucket.
|
866 |
+
*
|
867 |
+
* @param array $args
|
868 |
+
*/
|
869 |
+
abstract public function delete_object( array $args );
|
870 |
+
|
871 |
+
/**
|
872 |
+
* Delete multiple objects from bucket.
|
873 |
+
*
|
874 |
+
* @param array $args
|
875 |
+
*/
|
876 |
+
abstract public function delete_objects( array $args );
|
877 |
+
|
878 |
+
/**
|
879 |
+
* Returns arrays of found keys for given bucket and prefix locations, retaining given array's integer based index.
|
880 |
+
*
|
881 |
+
* @param array $locations Array with attachment ID as key and Bucket and Prefix in an associative array as values.
|
882 |
+
*
|
883 |
+
* @return array
|
884 |
+
*/
|
885 |
+
abstract public function list_keys( array $locations );
|
886 |
+
|
887 |
+
/**
|
888 |
+
* Copies objects into current bucket from another bucket hosted with provider.
|
889 |
+
*
|
890 |
+
* @param array $items
|
891 |
+
*
|
892 |
+
* @return array Failures with elements Key and Message
|
893 |
+
*/
|
894 |
+
abstract public function copy_objects( array $items );
|
895 |
+
|
896 |
+
/**
|
897 |
+
* Generate the stream wrapper protocol
|
898 |
+
*
|
899 |
+
* @param string $region
|
900 |
+
*
|
901 |
+
* @return string
|
902 |
+
*/
|
903 |
+
abstract protected function get_stream_wrapper_protocol( $region );
|
904 |
+
|
905 |
+
/**
|
906 |
+
* Register a stream wrapper for specific region.
|
907 |
+
*
|
908 |
+
* @param string $region
|
909 |
+
*
|
910 |
+
* @return bool
|
911 |
+
*/
|
912 |
+
abstract public function register_stream_wrapper( $region );
|
913 |
+
|
914 |
+
/**
|
915 |
+
* Check that a bucket and key can be written to.
|
916 |
+
*
|
917 |
+
* @param string $bucket
|
918 |
+
* @param string $key
|
919 |
+
* @param string $file_contents
|
920 |
+
*
|
921 |
+
* @return bool|string Error message on unexpected exception
|
922 |
+
*/
|
923 |
+
abstract public function can_write( $bucket, $key, $file_contents );
|
924 |
+
|
925 |
+
/**
|
926 |
+
* Get the region specific prefix for raw URL
|
927 |
+
*
|
928 |
+
* @param string $region
|
929 |
+
* @param null|int $expires
|
930 |
+
*
|
931 |
+
* @return string
|
932 |
+
*/
|
933 |
+
abstract protected function url_prefix( $region = '', $expires = null );
|
934 |
+
|
935 |
+
/**
|
936 |
+
* Get the url domain for the files
|
937 |
+
*
|
938 |
+
* @param string $domain Likely prefixed with region
|
939 |
+
* @param string $bucket
|
940 |
+
* @param string $region
|
941 |
+
* @param int $expires
|
942 |
+
* @param array $args Allows you to specify custom URL settings
|
943 |
+
*
|
944 |
+
* @return string
|
945 |
+
*/
|
946 |
+
abstract protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array() );
|
947 |
+
|
948 |
+
/**
|
949 |
+
* Get the suffix param to append to the link to the bucket on the provider's console.
|
950 |
+
*
|
951 |
+
* @param string $bucket
|
952 |
+
* @param string $prefix
|
953 |
+
* @param string $region
|
954 |
+
*
|
955 |
+
* @return string
|
956 |
+
*/
|
957 |
+
abstract protected function get_console_url_suffix_param( $bucket = '', $prefix = '', $region = '' );
|
958 |
+
}
|
@@ -1,11 +1,10 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace DeliciousBrains\WP_Offload_Media\Providers\Streams;
|
4 |
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3ClientInterface;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\StreamWrapper;
|
8 |
-
use DeliciousBrains\WP_Offload_Media\Providers\AWS_Provider;
|
9 |
|
10 |
class AWS_S3_Stream_Wrapper extends StreamWrapper {
|
11 |
|
@@ -76,22 +75,41 @@ class AWS_S3_Stream_Wrapper extends StreamWrapper {
|
|
76 |
* @return bool
|
77 |
*/
|
78 |
public function stream_flush() {
|
79 |
-
$
|
|
|
80 |
|
81 |
-
if (
|
82 |
-
$context =
|
83 |
-
|
|
|
|
|
|
|
84 |
|
85 |
-
|
86 |
|
87 |
-
|
88 |
-
|
|
|
89 |
|
90 |
-
|
91 |
-
|
92 |
|
93 |
-
|
|
|
94 |
|
95 |
return parent::stream_flush();
|
96 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
}
|
1 |
<?php
|
2 |
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Storage\Streams;
|
4 |
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3ClientInterface;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\StreamWrapper;
|
|
|
8 |
|
9 |
class AWS_S3_Stream_Wrapper extends StreamWrapper {
|
10 |
|
75 |
* @return bool
|
76 |
*/
|
77 |
public function stream_flush() {
|
78 |
+
/** @var \Amazon_S3_And_CloudFront|\Amazon_S3_And_CloudFront_Pro $as3cf */
|
79 |
+
global $as3cf;
|
80 |
|
81 |
+
if ( $as3cf->get_setting( 'use-bucket-acls' ) ) {
|
82 |
+
$context = stream_context_get_default();
|
83 |
+
|
84 |
+
if ( null !== $this->context ) {
|
85 |
+
$context = $this->context;
|
86 |
+
}
|
87 |
|
88 |
+
$options = stream_context_get_options( $context );
|
89 |
|
90 |
+
// Set the ACL, usually defaults to public.
|
91 |
+
$provider = $as3cf->get_storage_provider();
|
92 |
+
$options[ static::$wrapper ]['ACL'] = $provider->get_default_acl();
|
93 |
|
94 |
+
$options = apply_filters( 'wpos3_stream_flush_params', $options ); // Backwards compatibility
|
95 |
+
$options = apply_filters( 'as3cf_stream_flush_params', $options );
|
96 |
|
97 |
+
stream_context_set_option( $context, $options );
|
98 |
+
}
|
99 |
|
100 |
return parent::stream_flush();
|
101 |
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Dummy function to stop PHP from throwing a wobbly.
|
105 |
+
*
|
106 |
+
* @param string $path
|
107 |
+
* @param int $option
|
108 |
+
* @param mixed $value
|
109 |
+
*
|
110 |
+
* @return bool
|
111 |
+
*/
|
112 |
+
public function stream_metadata( $path, $option, $value ) {
|
113 |
+
return true;
|
114 |
+
}
|
115 |
}
|
@@ -1,10 +1,9 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace DeliciousBrains\WP_Offload_Media\Providers\Streams;
|
4 |
|
5 |
use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StorageClient;
|
6 |
use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StreamWrapper;
|
7 |
-
use DeliciousBrains\WP_Offload_Media\Providers\GCP_Provider;
|
8 |
|
9 |
class GCP_GCS_Stream_Wrapper extends StreamWrapper {
|
10 |
|
1 |
<?php
|
2 |
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Providers\Storage\Streams;
|
4 |
|
5 |
use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StorageClient;
|
6 |
use DeliciousBrains\WP_Offload_Media\Gcp\Google\Cloud\Storage\StreamWrapper;
|
|
|
7 |
|
8 |
class GCP_GCS_Stream_Wrapper extends StreamWrapper {
|
9 |
|
@@ -112,12 +112,12 @@ abstract class Upgrade_Filter_Post extends Upgrade {
|
|
112 |
/**
|
113 |
* Upgrade attachment.
|
114 |
*
|
115 |
-
* @throws Batch_Limits_Exceeded_Exception
|
116 |
-
* @throws Too_Many_Errors_Exception
|
117 |
-
*
|
118 |
* @param mixed $attachment
|
119 |
*
|
120 |
* @return bool
|
|
|
|
|
|
|
121 |
*/
|
122 |
protected function upgrade_item( $attachment ) {
|
123 |
$limit = apply_filters( 'as3cf_update_' . $this->upgrade_name . '_sql_limit', 100000 );
|
@@ -275,7 +275,7 @@ abstract class Upgrade_Filter_Post extends Upgrade {
|
|
275 |
protected function maybe_add_encoded_url_pairs( $url_pairs ) {
|
276 |
foreach ( $url_pairs as $url_pair ) {
|
277 |
$file_name = wp_basename( $url_pair['old_url'] );
|
278 |
-
$encoded_file_name =
|
279 |
|
280 |
if ( $file_name !== $encoded_file_name ) {
|
281 |
$url_pair['old_url'] = str_replace( $file_name, $encoded_file_name, $url_pair['old_url'] );
|
112 |
/**
|
113 |
* Upgrade attachment.
|
114 |
*
|
|
|
|
|
|
|
115 |
* @param mixed $attachment
|
116 |
*
|
117 |
* @return bool
|
118 |
+
* @throws Batch_Limits_Exceeded_Exception
|
119 |
+
* @throws Too_Many_Errors_Exception
|
120 |
+
*
|
121 |
*/
|
122 |
protected function upgrade_item( $attachment ) {
|
123 |
$limit = apply_filters( 'as3cf_update_' . $this->upgrade_name . '_sql_limit', 100000 );
|
275 |
protected function maybe_add_encoded_url_pairs( $url_pairs ) {
|
276 |
foreach ( $url_pairs as $url_pair ) {
|
277 |
$file_name = wp_basename( $url_pair['old_url'] );
|
278 |
+
$encoded_file_name = AS3CF_Utils::encode_filename_in_path( $file_name );
|
279 |
|
280 |
if ( $file_name !== $encoded_file_name ) {
|
281 |
$url_pair['old_url'] = str_replace( $file_name, $encoded_file_name, $url_pair['old_url'] );
|
@@ -162,8 +162,8 @@ class Upgrade_Items_Table extends Upgrade {
|
|
162 |
return $wpdb->get_var( $sql );
|
163 |
}
|
164 |
|
165 |
-
$sql = 'SELECT
|
166 |
-
$sql .= ' ORDER BY
|
167 |
|
168 |
if ( $limit && $limit > 0 ) {
|
169 |
$sql .= sprintf( ' LIMIT %d', (int) $limit );
|
162 |
return $wpdb->get_var( $sql );
|
163 |
}
|
164 |
|
165 |
+
$sql = 'SELECT a.post_id AS ID, p.meta_id AS po_id, a.meta_value AS source_path, p.meta_value AS provider_object' . $sql;
|
166 |
+
$sql .= ' ORDER BY ID, po_id';
|
167 |
|
168 |
if ( $limit && $limit > 0 ) {
|
169 |
$sql .= sprintf( ' LIMIT %d', (int) $limit );
|
@@ -168,6 +168,9 @@ abstract class Upgrade {
|
|
168 |
add_action( 'as3cf_pre_settings_render', array( $this, 'maybe_display_notices' ) );
|
169 |
add_action( 'admin_init', array( $this, 'maybe_handle_action' ) );
|
170 |
|
|
|
|
|
|
|
171 |
// Do default checks if the upgrade can be started
|
172 |
if ( $this->maybe_init() ) {
|
173 |
$this->init();
|
@@ -937,4 +940,26 @@ abstract class Upgrade {
|
|
937 |
|
938 |
return is_admin();
|
939 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
940 |
}
|
168 |
add_action( 'as3cf_pre_settings_render', array( $this, 'maybe_display_notices' ) );
|
169 |
add_action( 'admin_init', array( $this, 'maybe_handle_action' ) );
|
170 |
|
171 |
+
// Settings Tab
|
172 |
+
add_action( 'as3cf_pre_tab_render', array( $this, 'pre_tab_render' ) );
|
173 |
+
|
174 |
// Do default checks if the upgrade can be started
|
175 |
if ( $this->maybe_init() ) {
|
176 |
$this->init();
|
940 |
|
941 |
return is_admin();
|
942 |
}
|
943 |
+
|
944 |
+
/**
|
945 |
+
* Maybe add notices etc. at top of settings tab.
|
946 |
+
*
|
947 |
+
* @param string $tab
|
948 |
+
*
|
949 |
+
* @handles as3cf_pre_tab_render filter
|
950 |
+
*/
|
951 |
+
public function pre_tab_render( $tab ) {
|
952 |
+
if ( 'media' === $tab ) {
|
953 |
+
$title = ucwords( $this->upgrade_type ) . ' Update';
|
954 |
+
|
955 |
+
$lock_settings_args = array(
|
956 |
+
'message' => sprintf( __( '<strong>Settings Locked Temporarily</strong> — You can\'t change any of your settings until the "%s" has completed.', 'amazon-s3-and-cloudfront' ), $title ),
|
957 |
+
'id' => 'as3cf-media-settings-locked-upgrade',
|
958 |
+
'inline' => true,
|
959 |
+
'type' => 'notice-warning',
|
960 |
+
'style' => 'display: none',
|
961 |
+
);
|
962 |
+
$this->as3cf->render_view( 'notice', $lock_settings_args );
|
963 |
+
}
|
964 |
+
}
|
965 |
}
|
@@ -1,16 +1,40 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
if ( ! function_exists( 'as3cf_get_secure_attachment_url' ) ) {
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
global $as3cf;
|
13 |
|
14 |
-
return $as3cf->get_secure_attachment_url( $post_id, $expires, $size );
|
15 |
}
|
16 |
}
|
1 |
<?php
|
2 |
+
if ( ! function_exists( 'as3cf_get_attachment_url' ) ) {
|
3 |
+
/**
|
4 |
+
* Get the url of the file from provider, may be a signed expiring URL if associated file is set as private.
|
5 |
+
*
|
6 |
+
* NOTE: Returns false if attachment is not offloaded.
|
7 |
+
*
|
8 |
+
* @param int $post_id Post ID of the attachment, required.
|
9 |
+
* @param string|null $size Size of the image to get, optional.
|
10 |
+
* @param bool $skip_rewrite_check Always return the URL regardless of the 'Rewrite File URLs' setting, optional, default: false.
|
11 |
+
*
|
12 |
+
* @return string|bool|WP_Error
|
13 |
+
*/
|
14 |
+
function as3cf_get_attachment_url( $post_id, $size = null, $skip_rewrite_check = false ) {
|
15 |
+
/** @var Amazon_S3_And_CloudFront $as3cf */
|
16 |
+
global $as3cf;
|
17 |
+
|
18 |
+
return $as3cf->get_attachment_url( $post_id, null, $size, null, array(), $skip_rewrite_check );
|
19 |
+
}
|
20 |
+
}
|
21 |
if ( ! function_exists( 'as3cf_get_secure_attachment_url' ) ) {
|
22 |
+
/**
|
23 |
+
* Get the signed expiring url of the file from provider.
|
24 |
+
*
|
25 |
+
* NOTE: Returns false if attachment is not offloaded.
|
26 |
+
*
|
27 |
+
* @param int $post_id Post ID of the attachment, required.
|
28 |
+
* @param int|null $expires Seconds for the link to live, optional, default: 900 (15 minutes).
|
29 |
+
* @param string|null $size Size of the image to get, optional.
|
30 |
+
* @param bool $skip_rewrite_check Always return the URL regardless of the 'Rewrite File URLs' setting, optional, default: false.
|
31 |
+
*
|
32 |
+
* @return string|bool|WP_Error
|
33 |
+
*/
|
34 |
+
function as3cf_get_secure_attachment_url( $post_id, $expires = 900, $size = null, $skip_rewrite_check = false ) {
|
35 |
+
/** @var Amazon_S3_And_CloudFront $as3cf */
|
36 |
global $as3cf;
|
37 |
|
38 |
+
return $as3cf->get_secure_attachment_url( $post_id, $expires, $size, array(), $skip_rewrite_check );
|
39 |
}
|
40 |
}
|
@@ -8,7 +8,7 @@ msgid ""
|
|
8 |
msgstr ""
|
9 |
"Project-Id-Version: amazon-s3-and-cloudfront\n"
|
10 |
"Report-Msgid-Bugs-To: nom@deliciousbrains.com\n"
|
11 |
-
"POT-Creation-Date:
|
12 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
@@ -17,182 +17,232 @@ msgstr ""
|
|
17 |
"Content-Type: text/plain; charset=UTF-8\n"
|
18 |
"Content-Transfer-Encoding: 8bit\n"
|
19 |
|
20 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
21 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
22 |
msgid "Offload Media Lite"
|
23 |
msgstr ""
|
24 |
|
25 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
26 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
27 |
msgid "Unknown"
|
28 |
msgstr ""
|
29 |
|
30 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
31 |
-
#: view/bucket-
|
|
|
|
|
32 |
#: view/provider-select.php:122
|
|
|
|
|
|
|
33 |
msgid "defined in wp-config.php"
|
34 |
msgstr ""
|
35 |
|
36 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
37 |
#, php-format
|
38 |
msgid "Media Library item with ID %d does not have a valid file path"
|
39 |
msgstr ""
|
40 |
|
41 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
42 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
43 |
#, php-format
|
44 |
msgid "File %s does not exist"
|
45 |
msgstr ""
|
46 |
|
47 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
48 |
#, php-format
|
49 |
msgid "Mime type %s is not allowed"
|
50 |
msgstr ""
|
51 |
|
52 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
53 |
msgid "Already offloaded to a different provider"
|
54 |
msgstr ""
|
55 |
|
56 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
57 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
58 |
#, php-format
|
59 |
msgid "Error offloading %s to provider: %s"
|
60 |
msgstr ""
|
61 |
|
62 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
63 |
msgid "This action can only be performed through an admin screen."
|
64 |
msgstr ""
|
65 |
|
66 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
67 |
msgid "Cheatin’ eh?"
|
68 |
msgstr ""
|
69 |
|
70 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
71 |
msgid "You do not have sufficient permissions to access this page."
|
72 |
msgstr ""
|
73 |
|
74 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
75 |
msgid "Error Getting Bucket Region"
|
76 |
msgstr ""
|
77 |
|
78 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
79 |
#, php-format
|
80 |
msgid "There was an error attempting to get the region of the bucket %s: %s"
|
81 |
msgstr ""
|
82 |
|
83 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
84 |
msgid ""
|
85 |
"This is a test file to check if the user has write permission to the bucket. "
|
86 |
"Delete me if found."
|
87 |
msgstr ""
|
88 |
|
89 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
90 |
#, php-format
|
91 |
msgid ""
|
92 |
"There was an error attempting to check the permissions of the bucket %s: %s"
|
93 |
msgstr ""
|
94 |
|
95 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
96 |
msgid "Error creating bucket"
|
97 |
msgstr ""
|
98 |
|
99 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
100 |
msgid "Bucket name too short."
|
101 |
msgstr ""
|
102 |
|
103 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
104 |
msgid "Bucket name too long."
|
105 |
msgstr ""
|
106 |
|
107 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
108 |
msgid ""
|
109 |
"Invalid character. Bucket names can contain lowercase letters, numbers, "
|
110 |
"periods and hyphens."
|
111 |
msgstr ""
|
112 |
|
113 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
114 |
msgid "Error saving bucket"
|
115 |
msgstr ""
|
116 |
|
117 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
118 |
msgid "Error fetching buckets"
|
119 |
msgstr ""
|
120 |
|
121 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
122 |
msgid "Error getting URL preview: "
|
123 |
msgstr ""
|
124 |
|
125 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
126 |
msgid "The changes you made will be lost if you navigate away from this page"
|
127 |
msgstr ""
|
128 |
|
129 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
130 |
msgid "Getting diagnostic info..."
|
131 |
msgstr ""
|
132 |
|
133 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
134 |
msgid "Error getting diagnostic info: "
|
135 |
msgstr ""
|
136 |
|
137 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
138 |
msgctxt "placeholder for hidden access key, 39 char max"
|
139 |
msgid "-- not shown --"
|
140 |
msgstr ""
|
141 |
|
142 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
143 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
144 |
msgid "Settings saved."
|
145 |
msgstr ""
|
146 |
|
147 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
148 |
msgid "Cheatin' eh?"
|
149 |
msgstr ""
|
150 |
|
151 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
msgid "No bucket name provided."
|
153 |
msgstr ""
|
154 |
|
155 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
156 |
msgid "Bucket name not valid."
|
157 |
msgstr ""
|
158 |
|
159 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
160 |
msgid "No region provided."
|
161 |
msgstr ""
|
162 |
|
163 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
#: view/provider-select.php:329
|
165 |
msgctxt "placeholder for hidden secret access key, 39 char max"
|
166 |
msgid "-- not shown --"
|
167 |
msgstr ""
|
168 |
|
169 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
170 |
msgid "Key File not valid JSON."
|
171 |
msgstr ""
|
172 |
|
173 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
msgctxt "Show the media library tab"
|
175 |
msgid "Media Library"
|
176 |
msgstr ""
|
177 |
|
178 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
179 |
msgctxt "Show the addons tab"
|
180 |
msgid "Addons"
|
181 |
msgstr ""
|
182 |
|
183 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
184 |
msgctxt "Show the support tab"
|
185 |
msgid "Support"
|
186 |
msgstr ""
|
187 |
|
188 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
189 |
#, php-format
|
190 |
msgid ""
|
191 |
"<strong>WP Offload Media</strong> — The file %s has been given %s "
|
192 |
"permissions in the bucket."
|
193 |
msgstr ""
|
194 |
|
195 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
196 |
msgid ""
|
197 |
"<strong>WP Offload Media Requirement Missing</strong> — Looks like you "
|
198 |
"don't have an image manipulation library installed on this server and "
|
@@ -200,18 +250,18 @@ msgid ""
|
|
200 |
"Please setup GD or ImageMagick."
|
201 |
msgstr ""
|
202 |
|
203 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
204 |
#, php-format
|
205 |
msgid ""
|
206 |
"<a href=\"%s\">Define your access keys</a> to enable write access to the "
|
207 |
"bucket"
|
208 |
msgstr ""
|
209 |
|
210 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
211 |
msgid "Quick Start Guide"
|
212 |
msgstr ""
|
213 |
|
214 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
215 |
#, php-format
|
216 |
msgid ""
|
217 |
"Looks like we don't have write access to this bucket. It's likely that the "
|
@@ -220,7 +270,7 @@ msgid ""
|
|
220 |
"correctly."
|
221 |
msgstr ""
|
222 |
|
223 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
224 |
#, php-format
|
225 |
msgid ""
|
226 |
"Looks like we don't have access to the buckets. It's likely that the user "
|
@@ -228,39 +278,39 @@ msgid ""
|
|
228 |
"Please see our %s for instructions on setting up permissions correctly."
|
229 |
msgstr ""
|
230 |
|
231 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
232 |
msgid "WP Offload Media Activation"
|
233 |
msgstr ""
|
234 |
|
235 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
236 |
msgid ""
|
237 |
"WP Offload Media Lite and WP Offload Media cannot both be active. We've "
|
238 |
"automatically deactivated WP Offload Media Lite."
|
239 |
msgstr ""
|
240 |
|
241 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
242 |
msgid "WP Offload Media Lite Activation"
|
243 |
msgstr ""
|
244 |
|
245 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
246 |
msgid ""
|
247 |
"WP Offload Media Lite and WP Offload Media cannot both be active. We've "
|
248 |
"automatically deactivated WP Offload Media."
|
249 |
msgstr ""
|
250 |
|
251 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
252 |
msgid "More info »"
|
253 |
msgstr ""
|
254 |
|
255 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
256 |
msgid "this doc"
|
257 |
msgstr ""
|
258 |
|
259 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
260 |
msgid "WP Offload Media Feature Removed"
|
261 |
msgstr ""
|
262 |
|
263 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
264 |
#, php-format
|
265 |
msgid ""
|
266 |
"You had the \"Always non-SSL\" option selected in your settings, but we've "
|
@@ -271,59 +321,59 @@ msgid ""
|
|
271 |
"to the old behavior."
|
272 |
msgstr ""
|
273 |
|
274 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
275 |
msgid "Offload"
|
276 |
msgstr ""
|
277 |
|
278 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
279 |
msgctxt "Storage provider key name"
|
280 |
msgid "Storage Provider"
|
281 |
msgstr ""
|
282 |
|
283 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
284 |
msgctxt "Storage provider name"
|
285 |
msgid "Storage Provider"
|
286 |
msgstr ""
|
287 |
|
288 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
289 |
msgctxt "Bucket name"
|
290 |
msgid "Bucket"
|
291 |
msgstr ""
|
292 |
|
293 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
294 |
msgctxt "Path to file in bucket"
|
295 |
msgid "Path"
|
296 |
msgstr ""
|
297 |
|
298 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
299 |
msgctxt "Location of bucket"
|
300 |
msgid "Region"
|
301 |
msgstr ""
|
302 |
|
303 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
304 |
msgctxt "Access control list of the file in bucket"
|
305 |
msgid "Access"
|
306 |
msgstr ""
|
307 |
|
308 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
309 |
msgid "URL"
|
310 |
msgstr ""
|
311 |
|
312 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
313 |
msgid "Assets Pull"
|
314 |
msgstr ""
|
315 |
|
316 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
317 |
msgid ""
|
318 |
"An addon for WP Offload Media to serve your site's JS, CSS, and other "
|
319 |
"enqueued assets from Amazon CloudFront or another CDN."
|
320 |
msgstr ""
|
321 |
|
322 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
323 |
msgid "Feature"
|
324 |
msgstr ""
|
325 |
|
326 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
327 |
#, php-format
|
328 |
msgid ""
|
329 |
"<strong>Amazon Web Services Plugin No Longer Required</strong> — As of "
|
@@ -334,7 +384,7 @@ msgid ""
|
|
334 |
"plugin, it should be safe to deactivate and delete it. %2$s"
|
335 |
msgstr ""
|
336 |
|
337 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
338 |
#, php-format
|
339 |
msgid ""
|
340 |
"<strong>WP Offload Media Settings Moved</strong> — You now define your "
|
@@ -455,52 +505,93 @@ msgid ""
|
|
455 |
"zlib. Your server currently has"
|
456 |
msgstr ""
|
457 |
|
458 |
-
#: classes/as3cf-notices.php:
|
459 |
msgid "Error dismissing notice."
|
460 |
msgstr ""
|
461 |
|
462 |
-
#: classes/as3cf-notices.php:
|
463 |
msgid "Invalid notice ID."
|
464 |
msgstr ""
|
465 |
|
466 |
-
#: classes/as3cf-plugin-base.php:
|
467 |
msgid "Settings"
|
468 |
msgstr ""
|
469 |
|
470 |
-
#: classes/as3cf-plugin-compatibility.php:
|
471 |
#, php-format
|
472 |
msgid "The local directory %s does not exist and could not be created."
|
473 |
msgstr ""
|
474 |
|
475 |
-
#: classes/as3cf-plugin-compatibility.php:
|
476 |
-
#: classes/as3cf-plugin-compatibility.php:
|
477 |
#: classes/upgrades/upgrade-meta-wp-error.php:81
|
478 |
#, php-format
|
479 |
msgid ""
|
480 |
"There was an error attempting to download the file %s from the bucket: %s"
|
481 |
msgstr ""
|
482 |
|
483 |
-
#: classes/as3cf-plugin-compatibility.php:
|
484 |
#, php-format
|
485 |
msgid ""
|
486 |
"<strong>Warning:</strong> This site is using PHP %1$s, in a future update WP "
|
487 |
"Offload Media will require PHP %2$s or later. %3$s"
|
488 |
msgstr ""
|
489 |
|
490 |
-
#: classes/providers/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
491 |
msgid "Given Key File Path is invalid or could not be accessed."
|
492 |
msgstr ""
|
493 |
|
494 |
-
#: classes/providers/provider.php:
|
495 |
-
#: classes/providers/provider.php:
|
496 |
msgid "Could not read Key File Path's contents."
|
497 |
msgstr ""
|
498 |
|
499 |
-
#: classes/providers/provider.php:
|
500 |
msgid "Given Key File Path does not contain valid JSON."
|
501 |
msgstr ""
|
502 |
|
503 |
-
#: classes/providers/provider.php:
|
504 |
#, php-format
|
505 |
msgid "You must first <a href=\"%s\">set your access keys</a>."
|
506 |
msgstr ""
|
@@ -581,19 +672,19 @@ msgid ""
|
|
581 |
"version."
|
582 |
msgstr ""
|
583 |
|
584 |
-
#: classes/upgrades/upgrade.php:
|
585 |
msgid "Pause Update"
|
586 |
msgstr ""
|
587 |
|
588 |
-
#: classes/upgrades/upgrade.php:
|
589 |
msgid "Restart Update"
|
590 |
msgstr ""
|
591 |
|
592 |
-
#: classes/upgrades/upgrade.php:
|
593 |
msgid "Try To Run It Again"
|
594 |
msgstr ""
|
595 |
|
596 |
-
#: classes/upgrades/upgrade.php:
|
597 |
#, php-format
|
598 |
msgid ""
|
599 |
"<strong>Running %1$s Update%2$s</strong> — We’re going through "
|
@@ -603,14 +694,14 @@ msgid ""
|
|
603 |
"performance."
|
604 |
msgstr ""
|
605 |
|
606 |
-
#: classes/upgrades/upgrade.php:
|
607 |
#, php-format
|
608 |
msgid ""
|
609 |
"<strong>%1$s Update Paused%2$s</strong> — Updating Media Library %3$s "
|
610 |
"has been paused."
|
611 |
msgstr ""
|
612 |
|
613 |
-
#: classes/upgrades/upgrade.php:
|
614 |
#, php-format
|
615 |
msgid ""
|
616 |
"<strong>Error Updating %1$s</strong> — We ran into some errors "
|
@@ -618,16 +709,23 @@ msgid ""
|
|
618 |
"been offloaded. Please check your error log for details. (#%3$d)"
|
619 |
msgstr ""
|
620 |
|
621 |
-
#: classes/upgrades/upgrade.php:
|
622 |
#, php-format
|
623 |
msgid " (%s%% Complete)"
|
624 |
msgstr ""
|
625 |
|
626 |
-
#: classes/upgrades/upgrade.php:
|
627 |
#, php-format
|
628 |
msgid "Every %d Minutes"
|
629 |
msgstr ""
|
630 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
631 |
#: view/addon.php:11
|
632 |
msgid "More Details »"
|
633 |
msgstr ""
|
@@ -664,118 +762,252 @@ msgstr ""
|
|
664 |
msgid "File exists on server"
|
665 |
msgstr ""
|
666 |
|
667 |
-
#: view/bucket-select.php:
|
|
|
|
|
668 |
#: view/provider-select.php:21
|
669 |
msgid "« Back"
|
670 |
msgstr ""
|
671 |
|
672 |
-
#: view/bucket-select.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
673 |
msgid "What bucket would you like to use?"
|
674 |
msgstr ""
|
675 |
|
676 |
-
#: view/bucket-select.php:
|
677 |
-
#: view/bucket-select.php:
|
678 |
-
#: view/bucket-select.php:
|
679 |
msgid "Region:"
|
680 |
msgstr ""
|
681 |
|
682 |
-
#: view/bucket-select.php:
|
683 |
-
#: view/bucket-select.php:
|
684 |
-
#: view/bucket-select.php:
|
685 |
#, php-format
|
686 |
msgid "%s (defined in wp-config.php)"
|
687 |
msgstr ""
|
688 |
|
689 |
-
#: view/bucket-select.php:
|
690 |
-
#: view/bucket-select.php:
|
691 |
-
#: view/bucket-select.php:
|
692 |
-
#: view/bucket-setting.php:
|
693 |
msgid "Bucket:"
|
694 |
msgstr ""
|
695 |
|
696 |
-
#: view/bucket-select.php:
|
697 |
msgid "Existing bucket name"
|
698 |
msgstr ""
|
699 |
|
700 |
-
#: view/bucket-select.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
701 |
msgid "Save Bucket Setting"
|
702 |
msgstr ""
|
703 |
|
704 |
-
#: view/bucket-select.php:
|
705 |
-
#: view/bucket-select.php:
|
706 |
msgid "Browse existing buckets"
|
707 |
msgstr ""
|
708 |
|
709 |
-
#: view/bucket-select.php:
|
710 |
-
#: view/bucket-select.php:
|
711 |
-
#: view/bucket-select.php:
|
712 |
msgid "Create new bucket"
|
713 |
msgstr ""
|
714 |
|
715 |
-
#: view/bucket-select.php:
|
716 |
msgid "Select bucket"
|
717 |
msgstr ""
|
718 |
|
719 |
-
#: view/bucket-select.php:
|
720 |
-
#: view/bucket-select.php:
|
721 |
msgid "Loading..."
|
722 |
msgstr ""
|
723 |
|
724 |
-
#: view/bucket-select.php:
|
725 |
-
#: view/bucket-select.php:
|
726 |
msgid "Nothing found"
|
727 |
msgstr ""
|
728 |
|
729 |
-
#: view/bucket-select.php:
|
730 |
msgid "Save Selected Bucket"
|
731 |
msgstr ""
|
732 |
|
733 |
-
#: view/bucket-select.php:
|
734 |
-
#: view/bucket-select.php:
|
735 |
msgid "Enter bucket name"
|
736 |
msgstr ""
|
737 |
|
738 |
-
#: view/bucket-select.php:
|
739 |
msgid "Refresh"
|
740 |
msgstr ""
|
741 |
|
742 |
-
#: view/bucket-select.php:
|
743 |
msgid "New bucket name"
|
744 |
msgstr ""
|
745 |
|
746 |
-
#: view/bucket-select.php:
|
747 |
msgid "Create New Bucket"
|
748 |
msgstr ""
|
749 |
|
750 |
-
#: view/bucket-setting.php:
|
751 |
msgid "View in provider's console"
|
752 |
msgstr ""
|
753 |
|
754 |
-
#: view/bucket-setting.php:
|
|
|
755 |
#: view/provider-setting.php:17
|
756 |
msgid "Change"
|
757 |
msgstr ""
|
758 |
|
759 |
-
#: view/bucket-setting.php:
|
760 |
msgid "The region that the bucket is in."
|
761 |
msgstr ""
|
762 |
|
763 |
-
#: view/bucket-setting.php:
|
764 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
765 |
msgid ""
|
766 |
-
"
|
767 |
-
|
|
|
|
|
|
|
768 |
msgstr ""
|
769 |
|
770 |
-
#: view/bucket-setting.php:
|
771 |
msgid ""
|
772 |
-
"
|
773 |
-
"
|
774 |
msgstr ""
|
775 |
|
776 |
-
#: view/
|
777 |
-
|
778 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
779 |
msgstr ""
|
780 |
|
781 |
#: view/debug-info.php:2
|
@@ -787,37 +1019,47 @@ msgctxt "Download to your computer"
|
|
787 |
msgid "Download"
|
788 |
msgstr ""
|
789 |
|
790 |
-
#: view/
|
791 |
-
msgid "
|
792 |
msgstr ""
|
793 |
|
794 |
-
#: view/
|
795 |
-
msgid "
|
796 |
msgstr ""
|
797 |
|
798 |
-
#: view/
|
799 |
-
msgid "
|
800 |
msgstr ""
|
801 |
|
802 |
-
#: view/
|
803 |
-
msgid "
|
804 |
msgstr ""
|
805 |
|
806 |
-
#: view/
|
807 |
-
|
|
|
808 |
msgstr ""
|
809 |
|
810 |
-
#: view/domain-setting.php:
|
811 |
msgid "Custom Domain (CNAME)"
|
812 |
msgstr ""
|
813 |
|
814 |
-
#: view/domain-setting.php:
|
815 |
#, php-format
|
816 |
msgid ""
|
817 |
-
"We strongly recommend you configure a
|
818 |
-
"
|
819 |
-
"
|
820 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
821 |
msgstr ""
|
822 |
|
823 |
#: view/error-access.php:4
|
@@ -959,18 +1201,10 @@ msgid ""
|
|
959 |
msgstr ""
|
960 |
|
961 |
#: view/provider-select.php:373
|
962 |
-
|
963 |
-
msgstr ""
|
964 |
-
|
965 |
-
#: view/provider-select.php:373
|
966 |
-
#: view/settings/media.php:264
|
967 |
msgid "Save Changes"
|
968 |
msgstr ""
|
969 |
|
970 |
-
#: view/provider-setting.php:12
|
971 |
-
msgid "Provider:"
|
972 |
-
msgstr ""
|
973 |
-
|
974 |
#: view/settings/addons.php:10
|
975 |
#, php-format
|
976 |
msgid ""
|
@@ -979,7 +1213,7 @@ msgid ""
|
|
979 |
"\">deliciousbrains.com</a> to purchase in just a few clicks."
|
980 |
msgstr ""
|
981 |
|
982 |
-
#: view/settings/media.php:
|
983 |
#, php-format
|
984 |
msgid ""
|
985 |
"Yikes! That's not a very SEO-friendly URL. We strongly recommend you "
|
@@ -987,106 +1221,109 @@ msgid ""
|
|
987 |
"point at your CDN. %2$s"
|
988 |
msgstr ""
|
989 |
|
990 |
-
#: view/settings/media.php:
|
991 |
msgid "Storage"
|
992 |
msgstr ""
|
993 |
|
994 |
-
#: view/settings/media.php:
|
995 |
msgid "Copy Files to Bucket"
|
996 |
msgstr ""
|
997 |
|
998 |
-
#: view/settings/media.php:
|
999 |
msgid "When a file is uploaded to the Media Library, copy it to the bucket."
|
1000 |
msgstr ""
|
1001 |
|
1002 |
-
#: view/settings/media.php:
|
1003 |
msgid "Path"
|
1004 |
msgstr ""
|
1005 |
|
1006 |
-
#: view/settings/media.php:
|
1007 |
msgid "By default the path is the same as your local WordPress files."
|
1008 |
msgstr ""
|
1009 |
|
1010 |
-
#: view/settings/media.php:
|
|
|
1011 |
msgid "Year/Month"
|
1012 |
msgstr ""
|
1013 |
|
1014 |
-
#: view/settings/media.php:
|
1015 |
msgid ""
|
1016 |
"Add the Year/Month to the end of the path above just like WordPress does by "
|
1017 |
"default."
|
1018 |
msgstr ""
|
1019 |
|
1020 |
-
#: view/settings/media.php:
|
|
|
1021 |
msgid "Object Versioning"
|
1022 |
msgstr ""
|
1023 |
|
1024 |
-
#: view/settings/media.php:
|
1025 |
msgid ""
|
1026 |
"Append a timestamp to the file's bucket path. Recommended when using a CDN "
|
1027 |
"so you don't have to worry about cache invalidation."
|
1028 |
msgstr ""
|
1029 |
|
1030 |
-
#: view/settings/media.php:
|
1031 |
-
msgid "
|
1032 |
msgstr ""
|
1033 |
|
1034 |
-
#: view/settings/media.php:
|
1035 |
msgid "Rewrite Media URLs"
|
1036 |
msgstr ""
|
1037 |
|
1038 |
-
#: view/settings/media.php:
|
|
|
1039 |
msgid ""
|
1040 |
"For Media Library files that have been copied to your bucket, rewrite the "
|
1041 |
-
"URLs so that they are served from
|
1042 |
msgstr ""
|
1043 |
|
1044 |
-
#: view/settings/media.php:
|
1045 |
msgid "Force HTTPS"
|
1046 |
msgstr ""
|
1047 |
|
1048 |
-
#: view/settings/media.php:
|
1049 |
msgid ""
|
1050 |
"By default we use HTTPS when the request is HTTPS and regular HTTP when the "
|
1051 |
"request is HTTP, but you may want to force the use of HTTPS always, "
|
1052 |
"regardless of the request."
|
1053 |
msgstr ""
|
1054 |
|
1055 |
-
#: view/settings/media.php:
|
1056 |
msgid "Advanced Options"
|
1057 |
msgstr ""
|
1058 |
|
1059 |
-
#: view/settings/media.php:
|
1060 |
msgid "Remove Files From Server"
|
1061 |
msgstr ""
|
1062 |
|
1063 |
-
#: view/settings/media.php:
|
1064 |
msgid ""
|
1065 |
"Once a file has been copied to the bucket, remove it from the local server."
|
1066 |
msgstr ""
|
1067 |
|
1068 |
-
#: view/settings/media.php:
|
1069 |
msgid ""
|
1070 |
"<strong>Broken URLs</strong> — There will be broken URLs for files "
|
1071 |
"that don't exist locally. You can fix this by enabling <strong>Rewrite Media "
|
1072 |
"URLs</strong> to use the offloaded media."
|
1073 |
msgstr ""
|
1074 |
|
1075 |
-
#: view/settings/media.php:
|
1076 |
#, php-format
|
1077 |
msgid ""
|
1078 |
"<strong>Warning</strong> — Some plugins depend on the file being "
|
1079 |
"present on the local server and may not work when the file is removed. %s"
|
1080 |
msgstr ""
|
1081 |
|
1082 |
-
#: view/settings/media.php:
|
1083 |
msgid ""
|
1084 |
"If you have a backup system in place (as you should) that backs up your site "
|
1085 |
"files, media, and database, your media will no longer be backed up as it "
|
1086 |
"will no longer be present on the filesystem."
|
1087 |
msgstr ""
|
1088 |
|
1089 |
-
#: view/settings/media.php:
|
1090 |
#, php-format
|
1091 |
msgid ""
|
1092 |
"Need help getting your Access Keys? <a href=\"%s\">Check out the Quick Start "
|
@@ -1114,7 +1351,7 @@ msgid "Easy Digital Downloads integration"
|
|
1114 |
msgstr ""
|
1115 |
|
1116 |
#: view/sidebar.php:18
|
1117 |
-
msgid "
|
1118 |
msgstr ""
|
1119 |
|
1120 |
#: view/sidebar.php:25
|
@@ -1154,6 +1391,22 @@ msgid ""
|
|
1154 |
"unsubscribe with 1-click anytime."
|
1155 |
msgstr ""
|
1156 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1157 |
#: view/wordpress-org-support.php:2
|
1158 |
msgid "As this is a free plugin, we do not provide support."
|
1159 |
msgstr ""
|
8 |
msgstr ""
|
9 |
"Project-Id-Version: amazon-s3-and-cloudfront\n"
|
10 |
"Report-Msgid-Bugs-To: nom@deliciousbrains.com\n"
|
11 |
+
"POT-Creation-Date: 2020-07-14 09:51+0100\n"
|
12 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
17 |
"Content-Type: text/plain; charset=UTF-8\n"
|
18 |
"Content-Transfer-Encoding: 8bit\n"
|
19 |
|
20 |
+
#: classes/amazon-s3-and-cloudfront.php:165
|
21 |
+
#: classes/amazon-s3-and-cloudfront.php:166
|
22 |
msgid "Offload Media Lite"
|
23 |
msgstr ""
|
24 |
|
25 |
+
#: classes/amazon-s3-and-cloudfront.php:389
|
26 |
+
#: classes/amazon-s3-and-cloudfront.php:406
|
27 |
msgid "Unknown"
|
28 |
msgstr ""
|
29 |
|
30 |
+
#: classes/amazon-s3-and-cloudfront.php:478
|
31 |
+
#: view/bucket-select.php:87
|
32 |
+
#: view/delivery-provider-select.php:129
|
33 |
+
#: view/delivery-provider-select.php:149
|
34 |
#: view/provider-select.php:122
|
35 |
+
#: view/signed-urls-setting.php:18
|
36 |
+
#: view/signed-urls-setting.php:48
|
37 |
+
#: view/signed-urls-setting.php:79
|
38 |
msgid "defined in wp-config.php"
|
39 |
msgstr ""
|
40 |
|
41 |
+
#: classes/amazon-s3-and-cloudfront.php:1404
|
42 |
#, php-format
|
43 |
msgid "Media Library item with ID %d does not have a valid file path"
|
44 |
msgstr ""
|
45 |
|
46 |
+
#: classes/amazon-s3-and-cloudfront.php:1454
|
47 |
+
#: classes/amazon-s3-and-cloudfront.php:1653
|
48 |
#, php-format
|
49 |
msgid "File %s does not exist"
|
50 |
msgstr ""
|
51 |
|
52 |
+
#: classes/amazon-s3-and-cloudfront.php:1484
|
53 |
#, php-format
|
54 |
msgid "Mime type %s is not allowed"
|
55 |
msgstr ""
|
56 |
|
57 |
+
#: classes/amazon-s3-and-cloudfront.php:1495
|
58 |
msgid "Already offloaded to a different provider"
|
59 |
msgstr ""
|
60 |
|
61 |
+
#: classes/amazon-s3-and-cloudfront.php:1601
|
62 |
+
#: classes/amazon-s3-and-cloudfront.php:1666
|
63 |
#, php-format
|
64 |
msgid "Error offloading %s to provider: %s"
|
65 |
msgstr ""
|
66 |
|
67 |
+
#: classes/amazon-s3-and-cloudfront.php:2782
|
68 |
msgid "This action can only be performed through an admin screen."
|
69 |
msgstr ""
|
70 |
|
71 |
+
#: classes/amazon-s3-and-cloudfront.php:2784
|
72 |
msgid "Cheatin’ eh?"
|
73 |
msgstr ""
|
74 |
|
75 |
+
#: classes/amazon-s3-and-cloudfront.php:2786
|
76 |
msgid "You do not have sufficient permissions to access this page."
|
77 |
msgstr ""
|
78 |
|
79 |
+
#: classes/amazon-s3-and-cloudfront.php:3110
|
80 |
msgid "Error Getting Bucket Region"
|
81 |
msgstr ""
|
82 |
|
83 |
+
#: classes/amazon-s3-and-cloudfront.php:3111
|
84 |
#, php-format
|
85 |
msgid "There was an error attempting to get the region of the bucket %s: %s"
|
86 |
msgstr ""
|
87 |
|
88 |
+
#: classes/amazon-s3-and-cloudfront.php:3214
|
89 |
msgid ""
|
90 |
"This is a test file to check if the user has write permission to the bucket. "
|
91 |
"Delete me if found."
|
92 |
msgstr ""
|
93 |
|
94 |
+
#: classes/amazon-s3-and-cloudfront.php:3220
|
95 |
#, php-format
|
96 |
msgid ""
|
97 |
"There was an error attempting to check the permissions of the bucket %s: %s"
|
98 |
msgstr ""
|
99 |
|
100 |
+
#: classes/amazon-s3-and-cloudfront.php:3316
|
101 |
msgid "Error creating bucket"
|
102 |
msgstr ""
|
103 |
|
104 |
+
#: classes/amazon-s3-and-cloudfront.php:3317
|
105 |
msgid "Bucket name too short."
|
106 |
msgstr ""
|
107 |
|
108 |
+
#: classes/amazon-s3-and-cloudfront.php:3318
|
109 |
msgid "Bucket name too long."
|
110 |
msgstr ""
|
111 |
|
112 |
+
#: classes/amazon-s3-and-cloudfront.php:3319
|
113 |
msgid ""
|
114 |
"Invalid character. Bucket names can contain lowercase letters, numbers, "
|
115 |
"periods and hyphens."
|
116 |
msgstr ""
|
117 |
|
118 |
+
#: classes/amazon-s3-and-cloudfront.php:3320
|
119 |
msgid "Error saving bucket"
|
120 |
msgstr ""
|
121 |
|
122 |
+
#: classes/amazon-s3-and-cloudfront.php:3321
|
123 |
msgid "Error fetching buckets"
|
124 |
msgstr ""
|
125 |
|
126 |
+
#: classes/amazon-s3-and-cloudfront.php:3322
|
127 |
msgid "Error getting URL preview: "
|
128 |
msgstr ""
|
129 |
|
130 |
+
#: classes/amazon-s3-and-cloudfront.php:3323
|
131 |
msgid "The changes you made will be lost if you navigate away from this page"
|
132 |
msgstr ""
|
133 |
|
134 |
+
#: classes/amazon-s3-and-cloudfront.php:3324
|
135 |
msgid "Getting diagnostic info..."
|
136 |
msgstr ""
|
137 |
|
138 |
+
#: classes/amazon-s3-and-cloudfront.php:3325
|
139 |
msgid "Error getting diagnostic info: "
|
140 |
msgstr ""
|
141 |
|
142 |
+
#: classes/amazon-s3-and-cloudfront.php:3326
|
143 |
msgctxt "placeholder for hidden access key, 39 char max"
|
144 |
msgid "-- not shown --"
|
145 |
msgstr ""
|
146 |
|
147 |
+
#: classes/amazon-s3-and-cloudfront.php:3328
|
148 |
+
#: classes/amazon-s3-and-cloudfront.php:5585
|
149 |
msgid "Settings saved."
|
150 |
msgstr ""
|
151 |
|
152 |
+
#: classes/amazon-s3-and-cloudfront.php:3449
|
153 |
msgid "Cheatin' eh?"
|
154 |
msgstr ""
|
155 |
|
156 |
+
#: classes/amazon-s3-and-cloudfront.php:3522
|
157 |
+
#, php-format
|
158 |
+
msgid "Could not set new Delivery Provider: %s"
|
159 |
+
msgstr ""
|
160 |
+
|
161 |
+
#: classes/amazon-s3-and-cloudfront.php:3597
|
162 |
+
#: classes/amazon-s3-and-cloudfront.php:3727
|
163 |
msgid "No bucket name provided."
|
164 |
msgstr ""
|
165 |
|
166 |
+
#: classes/amazon-s3-and-cloudfront.php:3606
|
167 |
msgid "Bucket name not valid."
|
168 |
msgstr ""
|
169 |
|
170 |
+
#: classes/amazon-s3-and-cloudfront.php:3619
|
171 |
msgid "No region provided."
|
172 |
msgstr ""
|
173 |
|
174 |
+
#: classes/amazon-s3-and-cloudfront.php:3696
|
175 |
+
#, php-format
|
176 |
+
msgctxt "Trying to change public access setting for given provider's bucket."
|
177 |
+
msgid "Can't change Block All Public Access setting for %s buckets."
|
178 |
+
msgstr ""
|
179 |
+
|
180 |
+
#: classes/amazon-s3-and-cloudfront.php:3705
|
181 |
+
msgid "No block public access setting provided."
|
182 |
+
msgstr ""
|
183 |
+
|
184 |
+
#: classes/amazon-s3-and-cloudfront.php:3718
|
185 |
+
msgid "Storage Provider not configured with access credentials."
|
186 |
+
msgstr ""
|
187 |
+
|
188 |
+
#: classes/amazon-s3-and-cloudfront.php:3745
|
189 |
+
msgid "Could not change Block All Public Access status for bucket."
|
190 |
+
msgstr ""
|
191 |
+
|
192 |
+
#: classes/amazon-s3-and-cloudfront.php:3762
|
193 |
+
msgid ""
|
194 |
+
"<strong>Failed to Enable Block All Public Access</strong> — We could "
|
195 |
+
"not enable Block All Public Access. You will need to log in to the AWS "
|
196 |
+
"Console and do it manually."
|
197 |
+
msgstr ""
|
198 |
+
|
199 |
+
#: classes/amazon-s3-and-cloudfront.php:3764
|
200 |
+
msgid ""
|
201 |
+
"<strong>Failed to Disable Block All Public Access</strong> — We could "
|
202 |
+
"not disable Block All Public Access. You will need to log in to the AWS "
|
203 |
+
"Console and do it manually."
|
204 |
+
msgstr ""
|
205 |
+
|
206 |
+
#: classes/amazon-s3-and-cloudfront.php:3799
|
207 |
#: view/provider-select.php:329
|
208 |
msgctxt "placeholder for hidden secret access key, 39 char max"
|
209 |
msgid "-- not shown --"
|
210 |
msgstr ""
|
211 |
|
212 |
+
#: classes/amazon-s3-and-cloudfront.php:3822
|
213 |
msgid "Key File not valid JSON."
|
214 |
msgstr ""
|
215 |
|
216 |
+
#: classes/amazon-s3-and-cloudfront.php:3834
|
217 |
+
#: classes/amazon-s3-and-cloudfront.php:3848
|
218 |
+
#: classes/amazon-s3-and-cloudfront.php:3857
|
219 |
+
msgctxt "missing form field"
|
220 |
+
msgid " not provided."
|
221 |
+
msgstr ""
|
222 |
+
|
223 |
+
#: classes/amazon-s3-and-cloudfront.php:3900
|
224 |
msgctxt "Show the media library tab"
|
225 |
msgid "Media Library"
|
226 |
msgstr ""
|
227 |
|
228 |
+
#: classes/amazon-s3-and-cloudfront.php:3901
|
229 |
msgctxt "Show the addons tab"
|
230 |
msgid "Addons"
|
231 |
msgstr ""
|
232 |
|
233 |
+
#: classes/amazon-s3-and-cloudfront.php:3902
|
234 |
msgctxt "Show the support tab"
|
235 |
msgid "Support"
|
236 |
msgstr ""
|
237 |
|
238 |
+
#: classes/amazon-s3-and-cloudfront.php:4077
|
239 |
#, php-format
|
240 |
msgid ""
|
241 |
"<strong>WP Offload Media</strong> — The file %s has been given %s "
|
242 |
"permissions in the bucket."
|
243 |
msgstr ""
|
244 |
|
245 |
+
#: classes/amazon-s3-and-cloudfront.php:4096
|
246 |
msgid ""
|
247 |
"<strong>WP Offload Media Requirement Missing</strong> — Looks like you "
|
248 |
"don't have an image manipulation library installed on this server and "
|
250 |
"Please setup GD or ImageMagick."
|
251 |
msgstr ""
|
252 |
|
253 |
+
#: classes/amazon-s3-and-cloudfront.php:4878
|
254 |
#, php-format
|
255 |
msgid ""
|
256 |
"<a href=\"%s\">Define your access keys</a> to enable write access to the "
|
257 |
"bucket"
|
258 |
msgstr ""
|
259 |
|
260 |
+
#: classes/amazon-s3-and-cloudfront.php:4885
|
261 |
msgid "Quick Start Guide"
|
262 |
msgstr ""
|
263 |
|
264 |
+
#: classes/amazon-s3-and-cloudfront.php:4887
|
265 |
#, php-format
|
266 |
msgid ""
|
267 |
"Looks like we don't have write access to this bucket. It's likely that the "
|
270 |
"correctly."
|
271 |
msgstr ""
|
272 |
|
273 |
+
#: classes/amazon-s3-and-cloudfront.php:4889
|
274 |
#, php-format
|
275 |
msgid ""
|
276 |
"Looks like we don't have access to the buckets. It's likely that the user "
|
278 |
"Please see our %s for instructions on setting up permissions correctly."
|
279 |
msgstr ""
|
280 |
|
281 |
+
#: classes/amazon-s3-and-cloudfront.php:5015
|
282 |
msgid "WP Offload Media Activation"
|
283 |
msgstr ""
|
284 |
|
285 |
+
#: classes/amazon-s3-and-cloudfront.php:5016
|
286 |
msgid ""
|
287 |
"WP Offload Media Lite and WP Offload Media cannot both be active. We've "
|
288 |
"automatically deactivated WP Offload Media Lite."
|
289 |
msgstr ""
|
290 |
|
291 |
+
#: classes/amazon-s3-and-cloudfront.php:5018
|
292 |
msgid "WP Offload Media Lite Activation"
|
293 |
msgstr ""
|
294 |
|
295 |
+
#: classes/amazon-s3-and-cloudfront.php:5019
|
296 |
msgid ""
|
297 |
"WP Offload Media Lite and WP Offload Media cannot both be active. We've "
|
298 |
"automatically deactivated WP Offload Media."
|
299 |
msgstr ""
|
300 |
|
301 |
+
#: classes/amazon-s3-and-cloudfront.php:5071
|
302 |
msgid "More info »"
|
303 |
msgstr ""
|
304 |
|
305 |
+
#: classes/amazon-s3-and-cloudfront.php:5147
|
306 |
msgid "this doc"
|
307 |
msgstr ""
|
308 |
|
309 |
+
#: classes/amazon-s3-and-cloudfront.php:5149
|
310 |
msgid "WP Offload Media Feature Removed"
|
311 |
msgstr ""
|
312 |
|
313 |
+
#: classes/amazon-s3-and-cloudfront.php:5150
|
314 |
#, php-format
|
315 |
msgid ""
|
316 |
"You had the \"Always non-SSL\" option selected in your settings, but we've "
|
321 |
"to the old behavior."
|
322 |
msgstr ""
|
323 |
|
324 |
+
#: classes/amazon-s3-and-cloudfront.php:5185
|
325 |
msgid "Offload"
|
326 |
msgstr ""
|
327 |
|
328 |
+
#: classes/amazon-s3-and-cloudfront.php:5290
|
329 |
msgctxt "Storage provider key name"
|
330 |
msgid "Storage Provider"
|
331 |
msgstr ""
|
332 |
|
333 |
+
#: classes/amazon-s3-and-cloudfront.php:5291
|
334 |
msgctxt "Storage provider name"
|
335 |
msgid "Storage Provider"
|
336 |
msgstr ""
|
337 |
|
338 |
+
#: classes/amazon-s3-and-cloudfront.php:5292
|
339 |
msgctxt "Bucket name"
|
340 |
msgid "Bucket"
|
341 |
msgstr ""
|
342 |
|
343 |
+
#: classes/amazon-s3-and-cloudfront.php:5293
|
344 |
msgctxt "Path to file in bucket"
|
345 |
msgid "Path"
|
346 |
msgstr ""
|
347 |
|
348 |
+
#: classes/amazon-s3-and-cloudfront.php:5294
|
349 |
msgctxt "Location of bucket"
|
350 |
msgid "Region"
|
351 |
msgstr ""
|
352 |
|
353 |
+
#: classes/amazon-s3-and-cloudfront.php:5295
|
354 |
msgctxt "Access control list of the file in bucket"
|
355 |
msgid "Access"
|
356 |
msgstr ""
|
357 |
|
358 |
+
#: classes/amazon-s3-and-cloudfront.php:5296
|
359 |
msgid "URL"
|
360 |
msgstr ""
|
361 |
|
362 |
+
#: classes/amazon-s3-and-cloudfront.php:5548
|
363 |
msgid "Assets Pull"
|
364 |
msgstr ""
|
365 |
|
366 |
+
#: classes/amazon-s3-and-cloudfront.php:5549
|
367 |
msgid ""
|
368 |
"An addon for WP Offload Media to serve your site's JS, CSS, and other "
|
369 |
"enqueued assets from Amazon CloudFront or another CDN."
|
370 |
msgstr ""
|
371 |
|
372 |
+
#: classes/amazon-s3-and-cloudfront.php:5553
|
373 |
msgid "Feature"
|
374 |
msgstr ""
|
375 |
|
376 |
+
#: classes/amazon-s3-and-cloudfront.php:5599
|
377 |
#, php-format
|
378 |
msgid ""
|
379 |
"<strong>Amazon Web Services Plugin No Longer Required</strong> — As of "
|
384 |
"plugin, it should be safe to deactivate and delete it. %2$s"
|
385 |
msgstr ""
|
386 |
|
387 |
+
#: classes/amazon-s3-and-cloudfront.php:5631
|
388 |
#, php-format
|
389 |
msgid ""
|
390 |
"<strong>WP Offload Media Settings Moved</strong> — You now define your "
|
505 |
"zlib. Your server currently has"
|
506 |
msgstr ""
|
507 |
|
508 |
+
#: classes/as3cf-notices.php:430
|
509 |
msgid "Error dismissing notice."
|
510 |
msgstr ""
|
511 |
|
512 |
+
#: classes/as3cf-notices.php:445
|
513 |
msgid "Invalid notice ID."
|
514 |
msgstr ""
|
515 |
|
516 |
+
#: classes/as3cf-plugin-base.php:575
|
517 |
msgid "Settings"
|
518 |
msgstr ""
|
519 |
|
520 |
+
#: classes/as3cf-plugin-compatibility.php:595
|
521 |
#, php-format
|
522 |
msgid "The local directory %s does not exist and could not be created."
|
523 |
msgstr ""
|
524 |
|
525 |
+
#: classes/as3cf-plugin-compatibility.php:596
|
526 |
+
#: classes/as3cf-plugin-compatibility.php:608
|
527 |
#: classes/upgrades/upgrade-meta-wp-error.php:81
|
528 |
#, php-format
|
529 |
msgid ""
|
530 |
"There was an error attempting to download the file %s from the bucket: %s"
|
531 |
msgstr ""
|
532 |
|
533 |
+
#: classes/as3cf-plugin-compatibility.php:933
|
534 |
#, php-format
|
535 |
msgid ""
|
536 |
"<strong>Warning:</strong> This site is using PHP %1$s, in a future update WP "
|
537 |
"Offload Media will require PHP %2$s or later. %3$s"
|
538 |
msgstr ""
|
539 |
|
540 |
+
#: classes/providers/delivery/another-cdn.php:47
|
541 |
+
#: classes/providers/delivery/digitalocean-spaces-cdn.php:83
|
542 |
+
msgid "Fast, No Private Media"
|
543 |
+
msgstr ""
|
544 |
+
|
545 |
+
#: classes/providers/delivery/aws-cloudfront.php:106
|
546 |
+
#, php-format
|
547 |
+
msgid ""
|
548 |
+
"Fast, Private Media Supported with <a href=\"%s\" target=\"_blank\">upgrade</"
|
549 |
+
"a>"
|
550 |
+
msgstr ""
|
551 |
+
|
552 |
+
#: classes/providers/delivery/delivery-provider.php:94
|
553 |
+
msgid "Signing Key ID"
|
554 |
+
msgstr ""
|
555 |
+
|
556 |
+
#: classes/providers/delivery/delivery-provider.php:112
|
557 |
+
msgid "Signing Key File Path"
|
558 |
+
msgstr ""
|
559 |
+
|
560 |
+
#: classes/providers/delivery/delivery-provider.php:130
|
561 |
+
msgid "Private Path"
|
562 |
+
msgstr ""
|
563 |
+
|
564 |
+
#: classes/providers/delivery/delivery-provider.php:275
|
565 |
+
msgid "Given Signing Key File Path is invalid or could not be accessed."
|
566 |
+
msgstr ""
|
567 |
+
|
568 |
+
#: classes/providers/delivery/delivery-provider.php:285
|
569 |
+
#: classes/providers/delivery/delivery-provider.php:290
|
570 |
+
msgid "Could not read Signing Key File Path's contents."
|
571 |
+
msgstr ""
|
572 |
+
|
573 |
+
#: classes/providers/delivery/gcp-cdn.php:73
|
574 |
+
msgid "Fast, Private Media Supported"
|
575 |
+
msgstr ""
|
576 |
+
|
577 |
+
#: classes/providers/delivery/storage.php:92
|
578 |
+
msgid "Slow, Private Media Supported"
|
579 |
+
msgstr ""
|
580 |
+
|
581 |
+
#: classes/providers/storage/storage-provider.php:338
|
582 |
msgid "Given Key File Path is invalid or could not be accessed."
|
583 |
msgstr ""
|
584 |
|
585 |
+
#: classes/providers/storage/storage-provider.php:348
|
586 |
+
#: classes/providers/storage/storage-provider.php:353
|
587 |
msgid "Could not read Key File Path's contents."
|
588 |
msgstr ""
|
589 |
|
590 |
+
#: classes/providers/storage/storage-provider.php:361
|
591 |
msgid "Given Key File Path does not contain valid JSON."
|
592 |
msgstr ""
|
593 |
|
594 |
+
#: classes/providers/storage/storage-provider.php:511
|
595 |
#, php-format
|
596 |
msgid "You must first <a href=\"%s\">set your access keys</a>."
|
597 |
msgstr ""
|
672 |
"version."
|
673 |
msgstr ""
|
674 |
|
675 |
+
#: classes/upgrades/upgrade.php:410
|
676 |
msgid "Pause Update"
|
677 |
msgstr ""
|
678 |
|
679 |
+
#: classes/upgrades/upgrade.php:418
|
680 |
msgid "Restart Update"
|
681 |
msgstr ""
|
682 |
|
683 |
+
#: classes/upgrades/upgrade.php:422
|
684 |
msgid "Try To Run It Again"
|
685 |
msgstr ""
|
686 |
|
687 |
+
#: classes/upgrades/upgrade.php:445
|
688 |
#, php-format
|
689 |
msgid ""
|
690 |
"<strong>Running %1$s Update%2$s</strong> — We’re going through "
|
694 |
"performance."
|
695 |
msgstr ""
|
696 |
|
697 |
+
#: classes/upgrades/upgrade.php:459
|
698 |
#, php-format
|
699 |
msgid ""
|
700 |
"<strong>%1$s Update Paused%2$s</strong> — Updating Media Library %3$s "
|
701 |
"has been paused."
|
702 |
msgstr ""
|
703 |
|
704 |
+
#: classes/upgrades/upgrade.php:472
|
705 |
#, php-format
|
706 |
msgid ""
|
707 |
"<strong>Error Updating %1$s</strong> — We ran into some errors "
|
709 |
"been offloaded. Please check your error log for details. (#%3$d)"
|
710 |
msgstr ""
|
711 |
|
712 |
+
#: classes/upgrades/upgrade.php:496
|
713 |
#, php-format
|
714 |
msgid " (%s%% Complete)"
|
715 |
msgstr ""
|
716 |
|
717 |
+
#: classes/upgrades/upgrade.php:629
|
718 |
#, php-format
|
719 |
msgid "Every %d Minutes"
|
720 |
msgstr ""
|
721 |
|
722 |
+
#: classes/upgrades/upgrade.php:956
|
723 |
+
#, php-format
|
724 |
+
msgid ""
|
725 |
+
"<strong>Settings Locked Temporarily</strong> — You can't change any of "
|
726 |
+
"your settings until the \"%s\" has completed."
|
727 |
+
msgstr ""
|
728 |
+
|
729 |
#: view/addon.php:11
|
730 |
msgid "More Details »"
|
731 |
msgstr ""
|
762 |
msgid "File exists on server"
|
763 |
msgstr ""
|
764 |
|
765 |
+
#: view/bucket-access-select.php:11
|
766 |
+
#: view/bucket-select.php:39
|
767 |
+
#: view/delivery-provider-select.php:17
|
768 |
#: view/provider-select.php:21
|
769 |
msgid "« Back"
|
770 |
msgstr ""
|
771 |
|
772 |
+
#: view/bucket-access-select.php:42
|
773 |
+
#: view/bucket-access-select.php:65
|
774 |
+
msgid "Block All Public Access is currently disabled"
|
775 |
+
msgstr ""
|
776 |
+
|
777 |
+
#: view/bucket-access-select.php:45
|
778 |
+
msgid ""
|
779 |
+
"Since you're using Amazon CloudFront for delivery we recommend you enable "
|
780 |
+
"Block All Public Access once you have set up the required Origin Access "
|
781 |
+
"Identity and bucket policy."
|
782 |
+
msgstr ""
|
783 |
+
|
784 |
+
#: view/bucket-access-select.php:54
|
785 |
+
#, php-format
|
786 |
+
msgid ""
|
787 |
+
"I have set up the required <a href=\"%1$s\">Origin Access Identity and "
|
788 |
+
"bucket policy</a>"
|
789 |
+
msgstr ""
|
790 |
+
|
791 |
+
#: view/bucket-access-select.php:61
|
792 |
+
#: view/bucket-access-select.php:74
|
793 |
+
msgid "Enable \"Block All Public Access\""
|
794 |
+
msgstr ""
|
795 |
+
|
796 |
+
#: view/bucket-access-select.php:62
|
797 |
+
msgid "Leave \"Block All Public Access\" disabled"
|
798 |
+
msgstr ""
|
799 |
+
|
800 |
+
#: view/bucket-access-select.php:68
|
801 |
+
msgid ""
|
802 |
+
"Since you're not using Amazon CloudFront for delivery, we recommend you keep "
|
803 |
+
"Block All Public Access disabled unless you have a very good reason to "
|
804 |
+
"enable it."
|
805 |
+
msgstr ""
|
806 |
+
|
807 |
+
#: view/bucket-access-select.php:73
|
808 |
+
msgid "Leave \"Block All Public Access\" Disabled"
|
809 |
+
msgstr ""
|
810 |
+
|
811 |
+
#: view/bucket-access-select.php:81
|
812 |
+
#: view/bucket-access-select.php:108
|
813 |
+
msgid "Block All Public Access is currently enabled"
|
814 |
+
msgstr ""
|
815 |
+
|
816 |
+
#: view/bucket-access-select.php:84
|
817 |
+
msgid ""
|
818 |
+
"Since you're using Amazon CloudFront for delivery we recommend you keep "
|
819 |
+
"Block All Public Access enabled."
|
820 |
+
msgstr ""
|
821 |
+
|
822 |
+
#: view/bucket-access-select.php:89
|
823 |
+
#: view/bucket-access-select.php:124
|
824 |
+
msgid "Leave \"Block All Public Access\" enabled"
|
825 |
+
msgstr ""
|
826 |
+
|
827 |
+
#: view/bucket-access-select.php:90
|
828 |
+
#: view/bucket-access-select.php:105
|
829 |
+
#: view/bucket-access-select.php:123
|
830 |
+
msgid "Disable \"Block All Public Access\""
|
831 |
+
msgstr ""
|
832 |
+
|
833 |
+
#: view/bucket-access-select.php:93
|
834 |
+
msgid "Warning: Block All Public Access is currently enabled"
|
835 |
+
msgstr ""
|
836 |
+
|
837 |
+
#: view/bucket-access-select.php:97
|
838 |
+
#, php-format
|
839 |
+
msgid ""
|
840 |
+
"If you're following <a href=\"%1$s\">our documentation on setting up Amazon "
|
841 |
+
"CloudFront for delivery</a>, you can ignore this warning and continue. If "
|
842 |
+
"you're not planning on using Amazon CloudFront for delivery, you need to <a "
|
843 |
+
"href=\"%2$s\">disable Block All Public Access</a>."
|
844 |
+
msgstr ""
|
845 |
+
|
846 |
+
#: view/bucket-access-select.php:104
|
847 |
+
msgid "Continue"
|
848 |
+
msgstr ""
|
849 |
+
|
850 |
+
#: view/bucket-access-select.php:112
|
851 |
+
msgid ""
|
852 |
+
"You need to disable Block All Public Access so that your bucket is "
|
853 |
+
"accessible for delivery. Block All Public Access should only been enabled "
|
854 |
+
"when Amazon CloudFront is configured for delivery."
|
855 |
+
msgstr ""
|
856 |
+
|
857 |
+
#: view/bucket-access-select.php:115
|
858 |
+
#, php-format
|
859 |
+
msgid ""
|
860 |
+
"You need to disable Block All Public Access so that %1$s can access your "
|
861 |
+
"bucket for delivery. Block All Public Access should only been enabled when "
|
862 |
+
"Amazon CloudFront is configured for delivery."
|
863 |
+
msgstr ""
|
864 |
+
|
865 |
+
#: view/bucket-select.php:45
|
866 |
msgid "What bucket would you like to use?"
|
867 |
msgstr ""
|
868 |
|
869 |
+
#: view/bucket-select.php:58
|
870 |
+
#: view/bucket-select.php:128
|
871 |
+
#: view/bucket-select.php:181
|
872 |
msgid "Region:"
|
873 |
msgstr ""
|
874 |
|
875 |
+
#: view/bucket-select.php:73
|
876 |
+
#: view/bucket-select.php:143
|
877 |
+
#: view/bucket-select.php:198
|
878 |
#, php-format
|
879 |
msgid "%s (defined in wp-config.php)"
|
880 |
msgstr ""
|
881 |
|
882 |
+
#: view/bucket-select.php:80
|
883 |
+
#: view/bucket-select.php:149
|
884 |
+
#: view/bucket-select.php:204
|
885 |
+
#: view/bucket-setting.php:16
|
886 |
msgid "Bucket:"
|
887 |
msgstr ""
|
888 |
|
889 |
+
#: view/bucket-select.php:95
|
890 |
msgid "Existing bucket name"
|
891 |
msgstr ""
|
892 |
|
893 |
+
#: view/bucket-select.php:104
|
894 |
+
#: view/delivery-provider-select.php:189
|
895 |
+
#: view/provider-select.php:373
|
896 |
+
msgid "Next"
|
897 |
+
msgstr ""
|
898 |
+
|
899 |
+
#: view/bucket-select.php:104
|
900 |
msgid "Save Bucket Setting"
|
901 |
msgstr ""
|
902 |
|
903 |
+
#: view/bucket-select.php:106
|
904 |
+
#: view/bucket-select.php:214
|
905 |
msgid "Browse existing buckets"
|
906 |
msgstr ""
|
907 |
|
908 |
+
#: view/bucket-select.php:107
|
909 |
+
#: view/bucket-select.php:163
|
910 |
+
#: view/bucket-select.php:169
|
911 |
msgid "Create new bucket"
|
912 |
msgstr ""
|
913 |
|
914 |
+
#: view/bucket-select.php:113
|
915 |
msgid "Select bucket"
|
916 |
msgstr ""
|
917 |
|
918 |
+
#: view/bucket-select.php:152
|
919 |
+
#: view/bucket-select.php:157
|
920 |
msgid "Loading..."
|
921 |
msgstr ""
|
922 |
|
923 |
+
#: view/bucket-select.php:152
|
924 |
+
#: view/bucket-select.php:157
|
925 |
msgid "Nothing found"
|
926 |
msgstr ""
|
927 |
|
928 |
+
#: view/bucket-select.php:161
|
929 |
msgid "Save Selected Bucket"
|
930 |
msgstr ""
|
931 |
|
932 |
+
#: view/bucket-select.php:162
|
933 |
+
#: view/bucket-select.php:215
|
934 |
msgid "Enter bucket name"
|
935 |
msgstr ""
|
936 |
|
937 |
+
#: view/bucket-select.php:164
|
938 |
msgid "Refresh"
|
939 |
msgstr ""
|
940 |
|
941 |
+
#: view/bucket-select.php:207
|
942 |
msgid "New bucket name"
|
943 |
msgstr ""
|
944 |
|
945 |
+
#: view/bucket-select.php:213
|
946 |
msgid "Create New Bucket"
|
947 |
msgstr ""
|
948 |
|
949 |
+
#: view/bucket-setting.php:21
|
950 |
msgid "View in provider's console"
|
951 |
msgstr ""
|
952 |
|
953 |
+
#: view/bucket-setting.php:25
|
954 |
+
#: view/delivery-provider-setting.php:17
|
955 |
#: view/provider-setting.php:17
|
956 |
msgid "Change"
|
957 |
msgstr ""
|
958 |
|
959 |
+
#: view/bucket-setting.php:28
|
960 |
msgid "The region that the bucket is in."
|
961 |
msgstr ""
|
962 |
|
963 |
+
#: view/bucket-setting.php:33
|
964 |
+
msgid "Unknown Region"
|
965 |
+
msgstr ""
|
966 |
+
|
967 |
+
#: view/bucket-setting.php:54
|
968 |
+
msgid "Block All Public Access Enabled"
|
969 |
+
msgstr ""
|
970 |
+
|
971 |
+
#: view/bucket-setting.php:55
|
972 |
msgid ""
|
973 |
+
"Public access to bucket has been blocked at either account or bucket level."
|
974 |
+
msgstr ""
|
975 |
+
|
976 |
+
#: view/bucket-setting.php:57
|
977 |
+
msgid "Block All Public Access Disabled"
|
978 |
msgstr ""
|
979 |
|
980 |
+
#: view/bucket-setting.php:58
|
981 |
msgid ""
|
982 |
+
"Public access to bucket has not been blocked at either account or bucket "
|
983 |
+
"level."
|
984 |
msgstr ""
|
985 |
|
986 |
+
#: view/bucket-setting.php:60
|
987 |
+
msgid "Block All Public Access Status Unknown"
|
988 |
+
msgstr ""
|
989 |
+
|
990 |
+
#: view/bucket-setting.php:61
|
991 |
+
msgid ""
|
992 |
+
"Public access to bucket status unknown, please grant IAM User the s3:"
|
993 |
+
"GetBucketPublicAccessBlock permission."
|
994 |
+
msgstr ""
|
995 |
+
|
996 |
+
#: view/bucket-setting.php:82
|
997 |
+
#, php-format
|
998 |
+
msgid ""
|
999 |
+
"<strong>Block All Public Access is Enabled</strong> — If you're "
|
1000 |
+
"following <a href=\"%1$s\">our documentation on setting up Amazon CloudFront "
|
1001 |
+
"for delivery</a>, you can ignore this warning and continue. If you're not "
|
1002 |
+
"planning on using Amazon CloudFront for delivery, you need to <a href=\"%2$s"
|
1003 |
+
"\">disable Block All Public Access</a>."
|
1004 |
+
msgstr ""
|
1005 |
+
|
1006 |
+
#: view/bucket-setting.php:114
|
1007 |
+
#, php-format
|
1008 |
+
msgid ""
|
1009 |
+
"<strong>Bucket Select Disabled</strong> — <a href=\"%s\">Define your "
|
1010 |
+
"access keys</a> to configure the bucket"
|
1011 |
msgstr ""
|
1012 |
|
1013 |
#: view/debug-info.php:2
|
1019 |
msgid "Download"
|
1020 |
msgstr ""
|
1021 |
|
1022 |
+
#: view/delivery-domain-setting.php:10
|
1023 |
+
msgid "Invalid character. Letters, numbers, periods and hyphens are allowed."
|
1024 |
msgstr ""
|
1025 |
|
1026 |
+
#: view/delivery-provider-select.php:19
|
1027 |
+
msgid "How would you like to deliver your media?"
|
1028 |
msgstr ""
|
1029 |
|
1030 |
+
#: view/delivery-provider-select.php:154
|
1031 |
+
msgid "CDN Name"
|
1032 |
msgstr ""
|
1033 |
|
1034 |
+
#: view/delivery-provider-select.php:189
|
1035 |
+
msgid "Save Delivery Provider"
|
1036 |
msgstr ""
|
1037 |
|
1038 |
+
#: view/delivery-provider-setting.php:12
|
1039 |
+
#: view/provider-setting.php:12
|
1040 |
+
msgid "Provider:"
|
1041 |
msgstr ""
|
1042 |
|
1043 |
+
#: view/enable-delivery-domain-setting.php:15
|
1044 |
msgid "Custom Domain (CNAME)"
|
1045 |
msgstr ""
|
1046 |
|
1047 |
+
#: view/enable-delivery-domain-setting.php:17
|
1048 |
#, php-format
|
1049 |
msgid ""
|
1050 |
+
"We strongly recommend you configure a subdomain of %1$s to point at your "
|
1051 |
+
"%2$s distribution. If you don't enter a subdomain of your site's domain in "
|
1052 |
+
"the field below it will negatively impact your site's SEO."
|
1053 |
+
msgstr ""
|
1054 |
+
|
1055 |
+
#: view/enable-signed-urls-setting.php:18
|
1056 |
+
msgid "Private Media"
|
1057 |
+
msgstr ""
|
1058 |
+
|
1059 |
+
#: view/enable-signed-urls-setting.php:20
|
1060 |
+
msgid ""
|
1061 |
+
"You can prevent public access to certain media files by enabling this option "
|
1062 |
+
"and the files will only be accessibly via signed URLs."
|
1063 |
msgstr ""
|
1064 |
|
1065 |
#: view/error-access.php:4
|
1201 |
msgstr ""
|
1202 |
|
1203 |
#: view/provider-select.php:373
|
1204 |
+
#: view/settings/media.php:315
|
|
|
|
|
|
|
|
|
1205 |
msgid "Save Changes"
|
1206 |
msgstr ""
|
1207 |
|
|
|
|
|
|
|
|
|
1208 |
#: view/settings/addons.php:10
|
1209 |
#, php-format
|
1210 |
msgid ""
|
1213 |
"\">deliciousbrains.com</a> to purchase in just a few clicks."
|
1214 |
msgstr ""
|
1215 |
|
1216 |
+
#: view/settings/media.php:108
|
1217 |
#, php-format
|
1218 |
msgid ""
|
1219 |
"Yikes! That's not a very SEO-friendly URL. We strongly recommend you "
|
1221 |
"point at your CDN. %2$s"
|
1222 |
msgstr ""
|
1223 |
|
1224 |
+
#: view/settings/media.php:124
|
1225 |
msgid "Storage"
|
1226 |
msgstr ""
|
1227 |
|
1228 |
+
#: view/settings/media.php:152
|
1229 |
msgid "Copy Files to Bucket"
|
1230 |
msgstr ""
|
1231 |
|
1232 |
+
#: view/settings/media.php:154
|
1233 |
msgid "When a file is uploaded to the Media Library, copy it to the bucket."
|
1234 |
msgstr ""
|
1235 |
|
1236 |
+
#: view/settings/media.php:169
|
1237 |
msgid "Path"
|
1238 |
msgstr ""
|
1239 |
|
1240 |
+
#: view/settings/media.php:171
|
1241 |
msgid "By default the path is the same as your local WordPress files."
|
1242 |
msgstr ""
|
1243 |
|
1244 |
+
#: view/settings/media.php:189
|
1245 |
+
#: view/settings/media.php:194
|
1246 |
msgid "Year/Month"
|
1247 |
msgstr ""
|
1248 |
|
1249 |
+
#: view/settings/media.php:191
|
1250 |
msgid ""
|
1251 |
"Add the Year/Month to the end of the path above just like WordPress does by "
|
1252 |
"default."
|
1253 |
msgstr ""
|
1254 |
|
1255 |
+
#: view/settings/media.php:205
|
1256 |
+
#: view/settings/media.php:210
|
1257 |
msgid "Object Versioning"
|
1258 |
msgstr ""
|
1259 |
|
1260 |
+
#: view/settings/media.php:207
|
1261 |
msgid ""
|
1262 |
"Append a timestamp to the file's bucket path. Recommended when using a CDN "
|
1263 |
"so you don't have to worry about cache invalidation."
|
1264 |
msgstr ""
|
1265 |
|
1266 |
+
#: view/settings/media.php:216
|
1267 |
+
msgid "Delivery"
|
1268 |
msgstr ""
|
1269 |
|
1270 |
+
#: view/settings/media.php:234
|
1271 |
msgid "Rewrite Media URLs"
|
1272 |
msgstr ""
|
1273 |
|
1274 |
+
#: view/settings/media.php:236
|
1275 |
+
#, php-format
|
1276 |
msgid ""
|
1277 |
"For Media Library files that have been copied to your bucket, rewrite the "
|
1278 |
+
"URLs so that they are served from %s instead of your server."
|
1279 |
msgstr ""
|
1280 |
|
1281 |
+
#: view/settings/media.php:261
|
1282 |
msgid "Force HTTPS"
|
1283 |
msgstr ""
|
1284 |
|
1285 |
+
#: view/settings/media.php:263
|
1286 |
msgid ""
|
1287 |
"By default we use HTTPS when the request is HTTPS and regular HTTP when the "
|
1288 |
"request is HTTP, but you may want to force the use of HTTPS always, "
|
1289 |
"regardless of the request."
|
1290 |
msgstr ""
|
1291 |
|
1292 |
+
#: view/settings/media.php:271
|
1293 |
msgid "Advanced Options"
|
1294 |
msgstr ""
|
1295 |
|
1296 |
+
#: view/settings/media.php:281
|
1297 |
msgid "Remove Files From Server"
|
1298 |
msgstr ""
|
1299 |
|
1300 |
+
#: view/settings/media.php:282
|
1301 |
msgid ""
|
1302 |
"Once a file has been copied to the bucket, remove it from the local server."
|
1303 |
msgstr ""
|
1304 |
|
1305 |
+
#: view/settings/media.php:286
|
1306 |
msgid ""
|
1307 |
"<strong>Broken URLs</strong> — There will be broken URLs for files "
|
1308 |
"that don't exist locally. You can fix this by enabling <strong>Rewrite Media "
|
1309 |
"URLs</strong> to use the offloaded media."
|
1310 |
msgstr ""
|
1311 |
|
1312 |
+
#: view/settings/media.php:297
|
1313 |
#, php-format
|
1314 |
msgid ""
|
1315 |
"<strong>Warning</strong> — Some plugins depend on the file being "
|
1316 |
"present on the local server and may not work when the file is removed. %s"
|
1317 |
msgstr ""
|
1318 |
|
1319 |
+
#: view/settings/media.php:299
|
1320 |
msgid ""
|
1321 |
"If you have a backup system in place (as you should) that backs up your site "
|
1322 |
"files, media, and database, your media will no longer be backed up as it "
|
1323 |
"will no longer be present on the filesystem."
|
1324 |
msgstr ""
|
1325 |
|
1326 |
+
#: view/settings/media.php:327
|
1327 |
#, php-format
|
1328 |
msgid ""
|
1329 |
"Need help getting your Access Keys? <a href=\"%s\">Check out the Quick Start "
|
1351 |
msgstr ""
|
1352 |
|
1353 |
#: view/sidebar.php:18
|
1354 |
+
msgid "Priority email support"
|
1355 |
msgstr ""
|
1356 |
|
1357 |
#: view/sidebar.php:25
|
1391 |
"unsubscribe with 1-click anytime."
|
1392 |
msgstr ""
|
1393 |
|
1394 |
+
#: view/signed-urls-setting.php:41
|
1395 |
+
msgid "Invalid character. Letters and numbers are allowed."
|
1396 |
+
msgstr ""
|
1397 |
+
|
1398 |
+
#: view/signed-urls-setting.php:72
|
1399 |
+
msgid ""
|
1400 |
+
"Invalid character. Letters, numbers, periods, hyphens, colons, spaces and "
|
1401 |
+
"slashes are allowed."
|
1402 |
+
msgstr ""
|
1403 |
+
|
1404 |
+
#: view/signed-urls-setting.php:103
|
1405 |
+
msgid ""
|
1406 |
+
"Invalid character. Letters, numbers, hyphens, spaces and forward slashes are "
|
1407 |
+
"allowed."
|
1408 |
+
msgstr ""
|
1409 |
+
|
1410 |
#: view/wordpress-org-support.php:2
|
1411 |
msgid "As this is a free plugin, we do not provide support."
|
1412 |
msgstr ""
|
@@ -2,9 +2,9 @@
|
|
2 |
Contributors: bradt, deliciousbrains, ianmjones
|
3 |
Tags: uploads, amazon, s3, amazon s3, digitalocean, digitalocean spaces, google cloud storage, gcs, mirror, admin, media, cdn, cloudfront
|
4 |
Requires at least: 4.9
|
5 |
-
Tested up to: 5.
|
6 |
Requires PHP: 5.5
|
7 |
-
Stable tag: 2.
|
8 |
License: GPLv3
|
9 |
|
10 |
Copies files to Amazon S3, DigitalOcean Spaces or Google Cloud Storage as they are uploaded to the Media Library. Optionally configure Amazon CloudFront or another CDN for faster delivery.
|
@@ -32,7 +32,7 @@ Although WP Offload Media doesn't include image optimization features, we work c
|
|
32 |
* [Assets Pull addon](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=assets%2Baddon#addons) - Serve your CSS, JS and fonts via CloudFront or another CDN
|
33 |
* [WooCommerce integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=woocommerce%2Baddon#integrations)
|
34 |
* [Easy Digital Downloads integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=edd%2Baddon#integrations)
|
35 |
-
*
|
36 |
|
37 |
[Compare pro vs free →](https://deliciousbrains.com/wp-offload-media/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
|
38 |
|
@@ -81,6 +81,34 @@ This version requires PHP 5.3.3+ and the Amazon Web Services plugin
|
|
81 |
|
82 |
== Changelog ==
|
83 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
= WP Offload Media Lite 2.3.2 - 2019-12-09 =
|
85 |
* Improvement: Reduced database queries when external object cache available
|
86 |
* Bug fix: Uncaught Error: Call to undefined function DeliciousBrains\WP_Offload_Media\Gcp\GuzzleHttp\choose_handler()
|
2 |
Contributors: bradt, deliciousbrains, ianmjones
|
3 |
Tags: uploads, amazon, s3, amazon s3, digitalocean, digitalocean spaces, google cloud storage, gcs, mirror, admin, media, cdn, cloudfront
|
4 |
Requires at least: 4.9
|
5 |
+
Tested up to: 5.5
|
6 |
Requires PHP: 5.5
|
7 |
+
Stable tag: 2.4
|
8 |
License: GPLv3
|
9 |
|
10 |
Copies files to Amazon S3, DigitalOcean Spaces or Google Cloud Storage as they are uploaded to the Media Library. Optionally configure Amazon CloudFront or another CDN for faster delivery.
|
32 |
* [Assets Pull addon](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=assets%2Baddon#addons) - Serve your CSS, JS and fonts via CloudFront or another CDN
|
33 |
* [WooCommerce integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=woocommerce%2Baddon#integrations)
|
34 |
* [Easy Digital Downloads integration](https://deliciousbrains.com/wp-offload-media/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=edd%2Baddon#integrations)
|
35 |
+
* Priority email support
|
36 |
|
37 |
[Compare pro vs free →](https://deliciousbrains.com/wp-offload-media/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
|
38 |
|
81 |
|
82 |
== Changelog ==
|
83 |
|
84 |
+
= WP Offload Media Lite 2.4 - 2020-07-14 =
|
85 |
+
* [Release Summary Blog Post](https://deliciousbrains.com/wp-offload-media-2-4-released/?utm_campaign=changelogs&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
|
86 |
+
* New: Setting to choose a Delivery Provider (i.e. S3, CloudFront, another CDN)
|
87 |
+
* New: Support for Block All Public Access setting on S3 buckets
|
88 |
+
* New: Raw S3 URLs use bucket in domain rather than path where possible as per changes required by AWS
|
89 |
+
* New: Raw S3 URLs use dot rather than dash between s3 and region name as per changes required by AWS
|
90 |
+
* New: Added S3 regions for Africa (Cape Town), Asia Pacific (Hong Kong), EU (Milan), EU (Stockholm), and Middle East (Bahrain)
|
91 |
+
* New: Added GCS regions for Salt Lake City, Las Vegas, Zürich, Osaka, Seoul, EUR4 (dual-region), and NAM4 (dual-region)
|
92 |
+
* Improvement: Updated AWS PHP SDK to v3.133.40
|
93 |
+
* Improvement: Updated Google Cloud Storage SDK to v1.18.0
|
94 |
+
* Improvement: S3 regions for China no longer hidden (configuration via AWS Console still required)
|
95 |
+
* Bug fix: Private images not showing in grid mode Media page overlay
|
96 |
+
* Bug fix: Public image thumbnails not showing in grid mode Media page when original is private
|
97 |
+
* Bug fix: URL rewriting sometimes fails for sites hosted on Windows
|
98 |
+
* Bug fix: URL rewrite fails for image when original upload has size in file name
|
99 |
+
* Bug fix: External URLs rewritten to local URLs when they shouldn't
|
100 |
+
* Bug fix: StreamWrappers don't work with private buckets
|
101 |
+
* Bug fix: Database error when inserting media library item and using HyperDB
|
102 |
+
* Bug fix: S3 bucket link in settings no longer goes direct to bucket contents
|
103 |
+
* Bug fix: New uploads slow with very large Media Library
|
104 |
+
* Bug fix: Migration to custom table very slow with large postmeta tables
|
105 |
+
* Bug fix: Signed GCS URLs have incorrect expires value
|
106 |
+
* Bug fix: The use-server-roles AS3CF_SETTINGS value is not properly reflected in Diagnostic Info
|
107 |
+
* Bug fix: Unknown column '2019/12/some-file-name.pdf' in 'where clause' when using managed MySQL on DigitalOcean
|
108 |
+
* Bug fix: WordPress database error Expression #1 of ORDER BY clause is not in SELECT list when using MySQL8
|
109 |
+
* Bug fix: WordPress forces HTTP in Edit Media page if site is not HTTPS, breaking remote URLs that require HTTPS
|
110 |
+
* Tested: WordPress 5.5
|
111 |
+
|
112 |
= WP Offload Media Lite 2.3.2 - 2019-12-09 =
|
113 |
* Improvement: Reduced database queries when external object cache available
|
114 |
* Bug fix: Uncaught Error: Call to undefined function DeliciousBrains\WP_Offload_Media\Gcp\GuzzleHttp\choose_handler()
|
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
6 |
+
/**
|
7 |
+
* A configuration provider is a function that returns a promise that is
|
8 |
+
* fulfilled with a configuration object. This class provides base functionality
|
9 |
+
* usable by specific configuration provider implementations
|
10 |
+
*/
|
11 |
+
abstract class AbstractConfigurationProvider
|
12 |
+
{
|
13 |
+
const ENV_PROFILE = 'AWS_PROFILE';
|
14 |
+
const ENV_CONFIG_FILE = 'AWS_CONFIG_FILE';
|
15 |
+
public static $cacheKey;
|
16 |
+
protected static $interfaceClass;
|
17 |
+
protected static $exceptionClass;
|
18 |
+
/**
|
19 |
+
* Wraps a config provider and saves provided configuration in an
|
20 |
+
* instance of Aws\CacheInterface. Forwards calls when no config found
|
21 |
+
* in cache and updates cache with the results.
|
22 |
+
*
|
23 |
+
* @param callable $provider Configuration provider function to wrap
|
24 |
+
* @param CacheInterface $cache Cache to store configuration
|
25 |
+
* @param string|null $cacheKey (optional) Cache key to use
|
26 |
+
*
|
27 |
+
* @return callable
|
28 |
+
*/
|
29 |
+
public static function cache(callable $provider, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface $cache, $cacheKey = null)
|
30 |
+
{
|
31 |
+
$cacheKey = $cacheKey ?: static::$cacheKey;
|
32 |
+
return function () use($provider, $cache, $cacheKey) {
|
33 |
+
$found = $cache->get($cacheKey);
|
34 |
+
if ($found instanceof static::$interfaceClass) {
|
35 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for($found);
|
36 |
+
}
|
37 |
+
return $provider()->then(function ($config) use($cache, $cacheKey) {
|
38 |
+
$cache->set($cacheKey, $config);
|
39 |
+
return $config;
|
40 |
+
});
|
41 |
+
};
|
42 |
+
}
|
43 |
+
/**
|
44 |
+
* Creates an aggregate configuration provider that invokes the provided
|
45 |
+
* variadic providers one after the other until a provider returns
|
46 |
+
* configuration.
|
47 |
+
*
|
48 |
+
* @return callable
|
49 |
+
*/
|
50 |
+
public static function chain()
|
51 |
+
{
|
52 |
+
$links = func_get_args();
|
53 |
+
if (empty($links)) {
|
54 |
+
throw new \InvalidArgumentException('No providers in chain');
|
55 |
+
}
|
56 |
+
return function () use($links) {
|
57 |
+
/** @var callable $parent */
|
58 |
+
$parent = array_shift($links);
|
59 |
+
$promise = $parent();
|
60 |
+
while ($next = array_shift($links)) {
|
61 |
+
$promise = $promise->otherwise($next);
|
62 |
+
}
|
63 |
+
return $promise;
|
64 |
+
};
|
65 |
+
}
|
66 |
+
/**
|
67 |
+
* Gets the environment's HOME directory if available.
|
68 |
+
*
|
69 |
+
* @return null|string
|
70 |
+
*/
|
71 |
+
protected static function getHomeDir()
|
72 |
+
{
|
73 |
+
// On Linux/Unix-like systems, use the HOME environment variable
|
74 |
+
if ($homeDir = getenv('HOME')) {
|
75 |
+
return $homeDir;
|
76 |
+
}
|
77 |
+
// Get the HOMEDRIVE and HOMEPATH values for Windows hosts
|
78 |
+
$homeDrive = getenv('HOMEDRIVE');
|
79 |
+
$homePath = getenv('HOMEPATH');
|
80 |
+
return $homeDrive && $homePath ? $homeDrive . $homePath : null;
|
81 |
+
}
|
82 |
+
/**
|
83 |
+
* Gets default config file location from environment, falling back to aws
|
84 |
+
* default location
|
85 |
+
*
|
86 |
+
* @return string
|
87 |
+
*/
|
88 |
+
protected static function getDefaultConfigFilename()
|
89 |
+
{
|
90 |
+
if ($filename = getenv(self::ENV_CONFIG_FILE)) {
|
91 |
+
return $filename;
|
92 |
+
}
|
93 |
+
return self::getHomeDir() . '/.aws/config';
|
94 |
+
}
|
95 |
+
/**
|
96 |
+
* Wraps a config provider and caches previously provided configuration.
|
97 |
+
*
|
98 |
+
* @param callable $provider Config provider function to wrap.
|
99 |
+
*
|
100 |
+
* @return callable
|
101 |
+
*/
|
102 |
+
public static function memoize(callable $provider)
|
103 |
+
{
|
104 |
+
return function () use($provider) {
|
105 |
+
static $result;
|
106 |
+
static $isConstant;
|
107 |
+
// Constant config will be returned constantly.
|
108 |
+
if ($isConstant) {
|
109 |
+
return $result;
|
110 |
+
}
|
111 |
+
// Create the initial promise that will be used as the cached value
|
112 |
+
if (null === $result) {
|
113 |
+
$result = $provider();
|
114 |
+
}
|
115 |
+
// Return config and set flag that provider is already set
|
116 |
+
return $result->then(function ($config) use(&$isConstant) {
|
117 |
+
$isConstant = true;
|
118 |
+
return $config;
|
119 |
+
});
|
120 |
+
};
|
121 |
+
}
|
122 |
+
/**
|
123 |
+
* Reject promise with standardized exception.
|
124 |
+
*
|
125 |
+
* @param $msg
|
126 |
+
* @return Promise\RejectedPromise
|
127 |
+
*/
|
128 |
+
protected static function reject($msg)
|
129 |
+
{
|
130 |
+
$exceptionClass = static::$exceptionClass;
|
131 |
+
return new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\RejectedPromise(new $exceptionClass($msg));
|
132 |
+
}
|
133 |
+
}
|
@@ -148,7 +148,7 @@ class ApiProvider
|
|
148 |
return array_values(array_unique($this->manifest[$service]['versions']));
|
149 |
}
|
150 |
/**
|
151 |
-
* Execute the
|
152 |
*
|
153 |
* @param string $type Type of data ('api', 'waiter', 'paginator').
|
154 |
* @param string $service Service name.
|
148 |
return array_values(array_unique($this->manifest[$service]['versions']));
|
149 |
}
|
150 |
/**
|
151 |
+
* Execute the provider.
|
152 |
*
|
153 |
* @param string $type Type of data ('api', 'waiter', 'paginator').
|
154 |
* @param string $service Service name.
|
@@ -94,7 +94,7 @@ class DocModel
|
|
94 |
if (!$content) {
|
95 |
return '';
|
96 |
}
|
97 |
-
$tidy = new \
|
98 |
$tidy->parseString($content, ['indent' => true, 'doctype' => 'omit', 'output-html' => true, 'show-body-only' => true, 'drop-empty-paras' => true, 'drop-font-tags' => true, 'drop-proprietary-attributes' => true, 'hide-comments' => true, 'logical-emphasis' => true]);
|
99 |
$tidy->cleanRepair();
|
100 |
return (string) $content;
|
94 |
if (!$content) {
|
95 |
return '';
|
96 |
}
|
97 |
+
$tidy = new \tidy();
|
98 |
$tidy->parseString($content, ['indent' => true, 'doctype' => 'omit', 'output-html' => true, 'show-body-only' => true, 'drop-empty-paras' => true, 'drop-font-tags' => true, 'drop-proprietary-attributes' => true, 'hide-comments' => true, 'logical-emphasis' => true]);
|
99 |
$tidy->cleanRepair();
|
100 |
return (string) $content;
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\MetadataParserTrait;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\PayloadParserTrait;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
|
10 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
11 |
+
abstract class AbstractErrorParser
|
12 |
+
{
|
13 |
+
use MetadataParserTrait;
|
14 |
+
use PayloadParserTrait;
|
15 |
+
/**
|
16 |
+
* @var Service
|
17 |
+
*/
|
18 |
+
protected $api;
|
19 |
+
/**
|
20 |
+
* @param Service $api
|
21 |
+
*/
|
22 |
+
public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api = null)
|
23 |
+
{
|
24 |
+
$this->api = $api;
|
25 |
+
}
|
26 |
+
protected abstract function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member);
|
27 |
+
protected function extractPayload(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
|
28 |
+
{
|
29 |
+
if ($member instanceof StructureShape) {
|
30 |
+
// Structure members parse top-level data into a specific key.
|
31 |
+
return $this->payload($response, $member);
|
32 |
+
} else {
|
33 |
+
// Streaming data is just the stream from the response body.
|
34 |
+
return $response->getBody();
|
35 |
+
}
|
36 |
+
}
|
37 |
+
protected function populateShape(array &$data, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command = null)
|
38 |
+
{
|
39 |
+
$data['body'] = [];
|
40 |
+
if (!empty($command) && !empty($this->api)) {
|
41 |
+
// If modeled error code is indicated, check for known error shape
|
42 |
+
if (!empty($data['code'])) {
|
43 |
+
$errors = $this->api->getOperation($command->getName())->getErrors();
|
44 |
+
foreach ($errors as $key => $error) {
|
45 |
+
// If error code matches a known error shape, populate the body
|
46 |
+
if ($data['code'] == $error['name'] && $error instanceof StructureShape) {
|
47 |
+
$modeledError = $error;
|
48 |
+
$data['body'] = $this->extractPayload($modeledError, $response);
|
49 |
+
foreach ($error->getMembers() as $name => $member) {
|
50 |
+
switch ($member['location']) {
|
51 |
+
case 'header':
|
52 |
+
$this->extractHeader($name, $member, $response, $data['body']);
|
53 |
+
break;
|
54 |
+
case 'headers':
|
55 |
+
$this->extractHeaders($name, $member, $response, $data['body']);
|
56 |
+
break;
|
57 |
+
case 'statusCode':
|
58 |
+
$this->extractStatus($name, $response, $data['body']);
|
59 |
+
break;
|
60 |
+
}
|
61 |
+
}
|
62 |
+
break;
|
63 |
+
}
|
64 |
+
}
|
65 |
+
}
|
66 |
+
}
|
67 |
+
return $data;
|
68 |
+
}
|
69 |
+
}
|
@@ -3,6 +3,7 @@
|
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
|
4 |
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\PayloadParserTrait;
|
|
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
7 |
/**
|
8 |
* Provides basic JSON error parsing functionality.
|
@@ -15,4 +16,11 @@ trait JsonParserTrait
|
|
15 |
$code = (string) $response->getStatusCode();
|
16 |
return ['request_id' => (string) $response->getHeaderLine('x-amzn-requestid'), 'code' => null, 'message' => null, 'type' => $code[0] == '4' ? 'client' : 'server', 'parsed' => $this->parseJson($response->getBody(), $response)];
|
17 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
}
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
|
4 |
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\PayloadParserTrait;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
8 |
/**
|
9 |
* Provides basic JSON error parsing functionality.
|
16 |
$code = (string) $response->getStatusCode();
|
17 |
return ['request_id' => (string) $response->getHeaderLine('x-amzn-requestid'), 'code' => null, 'message' => null, 'type' => $code[0] == '4' ? 'client' : 'server', 'parsed' => $this->parseJson($response->getBody(), $response)];
|
18 |
}
|
19 |
+
protected function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member)
|
20 |
+
{
|
21 |
+
$jsonBody = $this->parseJson($response->getBody(), $response);
|
22 |
+
if ($jsonBody) {
|
23 |
+
return $this->parser->parse($member, $jsonBody);
|
24 |
+
}
|
25 |
+
}
|
26 |
}
|
@@ -2,14 +2,23 @@
|
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
|
4 |
|
|
|
|
|
|
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
6 |
/**
|
7 |
* Parsers JSON-RPC errors.
|
8 |
*/
|
9 |
-
class JsonRpcErrorParser
|
10 |
{
|
11 |
use JsonParserTrait;
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
{
|
14 |
$data = $this->genericHandler($response);
|
15 |
// Make the casing consistent across services.
|
@@ -21,6 +30,7 @@ class JsonRpcErrorParser
|
|
21 |
$data['code'] = isset($parts[1]) ? $parts[1] : $parts[0];
|
22 |
$data['message'] = isset($data['parsed']['message']) ? $data['parsed']['message'] : null;
|
23 |
}
|
|
|
24 |
return $data;
|
25 |
}
|
26 |
}
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
|
4 |
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
9 |
/**
|
10 |
* Parsers JSON-RPC errors.
|
11 |
*/
|
12 |
+
class JsonRpcErrorParser extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser\AbstractErrorParser
|
13 |
{
|
14 |
use JsonParserTrait;
|
15 |
+
private $parser;
|
16 |
+
public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api = null, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser $parser = null)
|
17 |
+
{
|
18 |
+
parent::__construct($api);
|
19 |
+
$this->parser = $parser ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser();
|
20 |
+
}
|
21 |
+
public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command = null)
|
22 |
{
|
23 |
$data = $this->genericHandler($response);
|
24 |
// Make the casing consistent across services.
|
30 |
$data['code'] = isset($parts[1]) ? $parts[1] : $parts[0];
|
31 |
$data['message'] = isset($data['parsed']['message']) ? $data['parsed']['message'] : null;
|
32 |
}
|
33 |
+
$this->populateShape($data, $response, $command);
|
34 |
return $data;
|
35 |
}
|
36 |
}
|
@@ -2,14 +2,24 @@
|
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
|
4 |
|
|
|
|
|
|
|
|
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
6 |
/**
|
7 |
* Parses JSON-REST errors.
|
8 |
*/
|
9 |
-
class RestJsonErrorParser
|
10 |
{
|
11 |
use JsonParserTrait;
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
{
|
14 |
$data = $this->genericHandler($response);
|
15 |
// Merge in error data from the JSON body
|
@@ -25,6 +35,9 @@ class RestJsonErrorParser
|
|
25 |
$colon = strpos($code, ':');
|
26 |
$data['code'] = $colon ? substr($code, 0, $colon) : $code;
|
27 |
}
|
|
|
|
|
|
|
28 |
return $data;
|
29 |
}
|
30 |
}
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
|
4 |
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
10 |
/**
|
11 |
* Parses JSON-REST errors.
|
12 |
*/
|
13 |
+
class RestJsonErrorParser extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser\AbstractErrorParser
|
14 |
{
|
15 |
use JsonParserTrait;
|
16 |
+
private $parser;
|
17 |
+
public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api = null, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser $parser = null)
|
18 |
+
{
|
19 |
+
parent::__construct($api);
|
20 |
+
$this->parser = $parser ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser();
|
21 |
+
}
|
22 |
+
public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command = null)
|
23 |
{
|
24 |
$data = $this->genericHandler($response);
|
25 |
// Merge in error data from the JSON body
|
35 |
$colon = strpos($code, ':');
|
36 |
$data['code'] = $colon ? substr($code, 0, $colon) : $code;
|
37 |
}
|
38 |
+
// Retrieve error message directly
|
39 |
+
$data['message'] = isset($data['parsed']['message']) ? $data['parsed']['message'] : (isset($data['parsed']['Message']) ? $data['parsed']['Message'] : null);
|
40 |
+
$this->populateShape($data, $response, $command);
|
41 |
return $data;
|
42 |
}
|
43 |
}
|
@@ -3,14 +3,24 @@
|
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
|
4 |
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\PayloadParserTrait;
|
|
|
|
|
|
|
|
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
7 |
/**
|
8 |
* Parses XML errors.
|
9 |
*/
|
10 |
-
class XmlErrorParser
|
11 |
{
|
12 |
use PayloadParserTrait;
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
{
|
15 |
$code = (string) $response->getStatusCode();
|
16 |
$data = ['type' => $code[0] == '4' ? 'client' : 'server', 'request_id' => null, 'code' => null, 'message' => null, 'parsed' => null];
|
@@ -20,6 +30,7 @@ class XmlErrorParser
|
|
20 |
} else {
|
21 |
$this->parseHeaders($response, $data);
|
22 |
}
|
|
|
23 |
return $data;
|
24 |
}
|
25 |
private function parseHeaders(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, array &$data)
|
@@ -36,15 +47,7 @@ class XmlErrorParser
|
|
36 |
private function parseBody(\SimpleXMLElement $body, array &$data)
|
37 |
{
|
38 |
$data['parsed'] = $body;
|
39 |
-
$
|
40 |
-
if (!isset($namespaces[''])) {
|
41 |
-
$prefix = '';
|
42 |
-
} else {
|
43 |
-
// Account for the default namespace being defined and PHP not
|
44 |
-
// being able to handle it :(.
|
45 |
-
$body->registerXPathNamespace('ns', $namespaces['']);
|
46 |
-
$prefix = 'ns:';
|
47 |
-
}
|
48 |
if ($tempXml = $body->xpath("//{$prefix}Code[1]")) {
|
49 |
$data['code'] = (string) $tempXml[0];
|
50 |
}
|
@@ -52,11 +55,28 @@ class XmlErrorParser
|
|
52 |
$data['message'] = (string) $tempXml[0];
|
53 |
}
|
54 |
$tempXml = $body->xpath("//{$prefix}RequestId[1]");
|
55 |
-
if (empty($tempXml)) {
|
56 |
-
$tempXml = $body->xpath("//{$prefix}RequestID[1]");
|
57 |
-
}
|
58 |
if (isset($tempXml[0])) {
|
59 |
$data['request_id'] = (string) $tempXml[0];
|
60 |
}
|
61 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
}
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser;
|
4 |
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\PayloadParserTrait;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\XmlParser;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
|
10 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
11 |
/**
|
12 |
* Parses XML errors.
|
13 |
*/
|
14 |
+
class XmlErrorParser extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ErrorParser\AbstractErrorParser
|
15 |
{
|
16 |
use PayloadParserTrait;
|
17 |
+
protected $parser;
|
18 |
+
public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api = null, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\XmlParser $parser = null)
|
19 |
+
{
|
20 |
+
parent::__construct($api);
|
21 |
+
$this->parser = $parser ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\XmlParser();
|
22 |
+
}
|
23 |
+
public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command = null)
|
24 |
{
|
25 |
$code = (string) $response->getStatusCode();
|
26 |
$data = ['type' => $code[0] == '4' ? 'client' : 'server', 'request_id' => null, 'code' => null, 'message' => null, 'parsed' => null];
|
30 |
} else {
|
31 |
$this->parseHeaders($response, $data);
|
32 |
}
|
33 |
+
$this->populateShape($data, $response, $command);
|
34 |
return $data;
|
35 |
}
|
36 |
private function parseHeaders(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, array &$data)
|
47 |
private function parseBody(\SimpleXMLElement $body, array &$data)
|
48 |
{
|
49 |
$data['parsed'] = $body;
|
50 |
+
$prefix = $this->registerNamespacePrefix($body);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
if ($tempXml = $body->xpath("//{$prefix}Code[1]")) {
|
52 |
$data['code'] = (string) $tempXml[0];
|
53 |
}
|
55 |
$data['message'] = (string) $tempXml[0];
|
56 |
}
|
57 |
$tempXml = $body->xpath("//{$prefix}RequestId[1]");
|
|
|
|
|
|
|
58 |
if (isset($tempXml[0])) {
|
59 |
$data['request_id'] = (string) $tempXml[0];
|
60 |
}
|
61 |
}
|
62 |
+
protected function registerNamespacePrefix(\SimpleXMLElement $element)
|
63 |
+
{
|
64 |
+
$namespaces = $element->getDocNamespaces();
|
65 |
+
if (!isset($namespaces[''])) {
|
66 |
+
return '';
|
67 |
+
}
|
68 |
+
// Account for the default namespace being defined and PHP not
|
69 |
+
// being able to handle it :(.
|
70 |
+
$element->registerXPathNamespace('ns', $namespaces['']);
|
71 |
+
return 'ns:';
|
72 |
+
}
|
73 |
+
protected function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member)
|
74 |
+
{
|
75 |
+
$xmlBody = $this->parseXml($response->getBody(), $response);
|
76 |
+
$prefix = $this->registerNamespacePrefix($xmlBody);
|
77 |
+
$errorBody = $xmlBody->xpath("//{$prefix}Error");
|
78 |
+
if (is_array($errorBody) && !empty($errorBody[0])) {
|
79 |
+
return $this->parser->parse($member, $errorBody[0]);
|
80 |
+
}
|
81 |
+
}
|
82 |
}
|
@@ -99,10 +99,20 @@ abstract class AbstractRestParser extends \DeliciousBrains\WP_Offload_Media\Aws3
|
|
99 |
return;
|
100 |
}
|
101 |
case 'string':
|
102 |
-
|
103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
}
|
105 |
-
break;
|
106 |
}
|
107 |
$result[$name] = $value;
|
108 |
}
|
99 |
return;
|
100 |
}
|
101 |
case 'string':
|
102 |
+
try {
|
103 |
+
if ($shape['jsonvalue']) {
|
104 |
+
$value = $this->parseJson(base64_decode($value), $response);
|
105 |
+
}
|
106 |
+
// If value is not set, do not add to output structure.
|
107 |
+
if (!isset($value)) {
|
108 |
+
return;
|
109 |
+
}
|
110 |
+
break;
|
111 |
+
} catch (\Exception $e) {
|
112 |
+
//If the value cannot be parsed, then do not add it to the
|
113 |
+
//output structure.
|
114 |
+
return;
|
115 |
}
|
|
|
116 |
}
|
117 |
$result[$name] = $value;
|
118 |
}
|
@@ -29,7 +29,7 @@ class DecodingEventStreamIterator implements \Iterator
|
|
29 |
private $currentEvent;
|
30 |
/** @var int Current in-order event key. */
|
31 |
private $key;
|
32 |
-
/** @var resource
|
33 |
private $hashContext;
|
34 |
/** @var int $currentPosition */
|
35 |
private $currentPosition;
|
29 |
private $currentEvent;
|
30 |
/** @var int Current in-order event key. */
|
31 |
private $key;
|
32 |
+
/** @var resource|\HashContext CRC32 hash context for event validation */
|
33 |
private $hashContext;
|
34 |
/** @var int $currentPosition */
|
35 |
private $currentPosition;
|
@@ -5,15 +5,38 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\Exception;
|
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface;
|
|
|
8 |
class ParserException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface
|
9 |
{
|
10 |
use HasMonitoringEventsTrait;
|
|
|
|
|
11 |
private $response;
|
12 |
public function __construct($message = '', $code = 0, $previous = null, array $context = [])
|
13 |
{
|
|
|
|
|
14 |
$this->response = isset($context['response']) ? $context['response'] : null;
|
15 |
parent::__construct($message, $code, $previous);
|
16 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
/**
|
18 |
* Get the received HTTP response if any.
|
19 |
*
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
9 |
class ParserException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface
|
10 |
{
|
11 |
use HasMonitoringEventsTrait;
|
12 |
+
private $errorCode;
|
13 |
+
private $requestId;
|
14 |
private $response;
|
15 |
public function __construct($message = '', $code = 0, $previous = null, array $context = [])
|
16 |
{
|
17 |
+
$this->errorCode = isset($context['error_code']) ? $context['error_code'] : null;
|
18 |
+
$this->requestId = isset($context['request_id']) ? $context['request_id'] : null;
|
19 |
$this->response = isset($context['response']) ? $context['response'] : null;
|
20 |
parent::__construct($message, $code, $previous);
|
21 |
}
|
22 |
+
/**
|
23 |
+
* Get the error code, if any.
|
24 |
+
*
|
25 |
+
* @return string|null
|
26 |
+
*/
|
27 |
+
public function getErrorCode()
|
28 |
+
{
|
29 |
+
return $this->errorCode;
|
30 |
+
}
|
31 |
+
/**
|
32 |
+
* Get the request ID, if any.
|
33 |
+
*
|
34 |
+
* @return string|null
|
35 |
+
*/
|
36 |
+
public function getRequestId()
|
37 |
+
{
|
38 |
+
return $this->requestId;
|
39 |
+
}
|
40 |
/**
|
41 |
* Get the received HTTP response if any.
|
42 |
*
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
8 |
+
trait MetadataParserTrait
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Extract a single header from the response into the result.
|
12 |
+
*/
|
13 |
+
protected function extractHeader($name, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, &$result)
|
14 |
+
{
|
15 |
+
$value = $response->getHeaderLine($shape['locationName'] ?: $name);
|
16 |
+
switch ($shape->getType()) {
|
17 |
+
case 'float':
|
18 |
+
case 'double':
|
19 |
+
$value = (double) $value;
|
20 |
+
break;
|
21 |
+
case 'long':
|
22 |
+
$value = (int) $value;
|
23 |
+
break;
|
24 |
+
case 'boolean':
|
25 |
+
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
|
26 |
+
break;
|
27 |
+
case 'blob':
|
28 |
+
$value = base64_decode($value);
|
29 |
+
break;
|
30 |
+
case 'timestamp':
|
31 |
+
try {
|
32 |
+
if (!empty($shape['timestampFormat']) && $shape['timestampFormat'] === 'unixTimestamp') {
|
33 |
+
$value = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult::fromEpoch($value);
|
34 |
+
}
|
35 |
+
$value = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult($value);
|
36 |
+
break;
|
37 |
+
} catch (\Exception $e) {
|
38 |
+
// If the value cannot be parsed, then do not add it to the
|
39 |
+
// output structure.
|
40 |
+
return;
|
41 |
+
}
|
42 |
+
case 'string':
|
43 |
+
if ($shape['jsonvalue']) {
|
44 |
+
$value = $this->parseJson(base64_decode($value), $response);
|
45 |
+
}
|
46 |
+
break;
|
47 |
+
}
|
48 |
+
$result[$name] = $value;
|
49 |
+
}
|
50 |
+
/**
|
51 |
+
* Extract a map of headers with an optional prefix from the response.
|
52 |
+
*/
|
53 |
+
protected function extractHeaders($name, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, &$result)
|
54 |
+
{
|
55 |
+
// Check if the headers are prefixed by a location name
|
56 |
+
$result[$name] = [];
|
57 |
+
$prefix = $shape['locationName'];
|
58 |
+
$prefixLen = strlen($prefix);
|
59 |
+
foreach ($response->getHeaders() as $k => $values) {
|
60 |
+
if (!$prefixLen) {
|
61 |
+
$result[$name][$k] = implode(', ', $values);
|
62 |
+
} elseif (stripos($k, $prefix) === 0) {
|
63 |
+
$result[$name][substr($k, $prefixLen)] = implode(', ', $values);
|
64 |
+
}
|
65 |
+
}
|
66 |
+
}
|
67 |
+
/**
|
68 |
+
* Places the status code of the response into the result array.
|
69 |
+
*/
|
70 |
+
protected function extractStatus($name, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, array &$result)
|
71 |
+
{
|
72 |
+
$result[$name] = (int) $response->getStatusCode();
|
73 |
+
}
|
74 |
+
}
|
@@ -28,7 +28,7 @@ trait PayloadParserTrait
|
|
28 |
*
|
29 |
* @return \SimpleXMLElement
|
30 |
*/
|
31 |
-
|
32 |
{
|
33 |
$priorSetting = libxml_use_internal_errors(true);
|
34 |
try {
|
28 |
*
|
29 |
* @return \SimpleXMLElement
|
30 |
*/
|
31 |
+
protected function parseXml($xml, $response)
|
32 |
{
|
33 |
$priorSetting = libxml_use_internal_errors(true);
|
34 |
try {
|
@@ -33,6 +33,11 @@ class XmlParser
|
|
33 |
$node = $this->memberKey($member, $name);
|
34 |
if (isset($value->{$node})) {
|
35 |
$target[$name] = $this->dispatch($member, $value->{$node});
|
|
|
|
|
|
|
|
|
|
|
36 |
}
|
37 |
}
|
38 |
return $target;
|
@@ -99,4 +104,15 @@ class XmlParser
|
|
99 |
}
|
100 |
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult($value);
|
101 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
}
|
33 |
$node = $this->memberKey($member, $name);
|
34 |
if (isset($value->{$node})) {
|
35 |
$target[$name] = $this->dispatch($member, $value->{$node});
|
36 |
+
} else {
|
37 |
+
$memberShape = $shape->getMember($name);
|
38 |
+
if (!empty($memberShape['xmlAttribute'])) {
|
39 |
+
$target[$name] = $this->parse_xml_attribute($shape, $memberShape, $value);
|
40 |
+
}
|
41 |
}
|
42 |
}
|
43 |
return $target;
|
104 |
}
|
105 |
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult($value);
|
106 |
}
|
107 |
+
private function parse_xml_attribute(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $memberShape, $value)
|
108 |
+
{
|
109 |
+
$namespace = $shape['xmlNamespace']['uri'] ? $shape['xmlNamespace']['uri'] : '';
|
110 |
+
$prefix = $shape['xmlNamespace']['prefix'] ? $shape['xmlNamespace']['prefix'] : '';
|
111 |
+
if (!empty($prefix)) {
|
112 |
+
$prefix .= ':';
|
113 |
+
}
|
114 |
+
$key = str_replace($prefix, '', $memberShape['locationName']);
|
115 |
+
$attributes = $value->attributes($namespace);
|
116 |
+
return isset($attributes[$key]) ? (string) $attributes[$key] : null;
|
117 |
+
}
|
118 |
}
|
@@ -22,7 +22,7 @@ class RestJsonSerializer extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\
|
|
22 |
public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, $endpoint, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody $jsonFormatter = null)
|
23 |
{
|
24 |
parent::__construct($api, $endpoint);
|
25 |
-
$this->contentType =
|
26 |
$this->jsonFormatter = $jsonFormatter ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody($api);
|
27 |
}
|
28 |
protected function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member, array $value, array &$opts)
|
22 |
public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, $endpoint, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody $jsonFormatter = null)
|
23 |
{
|
24 |
parent::__construct($api, $endpoint);
|
25 |
+
$this->contentType = 'application/json';
|
26 |
$this->jsonFormatter = $jsonFormatter ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody($api);
|
27 |
}
|
28 |
protected function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member, array $value, array &$opts)
|
@@ -160,6 +160,11 @@ abstract class RestSerializer
|
|
160 |
$append = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\build_query($opts['query']);
|
161 |
$relative .= strpos($relative, '?') ? "&{$append}" : "?{$append}";
|
162 |
}
|
|
|
|
|
|
|
|
|
|
|
163 |
// Expand path place holders using Amazon's slightly different URI
|
164 |
// template syntax.
|
165 |
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\UriResolver::resolve($this->endpoint, new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri($relative));
|
160 |
$append = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\build_query($opts['query']);
|
161 |
$relative .= strpos($relative, '?') ? "&{$append}" : "?{$append}";
|
162 |
}
|
163 |
+
// If endpoint has path, remove leading '/' to preserve URI resolution.
|
164 |
+
$path = $this->endpoint->getPath();
|
165 |
+
if ($path && $relative[0] === '/') {
|
166 |
+
$relative = substr($relative, 1);
|
167 |
+
}
|
168 |
// Expand path place holders using Amazon's slightly different URI
|
169 |
// template syntax.
|
170 |
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\UriResolver::resolve($this->endpoint, new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri($relative));
|
@@ -61,7 +61,7 @@ class XmlBody
|
|
61 |
private function defaultShape(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
|
62 |
{
|
63 |
$this->startElement($shape, $name, $xml);
|
64 |
-
$xml->
|
65 |
$xml->endElement();
|
66 |
}
|
67 |
private function add_structure(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $shape, $name, array $value, \XMLWriter $xml)
|
61 |
private function defaultShape(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
|
62 |
{
|
63 |
$this->startElement($shape, $name, $xml);
|
64 |
+
$xml->text($value);
|
65 |
$xml->endElement();
|
66 |
}
|
67 |
private function add_structure(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $shape, $name, array $value, \XMLWriter $xml)
|
@@ -67,16 +67,18 @@ class Service extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\AbstractMod
|
|
67 |
/**
|
68 |
* Creates an error parser for the given protocol.
|
69 |
*
|
|
|
|
|
70 |
* @param string $protocol Protocol to parse (e.g., query, json, etc.)
|
71 |
*
|
72 |
* @return callable
|
73 |
* @throws \UnexpectedValueException
|
74 |
*/
|
75 |
-
public static function createErrorParser($protocol)
|
76 |
{
|
77 |
static $mapping = ['json' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\JsonRpcErrorParser', 'query' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser', 'rest-json' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\RestJsonErrorParser', 'rest-xml' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser', 'ec2' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser'];
|
78 |
if (isset($mapping[$protocol])) {
|
79 |
-
return new $mapping[$protocol]();
|
80 |
}
|
81 |
throw new \UnexpectedValueException("Unknown protocol: {$protocol}");
|
82 |
}
|
@@ -224,6 +226,22 @@ class Service extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\AbstractMod
|
|
224 |
}
|
225 |
return $result;
|
226 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
/**
|
228 |
* Get all of the service metadata or a specific metadata key value.
|
229 |
*
|
67 |
/**
|
68 |
* Creates an error parser for the given protocol.
|
69 |
*
|
70 |
+
* Redundant method signature to preserve backwards compatibility.
|
71 |
+
*
|
72 |
* @param string $protocol Protocol to parse (e.g., query, json, etc.)
|
73 |
*
|
74 |
* @return callable
|
75 |
* @throws \UnexpectedValueException
|
76 |
*/
|
77 |
+
public static function createErrorParser($protocol, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api = null)
|
78 |
{
|
79 |
static $mapping = ['json' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\JsonRpcErrorParser', 'query' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser', 'rest-json' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\RestJsonErrorParser', 'rest-xml' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser', 'ec2' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser'];
|
80 |
if (isset($mapping[$protocol])) {
|
81 |
+
return new $mapping[$protocol]($api);
|
82 |
}
|
83 |
throw new \UnexpectedValueException("Unknown protocol: {$protocol}");
|
84 |
}
|
226 |
}
|
227 |
return $result;
|
228 |
}
|
229 |
+
/**
|
230 |
+
* Get all of the error shapes of the service
|
231 |
+
*
|
232 |
+
* @return array
|
233 |
+
*/
|
234 |
+
public function getErrorShapes()
|
235 |
+
{
|
236 |
+
$result = [];
|
237 |
+
foreach ($this->definition['shapes'] as $name => $definition) {
|
238 |
+
if (!empty($definition['exception'])) {
|
239 |
+
$definition['name'] = $name;
|
240 |
+
$result[] = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape($definition, $this->getShapeMap());
|
241 |
+
}
|
242 |
+
}
|
243 |
+
return $result;
|
244 |
+
}
|
245 |
/**
|
246 |
* Get all of the service metadata or a specific metadata key value.
|
247 |
*
|
@@ -47,7 +47,9 @@ class ShapeMap
|
|
47 |
}
|
48 |
$definition = $shapeRef + $this->definitions[$shape];
|
49 |
$definition['name'] = $definition['shape'];
|
50 |
-
|
|
|
|
|
51 |
$result = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape::create($definition, $this);
|
52 |
if ($isSimple) {
|
53 |
$this->simple[$shape] = $result;
|
47 |
}
|
48 |
$definition = $shapeRef + $this->definitions[$shape];
|
49 |
$definition['name'] = $definition['shape'];
|
50 |
+
if (isset($definition['shape'])) {
|
51 |
+
unset($definition['shape']);
|
52 |
+
}
|
53 |
$result = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape::create($definition, $this);
|
54 |
if ($isSimple) {
|
55 |
$this->simple[$shape] = $result;
|
@@ -164,7 +164,17 @@ class Validator
|
|
164 |
}
|
165 |
private function checkAssociativeArray($value)
|
166 |
{
|
167 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
$this->addError('must be an associative array. Found ' . \DeliciousBrains\WP_Offload_Media\Aws3\Aws\describe_type($value));
|
169 |
return false;
|
170 |
}
|
164 |
}
|
165 |
private function checkAssociativeArray($value)
|
166 |
{
|
167 |
+
$isAssociative = false;
|
168 |
+
if (is_array($value)) {
|
169 |
+
$expectedIndex = 0;
|
170 |
+
$key = key($value);
|
171 |
+
do {
|
172 |
+
$isAssociative = $key !== $expectedIndex++;
|
173 |
+
next($value);
|
174 |
+
$key = key($value);
|
175 |
+
} while (!$isAssociative && null !== $key);
|
176 |
+
}
|
177 |
+
if (!$isAssociative) {
|
178 |
$this->addError('must be an associative array. Found ' . \DeliciousBrains\WP_Offload_Media\Aws3\Aws\describe_type($value));
|
179 |
return false;
|
180 |
}
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException;
|
6 |
+
/**
|
7 |
+
* @internal
|
8 |
+
*/
|
9 |
+
class AccessPointArn extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Arn implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnInterface
|
10 |
+
{
|
11 |
+
use ResourceTypeAndIdTrait;
|
12 |
+
/**
|
13 |
+
* AccessPointArn constructor
|
14 |
+
*
|
15 |
+
* @param $data
|
16 |
+
*/
|
17 |
+
public function __construct($data)
|
18 |
+
{
|
19 |
+
parent::__construct($data);
|
20 |
+
static::validate($this->data);
|
21 |
+
}
|
22 |
+
public static function parse($string)
|
23 |
+
{
|
24 |
+
$data = parent::parse($string);
|
25 |
+
return self::parseResourceTypeAndId($data);
|
26 |
+
}
|
27 |
+
/**
|
28 |
+
* Validation specific to AccessPointArn
|
29 |
+
*
|
30 |
+
* @param array $data
|
31 |
+
*/
|
32 |
+
protected static function validate(array $data)
|
33 |
+
{
|
34 |
+
if (empty($data['region'])) {
|
35 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 4th component of an access point ARN" . " represents the region and must not be empty.");
|
36 |
+
}
|
37 |
+
if (empty($data['account_id'])) {
|
38 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 5th component of an access point ARN" . " represents the account ID and must not be empty.");
|
39 |
+
}
|
40 |
+
if (!self::isValidHostLabel($data['account_id'])) {
|
41 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The account ID in an access point ARN" . " must be a valid host label value.");
|
42 |
+
}
|
43 |
+
if ($data['resource_type'] !== 'accesspoint') {
|
44 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 6th component of an access point ARN" . " represents the resource type and must be 'accesspoint'.");
|
45 |
+
}
|
46 |
+
if (empty($data['resource_id'])) {
|
47 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 7th component of an access point ARN" . " represents the resource ID and must not be empty.");
|
48 |
+
}
|
49 |
+
if (strpos($data['resource_id'], ':') !== false) {
|
50 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The resource ID component of an access" . " point ARN must not contain additional components" . " (delimited by ':').");
|
51 |
+
}
|
52 |
+
if (!self::isValidHostLabel($data['resource_id'])) {
|
53 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The resource ID in an access point ARN" . " must be a valid host label value.");
|
54 |
+
}
|
55 |
+
}
|
56 |
+
protected static function isValidHostLabel($string)
|
57 |
+
{
|
58 |
+
$length = strlen($string);
|
59 |
+
if ($length < 1 || $length > 63) {
|
60 |
+
return false;
|
61 |
+
}
|
62 |
+
if ($value = preg_match("/^[a-zA-Z0-9-]+\$/", $string)) {
|
63 |
+
return true;
|
64 |
+
}
|
65 |
+
return false;
|
66 |
+
}
|
67 |
+
}
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException;
|
6 |
+
/**
|
7 |
+
* Amazon Resource Names (ARNs) uniquely identify AWS resources. The Arn class
|
8 |
+
* parses and stores a generic ARN object representation that can apply to any
|
9 |
+
* service resource.
|
10 |
+
*
|
11 |
+
* @internal
|
12 |
+
*/
|
13 |
+
class Arn implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnInterface
|
14 |
+
{
|
15 |
+
protected $data;
|
16 |
+
protected $string;
|
17 |
+
public static function parse($string)
|
18 |
+
{
|
19 |
+
$data = ['arn' => null, 'partition' => null, 'service' => null, 'region' => null, 'account_id' => null, 'resource' => null];
|
20 |
+
$length = strlen($string);
|
21 |
+
$lastDelim = 0;
|
22 |
+
$numComponents = 0;
|
23 |
+
for ($i = 0; $i < $length; $i++) {
|
24 |
+
if ($numComponents < 5 && $string[$i] === ':') {
|
25 |
+
// Split components between delimiters
|
26 |
+
$data[key($data)] = substr($string, $lastDelim, $i - $lastDelim);
|
27 |
+
// Do not include delimiter character itself
|
28 |
+
$lastDelim = $i + 1;
|
29 |
+
next($data);
|
30 |
+
$numComponents++;
|
31 |
+
}
|
32 |
+
if ($i === $length - 1) {
|
33 |
+
// Put the remainder in the last component.
|
34 |
+
if (in_array($numComponents, [5])) {
|
35 |
+
$data['resource'] = substr($string, $lastDelim);
|
36 |
+
} else {
|
37 |
+
// If there are < 5 components, put remainder in current
|
38 |
+
// component.
|
39 |
+
$data[key($data)] = substr($string, $lastDelim);
|
40 |
+
}
|
41 |
+
}
|
42 |
+
}
|
43 |
+
return $data;
|
44 |
+
}
|
45 |
+
public function __construct($data)
|
46 |
+
{
|
47 |
+
if (is_array($data)) {
|
48 |
+
$this->data = $data;
|
49 |
+
} elseif (is_string($data)) {
|
50 |
+
$this->data = static::parse($data);
|
51 |
+
} else {
|
52 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException('Constructor accepts a string or an' . ' array as an argument.');
|
53 |
+
}
|
54 |
+
self::validate($this->data);
|
55 |
+
}
|
56 |
+
public function __toString()
|
57 |
+
{
|
58 |
+
if (!isset($this->string)) {
|
59 |
+
$components = [$this->getPrefix(), $this->getPartition(), $this->getService(), $this->getRegion(), $this->getAccountId(), $this->getResource()];
|
60 |
+
$this->string = implode(':', $components);
|
61 |
+
}
|
62 |
+
return $this->string;
|
63 |
+
}
|
64 |
+
public function getPrefix()
|
65 |
+
{
|
66 |
+
return $this->data['arn'];
|
67 |
+
}
|
68 |
+
public function getPartition()
|
69 |
+
{
|
70 |
+
return $this->data['partition'];
|
71 |
+
}
|
72 |
+
public function getService()
|
73 |
+
{
|
74 |
+
return $this->data['service'];
|
75 |
+
}
|
76 |
+
public function getRegion()
|
77 |
+
{
|
78 |
+
return $this->data['region'];
|
79 |
+
}
|
80 |
+
public function getAccountId()
|
81 |
+
{
|
82 |
+
return $this->data['account_id'];
|
83 |
+
}
|
84 |
+
public function getResource()
|
85 |
+
{
|
86 |
+
return $this->data['resource'];
|
87 |
+
}
|
88 |
+
public function toArray()
|
89 |
+
{
|
90 |
+
return $this->data;
|
91 |
+
}
|
92 |
+
/**
|
93 |
+
* Minimally restrictive generic ARN validation
|
94 |
+
*
|
95 |
+
* @param array $data
|
96 |
+
*/
|
97 |
+
protected static function validate(array $data)
|
98 |
+
{
|
99 |
+
if ($data['arn'] !== 'arn') {
|
100 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 1st component of an ARN must be" . " 'arn'.");
|
101 |
+
}
|
102 |
+
if (empty($data['partition'])) {
|
103 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 2nd component of an ARN" . " represents the partition and must not be empty.");
|
104 |
+
}
|
105 |
+
if (empty($data['service'])) {
|
106 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 3rd component of an ARN" . " represents the service and must not be empty.");
|
107 |
+
}
|
108 |
+
if (empty($data['resource'])) {
|
109 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 6th component of an ARN" . " represents the resource information and must not be empty." . " Individual service ARNs may include additional delimiters" . " to further qualify resources.");
|
110 |
+
}
|
111 |
+
}
|
112 |
+
}
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Amazon Resource Names (ARNs) uniquely identify AWS resources. Classes
|
7 |
+
* implementing ArnInterface parse and store an ARN object representation.
|
8 |
+
*
|
9 |
+
* Valid ARN formats include:
|
10 |
+
*
|
11 |
+
* arn:partition:service:region:account-id:resource-id
|
12 |
+
* arn:partition:service:region:account-id:resource-type/resource-id
|
13 |
+
* arn:partition:service:region:account-id:resource-type:resource-id
|
14 |
+
*
|
15 |
+
* Some components may be omitted, depending on the service and resource type.
|
16 |
+
*
|
17 |
+
* @internal
|
18 |
+
*/
|
19 |
+
interface ArnInterface
|
20 |
+
{
|
21 |
+
public static function parse($string);
|
22 |
+
public function __toString();
|
23 |
+
public function getPrefix();
|
24 |
+
public function getPartition();
|
25 |
+
public function getService();
|
26 |
+
public function getRegion();
|
27 |
+
public function getAccountId();
|
28 |
+
public function getResource();
|
29 |
+
public function toArray();
|
30 |
+
}
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn as S3AccessPointArn;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\BucketArn;
|
7 |
+
/**
|
8 |
+
* @internal
|
9 |
+
*/
|
10 |
+
class ArnParser
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* @param $string
|
14 |
+
* @return bool
|
15 |
+
*/
|
16 |
+
public static function isArn($string)
|
17 |
+
{
|
18 |
+
return strpos($string, 'arn:') === 0;
|
19 |
+
}
|
20 |
+
/**
|
21 |
+
* Parses a string and returns an instance of ArnInterface. Returns a
|
22 |
+
* specific type of Arn object if it has a specific class representation
|
23 |
+
* or a generic Arn object if not.
|
24 |
+
*
|
25 |
+
* @param $string
|
26 |
+
* @return ArnInterface
|
27 |
+
*/
|
28 |
+
public static function parse($string)
|
29 |
+
{
|
30 |
+
$data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Arn::parse($string);
|
31 |
+
if (substr($data['resource'], 0, 11) === 'accesspoint') {
|
32 |
+
if ($data['service'] === 's3') {
|
33 |
+
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn($string);
|
34 |
+
}
|
35 |
+
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\AccessPointArn($string);
|
36 |
+
}
|
37 |
+
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Arn($data);
|
38 |
+
}
|
39 |
+
}
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Represents a failed attempt to construct an Arn
|
7 |
+
*/
|
8 |
+
class InvalidArnException extends \RuntimeException
|
9 |
+
{
|
10 |
+
}
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @internal
|
7 |
+
*/
|
8 |
+
trait ResourceTypeAndIdTrait
|
9 |
+
{
|
10 |
+
public function getResourceType()
|
11 |
+
{
|
12 |
+
return $this->data['resource_type'];
|
13 |
+
}
|
14 |
+
public function getResourceId()
|
15 |
+
{
|
16 |
+
return $this->data['resource_id'];
|
17 |
+
}
|
18 |
+
private static function parseResourceTypeAndId(array $data)
|
19 |
+
{
|
20 |
+
$data['resource_type'] = null;
|
21 |
+
$data['resource_id'] = null;
|
22 |
+
$length = strlen($data['resource']);
|
23 |
+
for ($i = 0; $i < $length; $i++) {
|
24 |
+
if (in_array($data['resource'][$i], ['/', ':'])) {
|
25 |
+
$data['resource_type'] = substr($data['resource'], 0, $i);
|
26 |
+
$data['resource_id'] = substr($data['resource'], $i + 1);
|
27 |
+
break;
|
28 |
+
}
|
29 |
+
}
|
30 |
+
return $data;
|
31 |
+
}
|
32 |
+
}
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\AccessPointArn as BaseAccessPointArn;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnInterface;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException;
|
8 |
+
/**
|
9 |
+
* @internal
|
10 |
+
*/
|
11 |
+
class AccessPointArn extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\AccessPointArn implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnInterface
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Validation specific to AccessPointArn
|
15 |
+
*
|
16 |
+
* @param array $data
|
17 |
+
*/
|
18 |
+
protected static function validate(array $data)
|
19 |
+
{
|
20 |
+
parent::validate($data);
|
21 |
+
if ($data['service'] !== 's3') {
|
22 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException("The 3rd component of an S3 access" . " point ARN represents the region and must be 's3'.");
|
23 |
+
}
|
24 |
+
}
|
25 |
+
}
|
@@ -8,6 +8,7 @@ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
|
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallAttemptMonitoringMiddleware;
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallMonitoringMiddleware;
|
10 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider;
|
|
|
11 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Signature\SignatureProvider;
|
12 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri;
|
13 |
/**
|
@@ -17,6 +18,8 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
|
|
17 |
{
|
18 |
use AwsClientTrait;
|
19 |
/** @var array */
|
|
|
|
|
20 |
private $config;
|
21 |
/** @var string */
|
22 |
private $region;
|
@@ -57,6 +60,16 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
|
|
57 |
* credentials or return null. See Aws\Credentials\CredentialProvider for
|
58 |
* a list of built-in credentials providers. If no credentials are
|
59 |
* provided, the SDK will attempt to load them from the environment.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
* - debug: (bool|array) Set to true to display debug information when
|
61 |
* sending requests. Alternatively, you can provide an associative array
|
62 |
* with the following keys: logfn: (callable) Function that is invoked
|
@@ -83,6 +96,14 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
|
|
83 |
* - endpoint: (string) The full URI of the webservice. This is only
|
84 |
* required when connecting to a custom endpoint (e.g., a local version
|
85 |
* of S3).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
* - endpoint_provider: (callable) An optional PHP callable that
|
87 |
* accepts a hash of options including a "service" and "region" key and
|
88 |
* returns NULL or a hash of endpoint data, of which the "endpoint" key
|
@@ -162,8 +183,10 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
|
|
162 |
$this->defaultRequestOptions = $config['http'];
|
163 |
$this->addSignatureMiddleware();
|
164 |
$this->addInvocationId();
|
165 |
-
$this->addClientSideMonitoring($args);
|
166 |
$this->addEndpointParameterMiddleware($args);
|
|
|
|
|
|
|
167 |
if (isset($args['with_resolved'])) {
|
168 |
$args['with_resolved']($config);
|
169 |
}
|
@@ -244,6 +267,13 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
|
|
244 |
$list->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointParameterMiddleware::wrap($this->api), 'endpoint_parameter');
|
245 |
}
|
246 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
247 |
private function addSignatureMiddleware()
|
248 |
{
|
249 |
$api = $this->getApi();
|
@@ -252,6 +282,9 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
|
|
252 |
$name = $this->config['signing_name'];
|
253 |
$region = $this->config['signing_region'];
|
254 |
$resolver = static function (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $c) use($api, $provider, $name, $region, $version) {
|
|
|
|
|
|
|
255 |
$authType = $api->getOperation($c->getName())['authtype'];
|
256 |
switch ($authType) {
|
257 |
case 'none':
|
@@ -270,12 +303,24 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
|
|
270 |
// Add invocation id to each request
|
271 |
$this->handlerList->prependSign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::invocationId(), 'invocation-id');
|
272 |
}
|
273 |
-
private function
|
274 |
{
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
}
|
280 |
/**
|
281 |
* Returns a service model and doc model with any necessary changes
|
@@ -291,6 +336,18 @@ class AwsClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClientI
|
|
291 |
*/
|
292 |
public static function applyDocFilters(array $api, array $docs)
|
293 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
294 |
return [new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service($api, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::defaultProvider()), new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DocModel($docs)];
|
295 |
}
|
296 |
/**
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallAttemptMonitoringMiddleware;
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallMonitoringMiddleware;
|
10 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider;
|
11 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\EndpointDiscoveryMiddleware;
|
12 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Signature\SignatureProvider;
|
13 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri;
|
14 |
/**
|
18 |
{
|
19 |
use AwsClientTrait;
|
20 |
/** @var array */
|
21 |
+
private $aliases;
|
22 |
+
/** @var array */
|
23 |
private $config;
|
24 |
/** @var string */
|
25 |
private $region;
|
60 |
* credentials or return null. See Aws\Credentials\CredentialProvider for
|
61 |
* a list of built-in credentials providers. If no credentials are
|
62 |
* provided, the SDK will attempt to load them from the environment.
|
63 |
+
* - csm:
|
64 |
+
* (Aws\ClientSideMonitoring\ConfigurationInterface|array|callable) Specifies
|
65 |
+
* the credentials used to sign requests. Provide an
|
66 |
+
* Aws\ClientSideMonitoring\ConfigurationInterface object, a callable
|
67 |
+
* configuration provider used to create client-side monitoring configuration,
|
68 |
+
* `false` to disable csm, or an associative array with the following keys:
|
69 |
+
* enabled: (bool) Set to true to enable client-side monitoring, defaults
|
70 |
+
* to false; host: (string) the host location to send monitoring events to,
|
71 |
+
* defaults to 127.0.0.1; port: (int) The port used for the host connection,
|
72 |
+
* defaults to 31000; client_id: (string) An identifier for this project
|
73 |
* - debug: (bool|array) Set to true to display debug information when
|
74 |
* sending requests. Alternatively, you can provide an associative array
|
75 |
* with the following keys: logfn: (callable) Function that is invoked
|
96 |
* - endpoint: (string) The full URI of the webservice. This is only
|
97 |
* required when connecting to a custom endpoint (e.g., a local version
|
98 |
* of S3).
|
99 |
+
* - endpoint_discovery: (Aws\EndpointDiscovery\ConfigurationInterface,
|
100 |
+
* Aws\CacheInterface, array, callable) Settings for endpoint discovery.
|
101 |
+
* Provide an instance of Aws\EndpointDiscovery\ConfigurationInterface,
|
102 |
+
* an instance Aws\CacheInterface, a callable that provides a promise for
|
103 |
+
* a Configuration object, or an associative array with the following
|
104 |
+
* keys: enabled: (bool) Set to true to enable endpoint discovery,
|
105 |
+
* defaults to false; cache_limit: (int) The maximum number of keys in the
|
106 |
+
* endpoints cache, defaults to 1000.
|
107 |
* - endpoint_provider: (callable) An optional PHP callable that
|
108 |
* accepts a hash of options including a "service" and "region" key and
|
109 |
* returns NULL or a hash of endpoint data, of which the "endpoint" key
|
183 |
$this->defaultRequestOptions = $config['http'];
|
184 |
$this->addSignatureMiddleware();
|
185 |
$this->addInvocationId();
|
|
|
186 |
$this->addEndpointParameterMiddleware($args);
|
187 |
+
$this->addEndpointDiscoveryMiddleware($config, $args);
|
188 |
+
$this->loadAliases();
|
189 |
+
$this->addStreamRequestPayload();
|
190 |
if (isset($args['with_resolved'])) {
|
191 |
$args['with_resolved']($config);
|
192 |
}
|
267 |
$list->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointParameterMiddleware::wrap($this->api), 'endpoint_parameter');
|
268 |
}
|
269 |
}
|
270 |
+
private function addEndpointDiscoveryMiddleware($config, $args)
|
271 |
+
{
|
272 |
+
$list = $this->getHandlerList();
|
273 |
+
if (!isset($args['endpoint'])) {
|
274 |
+
$list->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\EndpointDiscoveryMiddleware::wrap($this, $args, $config['endpoint_discovery']), 'EndpointDiscoveryMiddleware');
|
275 |
+
}
|
276 |
+
}
|
277 |
private function addSignatureMiddleware()
|
278 |
{
|
279 |
$api = $this->getApi();
|
282 |
$name = $this->config['signing_name'];
|
283 |
$region = $this->config['signing_region'];
|
284 |
$resolver = static function (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $c) use($api, $provider, $name, $region, $version) {
|
285 |
+
if (!empty($c['@context']['signing_region'])) {
|
286 |
+
$region = $c['@context']['signing_region'];
|
287 |
+
}
|
288 |
$authType = $api->getOperation($c->getName())['authtype'];
|
289 |
switch ($authType) {
|
290 |
case 'none':
|
303 |
// Add invocation id to each request
|
304 |
$this->handlerList->prependSign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::invocationId(), 'invocation-id');
|
305 |
}
|
306 |
+
private function loadAliases($file = null)
|
307 |
{
|
308 |
+
if (!isset($this->aliases)) {
|
309 |
+
if (is_null($file)) {
|
310 |
+
$file = __DIR__ . '/data/aliases.json';
|
311 |
+
}
|
312 |
+
$aliases = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json($file);
|
313 |
+
$serviceId = $this->api->getServiceId();
|
314 |
+
$version = $this->getApi()->getApiVersion();
|
315 |
+
if (!empty($aliases['operations'][$serviceId][$version])) {
|
316 |
+
$this->aliases = array_flip($aliases['operations'][$serviceId][$version]);
|
317 |
+
}
|
318 |
+
}
|
319 |
+
}
|
320 |
+
private function addStreamRequestPayload()
|
321 |
+
{
|
322 |
+
$streamRequestPayloadMiddleware = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\StreamRequestPayloadMiddleware::wrap($this->api);
|
323 |
+
$this->handlerList->prependSign($streamRequestPayloadMiddleware, 'StreamRequestPayloadMiddleware');
|
324 |
}
|
325 |
/**
|
326 |
* Returns a service model and doc model with any necessary changes
|
336 |
*/
|
337 |
public static function applyDocFilters(array $api, array $docs)
|
338 |
{
|
339 |
+
$aliases = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json(__DIR__ . '/data/aliases.json');
|
340 |
+
$serviceId = $api['metadata']['serviceId'];
|
341 |
+
$version = $api['metadata']['apiVersion'];
|
342 |
+
// Replace names for any operations with SDK aliases
|
343 |
+
if (!empty($aliases['operations'][$serviceId][$version])) {
|
344 |
+
foreach ($aliases['operations'][$serviceId][$version] as $op => $alias) {
|
345 |
+
$api['operations'][$alias] = $api['operations'][$op];
|
346 |
+
$docs['operations'][$alias] = $docs['operations'][$op];
|
347 |
+
unset($api['operations'][$op], $docs['operations'][$op]);
|
348 |
+
}
|
349 |
+
}
|
350 |
+
ksort($api['operations']);
|
351 |
return [new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service($api, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::defaultProvider()), new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DocModel($docs)];
|
352 |
}
|
353 |
/**
|
@@ -49,9 +49,16 @@ trait AwsClientTrait
|
|
49 |
}
|
50 |
public function __call($name, array $args)
|
51 |
{
|
52 |
-
$params = isset($args[0]) ? $args[0] : [];
|
53 |
if (substr($name, -5) === 'Async') {
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
}
|
56 |
return $this->execute($this->getCommand($name, $params));
|
57 |
}
|
49 |
}
|
50 |
public function __call($name, array $args)
|
51 |
{
|
|
|
52 |
if (substr($name, -5) === 'Async') {
|
53 |
+
$name = substr($name, 0, -5);
|
54 |
+
$isAsync = true;
|
55 |
+
}
|
56 |
+
if (!empty($this->aliases[ucfirst($name)])) {
|
57 |
+
$name = $this->aliases[ucfirst($name)];
|
58 |
+
}
|
59 |
+
$params = isset($args[0]) ? $args[0] : [];
|
60 |
+
if (!empty($isAsync)) {
|
61 |
+
return $this->executeAsync($this->getCommand($name, $params));
|
62 |
}
|
63 |
return $this->execute($this->getCommand($name, $params));
|
64 |
}
|
@@ -5,9 +5,15 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Validator;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
|
|
|
|
|
|
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\Credentials;
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface;
|
10 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider;
|
|
|
|
|
|
|
11 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Signature\SignatureProvider;
|
12 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\EndpointProvider;
|
13 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialProvider;
|
@@ -22,7 +28,7 @@ class ClientResolver
|
|
22 |
private $argDefinitions;
|
23 |
/** @var array Map of types to a corresponding function */
|
24 |
private static $typeMap = ['resource' => 'is_resource', 'callable' => 'is_callable', 'int' => 'is_int', 'bool' => 'is_bool', 'string' => 'is_string', 'object' => 'is_object', 'array' => 'is_array'];
|
25 |
-
private static $defaultArgs = ['service' => ['type' => 'value', 'valid' => ['string'], 'doc' => 'Name of the service to utilize. This value will be supplied by default when using one of the SDK clients (e.g., Aws\\S3\\S3Client).', 'required' => true, 'internal' => true], 'exception_class' => ['type' => 'value', 'valid' => ['string'], 'doc' => 'Exception class to create when an error occurs.', 'default' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Exception\\AwsException', 'internal' => true], 'scheme' => ['type' => 'value', 'valid' => ['string'], 'default' => 'https', 'doc' => 'URI scheme to use when connecting connect. The SDK will utilize "https" endpoints (i.e., utilize SSL/TLS connections) by default. You can attempt to connect to a service over an unencrypted "http" endpoint by setting ``scheme`` to "http".'], 'disable_host_prefix_injection' => ['type' => 'value', 'valid' => ['bool'], 'doc' => 'Set to true to disable host prefix injection logic for services that use it. This disables the entire prefix injection, including the portions supplied by user-defined parameters. Setting this flag will have no effect on services that do not use host prefix injection.', 'default' => false], 'endpoint' => ['type' => 'value', 'valid' => ['string'], 'doc' => 'The full URI of the webservice. This is only required when connecting to a custom endpoint (e.g., a local version of S3).', 'fn' => [__CLASS__, '_apply_endpoint']], 'region' => ['type' => 'value', 'valid' => ['string'], 'required' => [__CLASS__, '_missing_region'], 'doc' => 'Region to connect to. See http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of available regions.'], 'version' => ['type' => 'value', 'valid' => ['string'], 'required' => [__CLASS__, '_missing_version'], 'doc' => 'The version of the webservice to utilize (e.g., 2006-03-01).'], 'signature_provider' => ['type' => 'value', 'valid' => ['callable'], 'doc' => 'A callable that accepts a signature version name (e.g., "v4"), a service name, and region, and returns a SignatureInterface object or null. This provider is used to create signers utilized by the client. See Aws\\Signature\\SignatureProvider for a list of built-in providers', 'default' => [__CLASS__, '_default_signature_provider']], 'api_provider' => ['type' => 'value', 'valid' => ['callable'], 'doc' => 'An optional PHP callable that accepts a type, service, and version argument, and returns an array of corresponding configuration data. The type value can be one of api, waiter, or paginator.', 'fn' => [__CLASS__, '_apply_api_provider'], 'default' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::class, 'defaultProvider']], 'endpoint_provider' => ['type' => 'value', 'valid' => ['callable'], 'fn' => [__CLASS__, '_apply_endpoint_provider'], 'doc' => 'An optional PHP callable that accepts a hash of options including a "service" and "region" key and returns NULL or a hash of endpoint data, of which the "endpoint" key is required. See Aws\\Endpoint\\EndpointProvider for a list of built-in providers.', 'default' => [__CLASS__, '_default_endpoint_provider']], 'serializer' => ['default' => [__CLASS__, '_default_serializer'], 'fn' => [__CLASS__, '_apply_serializer'], 'internal' => true, 'type' => 'value', 'valid' => ['callable']], 'signature_version' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'A string representing a custom signature version to use with a service (e.g., v4). Note that per/operation signature version MAY override this requested signature version.', 'default' => [__CLASS__, '_default_signature_version']], 'signing_name' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'A string representing a custom service name to be used when calculating a request signature.', 'default' => [__CLASS__, '_default_signing_name']], 'signing_region' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'A string representing a custom region name to be used when calculating a request signature.', 'default' => [__CLASS__, '_default_signing_region']], 'profile' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'Allows you to specify which profile to use when credentials are created from the AWS credentials file in your HOME directory. This setting overrides the AWS_PROFILE environment variable. Note: Specifying "profile" will cause the "credentials" key to be ignored.', 'fn' => [__CLASS__, '_apply_profile']], 'credentials' => ['type' => 'value', 'valid' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface::class, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface::class, 'array', 'bool', 'callable'], 'doc' => 'Specifies the credentials used to sign requests. Provide an Aws\\Credentials\\CredentialsInterface object, an associative array of "key", "secret", and an optional "token" key, `false` to use null credentials, or a callable credentials provider used to create credentials or return null. See Aws\\Credentials\\CredentialProvider for a list of built-in credentials providers. If no credentials are provided, the SDK will attempt to load them from the environment.', 'fn' => [__CLASS__, '_apply_credentials'], 'default' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialProvider::class, 'defaultProvider']], 'stats' => ['type' => 'value', 'valid' => ['bool', 'array'], 'default' => false, 'doc' => 'Set to true to gather transfer statistics on requests sent. Alternatively, you can provide an associative array with the following keys: retries: (bool) Set to false to disable reporting on retries attempted; http: (bool) Set to true to enable collecting statistics from lower level HTTP adapters (e.g., values returned in GuzzleHttp\\TransferStats). HTTP handlers must support an http_stats_receiver option for this to have an effect; timer: (bool) Set to true to enable a command timer that reports the total wall clock time spent on an operation in seconds.', 'fn' => [__CLASS__, '_apply_stats']], 'retries' => ['type' => 'value', 'valid' => ['int'], 'doc' => 'Configures the maximum number of allowed retries for a client (pass 0 to disable retries). ', 'fn' => [__CLASS__, '_apply_retries'], 'default' => 3], 'validate' => ['type' => 'value', 'valid' => ['bool', 'array'], 'default' => true, 'doc' => 'Set to false to disable client-side parameter validation. Set to true to utilize default validation constraints. Set to an associative array of validation options to enable specific validation constraints.', 'fn' => [__CLASS__, '_apply_validate']], 'debug' => ['type' => 'value', 'valid' => ['bool', 'array'], 'doc' => 'Set to true to display debug information when sending requests. Alternatively, you can provide an associative array with the following keys: logfn: (callable) Function that is invoked with log messages; stream_size: (int) When the size of a stream is greater than this number, the stream data will not be logged (set to "0" to not log any stream data); scrub_auth: (bool) Set to false to disable the scrubbing of auth data from the logged messages; http: (bool) Set to false to disable the "debug" feature of lower level HTTP adapters (e.g., verbose curl output).', 'fn' => [__CLASS__, '_apply_debug']], 'http' => ['type' => 'value', 'valid' => ['array'], 'default' => [], 'doc' => 'Set to an array of SDK request options to apply to each request (e.g., proxy, verify, etc.).'], 'http_handler' => ['type' => 'value', 'valid' => ['callable'], 'doc' => 'An HTTP handler is a function that accepts a PSR-7 request object and returns a promise that is fulfilled with a PSR-7 response object or rejected with an array of exception data. NOTE: This option supersedes any provided "handler" option.', 'fn' => [__CLASS__, '_apply_http_handler']], 'handler' => ['type' => 'value', 'valid' => ['callable'], 'doc' => 'A handler that accepts a command object, request object and returns a promise that is fulfilled with an Aws\\ResultInterface object or rejected with an Aws\\Exception\\AwsException. A handler does not accept a next handler as it is terminal and expected to fulfill a command. If no handler is provided, a default Guzzle handler will be utilized.', 'fn' => [__CLASS__, '_apply_handler'], 'default' => [__CLASS__, '_default_handler']], 'ua_append' => ['type' => 'value', 'valid' => ['string', 'array'], 'doc' => 'Provide a string or array of strings to send in the User-Agent header.', 'fn' => [__CLASS__, '_apply_user_agent'], 'default' => []], 'idempotency_auto_fill' => ['type' => 'value', 'valid' => ['bool', 'callable'], 'doc' => 'Set to false to disable SDK to populate parameters that enabled \'idempotencyToken\' trait with a random UUID v4 value on your behalf. Using default value \'true\' still allows parameter value to be overwritten when provided. Note: auto-fill only works when cryptographically secure random bytes generator functions(random_bytes, openssl_random_pseudo_bytes or mcrypt_create_iv) can be found. You may also provide a callable source of random bytes.', 'default' => true, 'fn' => [__CLASS__, '_apply_idempotency_auto_fill']]];
|
26 |
/**
|
27 |
* Gets an array of default client arguments, each argument containing a
|
28 |
* hash of the following:
|
@@ -204,6 +210,19 @@ class ClientResolver
|
|
204 |
throw new \InvalidArgumentException('Credentials must be an instance of ' . 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Credentials\\CredentialsInterface, an associative ' . 'array that contains "key", "secret", and an optional "token" ' . 'key-value pairs, a credentials provider function, or false.');
|
205 |
}
|
206 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
207 |
public static function _apply_api_provider(callable $value, array &$args)
|
208 |
{
|
209 |
$api = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::resolve($value, 'api', $args['service'], $args['version']), $value);
|
@@ -212,14 +231,14 @@ class ClientResolver
|
|
212 |
}
|
213 |
$args['api'] = $api;
|
214 |
$args['parser'] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service::createParser($api);
|
215 |
-
$args['error_parser'] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service::createErrorParser($api->getProtocol());
|
216 |
}
|
217 |
public static function _apply_endpoint_provider(callable $value, array &$args)
|
218 |
{
|
219 |
if (!isset($args['endpoint'])) {
|
220 |
$endpointPrefix = isset($args['api']['metadata']['endpointPrefix']) ? $args['api']['metadata']['endpointPrefix'] : $args['service'];
|
221 |
// Invoke the endpoint provider and throw if it does not resolve.
|
222 |
-
$result = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\EndpointProvider::resolve($value, ['service' => $endpointPrefix, 'region' => $args['region'], 'scheme' => $args['scheme']]);
|
223 |
$args['endpoint'] = $result['endpoint'];
|
224 |
if (empty($args['config']['signature_version']) && isset($result['signatureVersion'])) {
|
225 |
$args['config']['signature_version'] = $result['signatureVersion'];
|
@@ -232,6 +251,14 @@ class ClientResolver
|
|
232 |
}
|
233 |
}
|
234 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
235 |
public static function _apply_serializer($value, array &$args, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\HandlerList $list)
|
236 |
{
|
237 |
$list->prependBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::requestBuilder($value), 'builder');
|
@@ -318,7 +345,8 @@ class ClientResolver
|
|
318 |
}
|
319 |
public static function _default_endpoint_provider(array $args)
|
320 |
{
|
321 |
-
|
|
|
322 |
}
|
323 |
public static function _default_serializer(array $args)
|
324 |
{
|
@@ -392,4 +420,21 @@ A "region" configuration value is required for the "{$service}" service
|
|
392 |
found at http://docs.aws.amazon.com/general/latest/gr/rande.html.
|
393 |
EOT;
|
394 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
395 |
}
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Validator;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallAttemptMonitoringMiddleware;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallMonitoringMiddleware;
|
10 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration;
|
11 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\Credentials;
|
12 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface;
|
13 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider;
|
14 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationInterface;
|
15 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationProvider;
|
16 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\EndpointDiscoveryMiddleware;
|
17 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Signature\SignatureProvider;
|
18 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\EndpointProvider;
|
19 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialProvider;
|
28 |
private $argDefinitions;
|
29 |
/** @var array Map of types to a corresponding function */
|
30 |
private static $typeMap = ['resource' => 'is_resource', 'callable' => 'is_callable', 'int' => 'is_int', 'bool' => 'is_bool', 'string' => 'is_string', 'object' => 'is_object', 'array' => 'is_array'];
|
31 |
+
private static $defaultArgs = ['service' => ['type' => 'value', 'valid' => ['string'], 'doc' => 'Name of the service to utilize. This value will be supplied by default when using one of the SDK clients (e.g., Aws\\S3\\S3Client).', 'required' => true, 'internal' => true], 'exception_class' => ['type' => 'value', 'valid' => ['string'], 'doc' => 'Exception class to create when an error occurs.', 'default' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Exception\\AwsException', 'internal' => true], 'scheme' => ['type' => 'value', 'valid' => ['string'], 'default' => 'https', 'doc' => 'URI scheme to use when connecting connect. The SDK will utilize "https" endpoints (i.e., utilize SSL/TLS connections) by default. You can attempt to connect to a service over an unencrypted "http" endpoint by setting ``scheme`` to "http".'], 'disable_host_prefix_injection' => ['type' => 'value', 'valid' => ['bool'], 'doc' => 'Set to true to disable host prefix injection logic for services that use it. This disables the entire prefix injection, including the portions supplied by user-defined parameters. Setting this flag will have no effect on services that do not use host prefix injection.', 'default' => false], 'endpoint' => ['type' => 'value', 'valid' => ['string'], 'doc' => 'The full URI of the webservice. This is only required when connecting to a custom endpoint (e.g., a local version of S3).', 'fn' => [__CLASS__, '_apply_endpoint']], 'region' => ['type' => 'value', 'valid' => ['string'], 'required' => [__CLASS__, '_missing_region'], 'doc' => 'Region to connect to. See http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of available regions.'], 'version' => ['type' => 'value', 'valid' => ['string'], 'required' => [__CLASS__, '_missing_version'], 'doc' => 'The version of the webservice to utilize (e.g., 2006-03-01).'], 'signature_provider' => ['type' => 'value', 'valid' => ['callable'], 'doc' => 'A callable that accepts a signature version name (e.g., "v4"), a service name, and region, and returns a SignatureInterface object or null. This provider is used to create signers utilized by the client. See Aws\\Signature\\SignatureProvider for a list of built-in providers', 'default' => [__CLASS__, '_default_signature_provider']], 'api_provider' => ['type' => 'value', 'valid' => ['callable'], 'doc' => 'An optional PHP callable that accepts a type, service, and version argument, and returns an array of corresponding configuration data. The type value can be one of api, waiter, or paginator.', 'fn' => [__CLASS__, '_apply_api_provider'], 'default' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::class, 'defaultProvider']], 'endpoint_provider' => ['type' => 'value', 'valid' => ['callable'], 'fn' => [__CLASS__, '_apply_endpoint_provider'], 'doc' => 'An optional PHP callable that accepts a hash of options including a "service" and "region" key and returns NULL or a hash of endpoint data, of which the "endpoint" key is required. See Aws\\Endpoint\\EndpointProvider for a list of built-in providers.', 'default' => [__CLASS__, '_default_endpoint_provider']], 'serializer' => ['default' => [__CLASS__, '_default_serializer'], 'fn' => [__CLASS__, '_apply_serializer'], 'internal' => true, 'type' => 'value', 'valid' => ['callable']], 'signature_version' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'A string representing a custom signature version to use with a service (e.g., v4). Note that per/operation signature version MAY override this requested signature version.', 'default' => [__CLASS__, '_default_signature_version']], 'signing_name' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'A string representing a custom service name to be used when calculating a request signature.', 'default' => [__CLASS__, '_default_signing_name']], 'signing_region' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'A string representing a custom region name to be used when calculating a request signature.', 'default' => [__CLASS__, '_default_signing_region']], 'profile' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'Allows you to specify which profile to use when credentials are created from the AWS credentials file in your HOME directory. This setting overrides the AWS_PROFILE environment variable. Note: Specifying "profile" will cause the "credentials" key to be ignored.', 'fn' => [__CLASS__, '_apply_profile']], 'credentials' => ['type' => 'value', 'valid' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface::class, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface::class, 'array', 'bool', 'callable'], 'doc' => 'Specifies the credentials used to sign requests. Provide an Aws\\Credentials\\CredentialsInterface object, an associative array of "key", "secret", and an optional "token" key, `false` to use null credentials, or a callable credentials provider used to create credentials or return null. See Aws\\Credentials\\CredentialProvider for a list of built-in credentials providers. If no credentials are provided, the SDK will attempt to load them from the environment.', 'fn' => [__CLASS__, '_apply_credentials'], 'default' => [__CLASS__, '_default_credential_provider']], 'endpoint_discovery' => ['type' => 'value', 'valid' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationInterface::class, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface::class, 'array', 'callable'], 'doc' => 'Specifies settings for endpoint discovery. Provide an instance of Aws\\EndpointDiscovery\\ConfigurationInterface, an instance Aws\\CacheInterface, a callable that provides a promise for a Configuration object, or an associative array with the following keys: enabled: (bool) Set to true to enable endpoint discovery. Defaults to false; cache_limit: (int) The maximum number of keys in the endpoints cache. Defaults to 1000.', 'fn' => [__CLASS__, '_apply_endpoint_discovery'], 'default' => [__CLASS__, '_default_endpoint_discovery_provider']], 'stats' => ['type' => 'value', 'valid' => ['bool', 'array'], 'default' => false, 'doc' => 'Set to true to gather transfer statistics on requests sent. Alternatively, you can provide an associative array with the following keys: retries: (bool) Set to false to disable reporting on retries attempted; http: (bool) Set to true to enable collecting statistics from lower level HTTP adapters (e.g., values returned in GuzzleHttp\\TransferStats). HTTP handlers must support an http_stats_receiver option for this to have an effect; timer: (bool) Set to true to enable a command timer that reports the total wall clock time spent on an operation in seconds.', 'fn' => [__CLASS__, '_apply_stats']], 'retries' => ['type' => 'value', 'valid' => ['int'], 'doc' => 'Configures the maximum number of allowed retries for a client (pass 0 to disable retries). ', 'fn' => [__CLASS__, '_apply_retries'], 'default' => 3], 'validate' => ['type' => 'value', 'valid' => ['bool', 'array'], 'default' => true, 'doc' => 'Set to false to disable client-side parameter validation. Set to true to utilize default validation constraints. Set to an associative array of validation options to enable specific validation constraints.', 'fn' => [__CLASS__, '_apply_validate']], 'debug' => ['type' => 'value', 'valid' => ['bool', 'array'], 'doc' => 'Set to true to display debug information when sending requests. Alternatively, you can provide an associative array with the following keys: logfn: (callable) Function that is invoked with log messages; stream_size: (int) When the size of a stream is greater than this number, the stream data will not be logged (set to "0" to not log any stream data); scrub_auth: (bool) Set to false to disable the scrubbing of auth data from the logged messages; http: (bool) Set to false to disable the "debug" feature of lower level HTTP adapters (e.g., verbose curl output).', 'fn' => [__CLASS__, '_apply_debug']], 'csm' => ['type' => 'value', 'valid' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationInterface::class, 'callable', 'array', 'bool'], 'doc' => 'CSM options for the client. Provides a callable wrapping a promise, a boolean "false", an instance of ConfigurationInterface, or an associative array of "enabled", "host", "port", and "client_id".', 'fn' => [__CLASS__, '_apply_csm'], 'default' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::class, 'defaultProvider']], 'http' => ['type' => 'value', 'valid' => ['array'], 'default' => [], 'doc' => 'Set to an array of SDK request options to apply to each request (e.g., proxy, verify, etc.).'], 'http_handler' => ['type' => 'value', 'valid' => ['callable'], 'doc' => 'An HTTP handler is a function that accepts a PSR-7 request object and returns a promise that is fulfilled with a PSR-7 response object or rejected with an array of exception data. NOTE: This option supersedes any provided "handler" option.', 'fn' => [__CLASS__, '_apply_http_handler']], 'handler' => ['type' => 'value', 'valid' => ['callable'], 'doc' => 'A handler that accepts a command object, request object and returns a promise that is fulfilled with an Aws\\ResultInterface object or rejected with an Aws\\Exception\\AwsException. A handler does not accept a next handler as it is terminal and expected to fulfill a command. If no handler is provided, a default Guzzle handler will be utilized.', 'fn' => [__CLASS__, '_apply_handler'], 'default' => [__CLASS__, '_default_handler']], 'ua_append' => ['type' => 'value', 'valid' => ['string', 'array'], 'doc' => 'Provide a string or array of strings to send in the User-Agent header.', 'fn' => [__CLASS__, '_apply_user_agent'], 'default' => []], 'idempotency_auto_fill' => ['type' => 'value', 'valid' => ['bool', 'callable'], 'doc' => 'Set to false to disable SDK to populate parameters that enabled \'idempotencyToken\' trait with a random UUID v4 value on your behalf. Using default value \'true\' still allows parameter value to be overwritten when provided. Note: auto-fill only works when cryptographically secure random bytes generator functions(random_bytes, openssl_random_pseudo_bytes or mcrypt_create_iv) can be found. You may also provide a callable source of random bytes.', 'default' => true, 'fn' => [__CLASS__, '_apply_idempotency_auto_fill']]];
|
32 |
/**
|
33 |
* Gets an array of default client arguments, each argument containing a
|
34 |
* hash of the following:
|
210 |
throw new \InvalidArgumentException('Credentials must be an instance of ' . 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Credentials\\CredentialsInterface, an associative ' . 'array that contains "key", "secret", and an optional "token" ' . 'key-value pairs, a credentials provider function, or false.');
|
211 |
}
|
212 |
}
|
213 |
+
public static function _default_credential_provider(array $args)
|
214 |
+
{
|
215 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialProvider::defaultProvider($args);
|
216 |
+
}
|
217 |
+
public static function _apply_csm($value, array &$args, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\HandlerList $list)
|
218 |
+
{
|
219 |
+
if ($value === false) {
|
220 |
+
$value = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration(false, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_HOST, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_PORT, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_CLIENT_ID);
|
221 |
+
$args['csm'] = $value;
|
222 |
+
}
|
223 |
+
$list->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallMonitoringMiddleware::wrap($args['credentials'], $value, $args['region'], $args['api']->getServiceId()), 'ApiCallMonitoringMiddleware');
|
224 |
+
$list->appendAttempt(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ApiCallAttemptMonitoringMiddleware::wrap($args['credentials'], $value, $args['region'], $args['api']->getServiceId()), 'ApiCallAttemptMonitoringMiddleware');
|
225 |
+
}
|
226 |
public static function _apply_api_provider(callable $value, array &$args)
|
227 |
{
|
228 |
$api = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::resolve($value, 'api', $args['service'], $args['version']), $value);
|
231 |
}
|
232 |
$args['api'] = $api;
|
233 |
$args['parser'] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service::createParser($api);
|
234 |
+
$args['error_parser'] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service::createErrorParser($api->getProtocol(), $api);
|
235 |
}
|
236 |
public static function _apply_endpoint_provider(callable $value, array &$args)
|
237 |
{
|
238 |
if (!isset($args['endpoint'])) {
|
239 |
$endpointPrefix = isset($args['api']['metadata']['endpointPrefix']) ? $args['api']['metadata']['endpointPrefix'] : $args['service'];
|
240 |
// Invoke the endpoint provider and throw if it does not resolve.
|
241 |
+
$result = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\EndpointProvider::resolve($value, ['service' => $endpointPrefix, 'region' => $args['region'], 'scheme' => $args['scheme'], 'options' => self::getEndpointProviderOptions($args)]);
|
242 |
$args['endpoint'] = $result['endpoint'];
|
243 |
if (empty($args['config']['signature_version']) && isset($result['signatureVersion'])) {
|
244 |
$args['config']['signature_version'] = $result['signatureVersion'];
|
251 |
}
|
252 |
}
|
253 |
}
|
254 |
+
public static function _apply_endpoint_discovery($value, array &$args)
|
255 |
+
{
|
256 |
+
$args['endpoint_discovery'] = $value;
|
257 |
+
}
|
258 |
+
public static function _default_endpoint_discovery_provider(array $args)
|
259 |
+
{
|
260 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationProvider::defaultProvider($args);
|
261 |
+
}
|
262 |
public static function _apply_serializer($value, array &$args, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\HandlerList $list)
|
263 |
{
|
264 |
$list->prependBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::requestBuilder($value), 'builder');
|
345 |
}
|
346 |
public static function _default_endpoint_provider(array $args)
|
347 |
{
|
348 |
+
$options = self::getEndpointProviderOptions($args);
|
349 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider::defaultProvider($options)->getPartition($args['region'], $args['service']);
|
350 |
}
|
351 |
public static function _default_serializer(array $args)
|
352 |
{
|
420 |
found at http://docs.aws.amazon.com/general/latest/gr/rande.html.
|
421 |
EOT;
|
422 |
}
|
423 |
+
/**
|
424 |
+
* Extracts client options for the endpoint provider to its own array
|
425 |
+
*
|
426 |
+
* @param array $args
|
427 |
+
* @return array
|
428 |
+
*/
|
429 |
+
private static function getEndpointProviderOptions(array $args)
|
430 |
+
{
|
431 |
+
$options = [];
|
432 |
+
$optionKeys = ['sts_regional_endpoints', 's3_us_east_1_regional_endpoint'];
|
433 |
+
foreach ($optionKeys as $key) {
|
434 |
+
if (isset($args[$key])) {
|
435 |
+
$options[$key] = $args[$key];
|
436 |
+
}
|
437 |
+
}
|
438 |
+
return $options;
|
439 |
+
}
|
440 |
}
|
@@ -57,7 +57,7 @@ abstract class AbstractMonitoringMiddleware implements \DeliciousBrains\WP_Offlo
|
|
57 |
*
|
58 |
* @param callable $handler
|
59 |
* @param callable $credentialProvider
|
60 |
-
* @param
|
61 |
* @param $region
|
62 |
* @param $service
|
63 |
*/
|
@@ -110,6 +110,10 @@ abstract class AbstractMonitoringMiddleware implements \DeliciousBrains\WP_Offlo
|
|
110 |
$event = ['Api' => $cmd->getName(), 'ClientId' => $this->getClientId(), 'Region' => $this->getRegion(), 'Service' => $this->getService(), 'Timestamp' => (int) floor(microtime(true) * 1000), 'UserAgent' => substr($request->getHeaderLine('User-Agent') . ' ' . \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_user_agent(), 0, 256), 'Version' => 1];
|
111 |
return $event;
|
112 |
}
|
|
|
|
|
|
|
|
|
113 |
private function getPort()
|
114 |
{
|
115 |
return $this->unwrappedOptions()->getPort();
|
@@ -181,7 +185,7 @@ abstract class AbstractMonitoringMiddleware implements \DeliciousBrains\WP_Offlo
|
|
181 |
if (!is_resource(self::$socket) || $forceNewConnection || socket_last_error(self::$socket)) {
|
182 |
self::$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
183 |
socket_clear_error(self::$socket);
|
184 |
-
socket_connect(self::$socket,
|
185 |
}
|
186 |
return self::$socket;
|
187 |
}
|
@@ -210,7 +214,12 @@ abstract class AbstractMonitoringMiddleware implements \DeliciousBrains\WP_Offlo
|
|
210 |
private function unwrappedOptions()
|
211 |
{
|
212 |
if (!$this->options instanceof ConfigurationInterface) {
|
213 |
-
|
|
|
|
|
|
|
|
|
|
|
214 |
}
|
215 |
return $this->options;
|
216 |
}
|
57 |
*
|
58 |
* @param callable $handler
|
59 |
* @param callable $credentialProvider
|
60 |
+
* @param $options
|
61 |
* @param $region
|
62 |
* @param $service
|
63 |
*/
|
110 |
$event = ['Api' => $cmd->getName(), 'ClientId' => $this->getClientId(), 'Region' => $this->getRegion(), 'Service' => $this->getService(), 'Timestamp' => (int) floor(microtime(true) * 1000), 'UserAgent' => substr($request->getHeaderLine('User-Agent') . ' ' . \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_user_agent(), 0, 256), 'Version' => 1];
|
111 |
return $event;
|
112 |
}
|
113 |
+
private function getHost()
|
114 |
+
{
|
115 |
+
return $this->unwrappedOptions()->getHost();
|
116 |
+
}
|
117 |
private function getPort()
|
118 |
{
|
119 |
return $this->unwrappedOptions()->getPort();
|
185 |
if (!is_resource(self::$socket) || $forceNewConnection || socket_last_error(self::$socket)) {
|
186 |
self::$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
187 |
socket_clear_error(self::$socket);
|
188 |
+
socket_connect(self::$socket, $this->getHost(), $this->getPort());
|
189 |
}
|
190 |
return self::$socket;
|
191 |
}
|
214 |
private function unwrappedOptions()
|
215 |
{
|
216 |
if (!$this->options instanceof ConfigurationInterface) {
|
217 |
+
try {
|
218 |
+
$this->options = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::unwrap($this->options);
|
219 |
+
} catch (\Exception $e) {
|
220 |
+
// Errors unwrapping CSM config defaults to disabling it
|
221 |
+
$this->options = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration(false, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_HOST, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_PORT);
|
222 |
+
}
|
223 |
}
|
224 |
return $this->options;
|
225 |
}
|
@@ -6,16 +6,19 @@ class Configuration implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Client
|
|
6 |
{
|
7 |
private $clientId;
|
8 |
private $enabled;
|
|
|
9 |
private $port;
|
10 |
/**
|
11 |
* Constructs a new Configuration object with the specified CSM options set.
|
12 |
*
|
13 |
* @param mixed $enabled
|
|
|
14 |
* @param string|int $port
|
15 |
* @param string $clientId
|
16 |
*/
|
17 |
-
public function __construct($enabled, $port, $clientId = '')
|
18 |
{
|
|
|
19 |
$this->port = filter_var($port, FILTER_VALIDATE_INT);
|
20 |
if ($this->port === false) {
|
21 |
throw new \InvalidArgumentException("CSM 'port' value must be an integer!");
|
@@ -38,6 +41,13 @@ class Configuration implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Client
|
|
38 |
{
|
39 |
return $this->clientId;
|
40 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
/**
|
42 |
* {@inheritdoc}
|
43 |
*/
|
@@ -50,6 +60,6 @@ class Configuration implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Client
|
|
50 |
*/
|
51 |
public function toArray()
|
52 |
{
|
53 |
-
return ['client_id' => $this->getClientId(), 'enabled' => $this->isEnabled(), 'port' => $this->getPort()];
|
54 |
}
|
55 |
}
|
6 |
{
|
7 |
private $clientId;
|
8 |
private $enabled;
|
9 |
+
private $host;
|
10 |
private $port;
|
11 |
/**
|
12 |
* Constructs a new Configuration object with the specified CSM options set.
|
13 |
*
|
14 |
* @param mixed $enabled
|
15 |
+
* @param string $host
|
16 |
* @param string|int $port
|
17 |
* @param string $clientId
|
18 |
*/
|
19 |
+
public function __construct($enabled, $host, $port, $clientId = '')
|
20 |
{
|
21 |
+
$this->host = $host;
|
22 |
$this->port = filter_var($port, FILTER_VALIDATE_INT);
|
23 |
if ($this->port === false) {
|
24 |
throw new \InvalidArgumentException("CSM 'port' value must be an integer!");
|
41 |
{
|
42 |
return $this->clientId;
|
43 |
}
|
44 |
+
/**
|
45 |
+
* /{@inheritdoc}
|
46 |
+
*/
|
47 |
+
public function getHost()
|
48 |
+
{
|
49 |
+
return $this->host;
|
50 |
+
}
|
51 |
/**
|
52 |
* {@inheritdoc}
|
53 |
*/
|
60 |
*/
|
61 |
public function toArray()
|
62 |
{
|
63 |
+
return ['client_id' => $this->getClientId(), 'enabled' => $this->isEnabled(), 'host' => $this->getHost(), 'port' => $this->getPort()];
|
64 |
}
|
65 |
}
|
@@ -4,7 +4,7 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring;
|
|
4 |
|
5 |
/**
|
6 |
* Provides access to client-side monitoring configuration options:
|
7 |
-
* 'client_id', 'enabled', 'port'
|
8 |
*/
|
9 |
interface ConfigurationInterface
|
10 |
{
|
@@ -20,6 +20,12 @@ interface ConfigurationInterface
|
|
20 |
* @return string|null
|
21 |
*/
|
22 |
public function getClientId();
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
/**
|
24 |
* Returns the configured port.
|
25 |
*
|
4 |
|
5 |
/**
|
6 |
* Provides access to client-side monitoring configuration options:
|
7 |
+
* 'client_id', 'enabled', 'host', 'port'
|
8 |
*/
|
9 |
interface ConfigurationInterface
|
10 |
{
|
20 |
* @return string|null
|
21 |
*/
|
22 |
public function getClientId();
|
23 |
+
/**
|
24 |
+
* Returns the configured host.
|
25 |
+
*
|
26 |
+
* @return string|null
|
27 |
+
*/
|
28 |
+
public function getHost();
|
29 |
/**
|
30 |
* Returns the configured port.
|
31 |
*
|
@@ -2,8 +2,10 @@
|
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring;
|
4 |
|
|
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Exception\ConfigurationException;
|
|
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
|
9 |
/**
|
@@ -40,75 +42,32 @@ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
|
|
40 |
* $config = $promise->wait();
|
41 |
* </code>
|
42 |
*/
|
43 |
-
class ConfigurationProvider
|
44 |
{
|
45 |
-
const CACHE_KEY = 'aws_cached_csm_config';
|
46 |
const DEFAULT_CLIENT_ID = '';
|
47 |
const DEFAULT_ENABLED = false;
|
|
|
48 |
const DEFAULT_PORT = 31000;
|
49 |
const ENV_CLIENT_ID = 'AWS_CSM_CLIENT_ID';
|
50 |
const ENV_ENABLED = 'AWS_CSM_ENABLED';
|
|
|
51 |
const ENV_PORT = 'AWS_CSM_PORT';
|
52 |
const ENV_PROFILE = 'AWS_PROFILE';
|
|
|
|
|
|
|
53 |
/**
|
54 |
-
*
|
55 |
-
*
|
56 |
-
*
|
57 |
-
*
|
58 |
-
*
|
59 |
-
*
|
60 |
-
* @param string|null $cacheKey (optional) Cache key to use
|
61 |
-
*
|
62 |
-
* @return callable
|
63 |
-
*/
|
64 |
-
public static function cache(callable $provider, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface $cache, $cacheKey = null)
|
65 |
-
{
|
66 |
-
$cacheKey = $cacheKey ?: self::CACHE_KEY;
|
67 |
-
return function () use($provider, $cache, $cacheKey) {
|
68 |
-
$found = $cache->get($cacheKey);
|
69 |
-
if ($found instanceof ConfigurationInterface) {
|
70 |
-
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for($found);
|
71 |
-
}
|
72 |
-
return $provider()->then(function (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationInterface $config) use($cache, $cacheKey) {
|
73 |
-
$cache->set($cacheKey, $config);
|
74 |
-
return $config;
|
75 |
-
});
|
76 |
-
};
|
77 |
-
}
|
78 |
-
/**
|
79 |
-
* Creates an aggregate credentials provider that invokes the provided
|
80 |
-
* variadic providers one after the other until a provider returns
|
81 |
-
* credentials.
|
82 |
-
*
|
83 |
-
* @return callable
|
84 |
-
*/
|
85 |
-
public static function chain()
|
86 |
-
{
|
87 |
-
$links = func_get_args();
|
88 |
-
if (empty($links)) {
|
89 |
-
throw new \InvalidArgumentException('No providers in chain');
|
90 |
-
}
|
91 |
-
return function () use($links) {
|
92 |
-
/** @var callable $parent */
|
93 |
-
$parent = array_shift($links);
|
94 |
-
$promise = $parent();
|
95 |
-
while ($next = array_shift($links)) {
|
96 |
-
$promise = $promise->otherwise($next);
|
97 |
-
}
|
98 |
-
return $promise;
|
99 |
-
};
|
100 |
-
}
|
101 |
-
/**
|
102 |
-
* Create a default CSM config provider that first checks for environment
|
103 |
-
* variables, then checks for a specified profile in ~/.aws/config, then
|
104 |
-
* checks for the "aws_csm" profile in ~/.aws/config, and failing those uses
|
105 |
-
* a default fallback set of configuration options.
|
106 |
*
|
107 |
* This provider is automatically wrapped in a memoize function that caches
|
108 |
* previously provided config options.
|
109 |
*
|
110 |
-
* @param array $config
|
111 |
-
* provider options.
|
112 |
*
|
113 |
* @return callable
|
114 |
*/
|
@@ -117,7 +76,7 @@ class ConfigurationProvider
|
|
117 |
$configProviders = [self::env(), self::ini(), self::fallback()];
|
118 |
$memo = self::memoize(call_user_func_array('self::chain', $configProviders));
|
119 |
if (isset($config['csm']) && $config['csm'] instanceof CacheInterface) {
|
120 |
-
return self::cache($memo, $config['csm'], self
|
121 |
}
|
122 |
return $memo;
|
123 |
}
|
@@ -132,9 +91,9 @@ class ConfigurationProvider
|
|
132 |
// Use credentials from environment variables, if available
|
133 |
$enabled = getenv(self::ENV_ENABLED);
|
134 |
if ($enabled !== false) {
|
135 |
-
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration($enabled, getenv(self::ENV_PORT) ?: self::DEFAULT_PORT, getenv(self::ENV_CLIENT_ID) ?: self::DEFAULT_CLIENT_ID));
|
136 |
}
|
137 |
-
return self::reject('Could not find environment variable CSM config' . ' in ' . self::ENV_ENABLED . '/' . self::ENV_PORT . '/' . self::ENV_CLIENT_ID);
|
138 |
};
|
139 |
}
|
140 |
/**
|
@@ -145,45 +104,30 @@ class ConfigurationProvider
|
|
145 |
public static function fallback()
|
146 |
{
|
147 |
return function () {
|
148 |
-
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration(self::DEFAULT_ENABLED, self::DEFAULT_PORT, self::DEFAULT_CLIENT_ID));
|
149 |
};
|
150 |
}
|
151 |
/**
|
152 |
-
*
|
153 |
-
*
|
154 |
-
*
|
155 |
-
*/
|
156 |
-
private static function getHomeDir()
|
157 |
-
{
|
158 |
-
// On Linux/Unix-like systems, use the HOME environment variable
|
159 |
-
if ($homeDir = getenv('HOME')) {
|
160 |
-
return $homeDir;
|
161 |
-
}
|
162 |
-
// Get the HOMEDRIVE and HOMEPATH values for Windows hosts
|
163 |
-
$homeDrive = getenv('HOMEDRIVE');
|
164 |
-
$homePath = getenv('HOMEPATH');
|
165 |
-
return $homeDrive && $homePath ? $homeDrive . $homePath : null;
|
166 |
-
}
|
167 |
-
/**
|
168 |
-
* CSM config provider that creates CSM config using an ini file stored
|
169 |
-
* in the current user's home directory.
|
170 |
*
|
171 |
* @param string|null $profile Profile to use. If not specified will use
|
172 |
-
* the "
|
173 |
* @param string|null $filename If provided, uses a custom filename rather
|
174 |
-
* than looking in the
|
175 |
*
|
176 |
* @return callable
|
177 |
*/
|
178 |
public static function ini($profile = null, $filename = null)
|
179 |
{
|
180 |
-
$filename = $filename ?: self::
|
181 |
$profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'aws_csm');
|
182 |
return function () use($profile, $filename) {
|
183 |
if (!is_readable($filename)) {
|
184 |
return self::reject("Cannot read CSM config from {$filename}");
|
185 |
}
|
186 |
-
$data = parse_ini_file($filename, true);
|
187 |
if ($data === false) {
|
188 |
return self::reject("Invalid config file: {$filename}");
|
189 |
}
|
@@ -193,6 +137,10 @@ class ConfigurationProvider
|
|
193 |
if (!isset($data[$profile]['csm_enabled'])) {
|
194 |
return self::reject("Required CSM config values not present in \n INI profile '{$profile}' ({$filename})");
|
195 |
}
|
|
|
|
|
|
|
|
|
196 |
// port is optional
|
197 |
if (empty($data[$profile]['csm_port'])) {
|
198 |
$data[$profile]['csm_port'] = self::DEFAULT_PORT;
|
@@ -201,49 +149,9 @@ class ConfigurationProvider
|
|
201 |
if (empty($data[$profile]['csm_client_id'])) {
|
202 |
$data[$profile]['csm_client_id'] = self::DEFAULT_CLIENT_ID;
|
203 |
}
|
204 |
-
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration($data[$profile]['csm_enabled'], $data[$profile]['csm_port'], $data[$profile]['csm_client_id']));
|
205 |
-
};
|
206 |
-
}
|
207 |
-
/**
|
208 |
-
* Wraps a CSM config provider and caches previously provided configuration.
|
209 |
-
*
|
210 |
-
* Ensures that cached configuration is refreshed when it expires.
|
211 |
-
*
|
212 |
-
* @param callable $provider CSM config provider function to wrap.
|
213 |
-
*
|
214 |
-
* @return callable
|
215 |
-
*/
|
216 |
-
public static function memoize(callable $provider)
|
217 |
-
{
|
218 |
-
return function () use($provider) {
|
219 |
-
static $result;
|
220 |
-
static $isConstant;
|
221 |
-
// Constant config will be returned constantly.
|
222 |
-
if ($isConstant) {
|
223 |
-
return $result;
|
224 |
-
}
|
225 |
-
// Create the initial promise that will be used as the cached value
|
226 |
-
// until it expires.
|
227 |
-
if (null === $result) {
|
228 |
-
$result = $provider();
|
229 |
-
}
|
230 |
-
// Return config and set flag that provider is already set
|
231 |
-
return $result->then(function (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationInterface $config) use(&$isConstant) {
|
232 |
-
$isConstant = true;
|
233 |
-
return $config;
|
234 |
-
});
|
235 |
};
|
236 |
}
|
237 |
-
/**
|
238 |
-
* Reject promise with standardized exception.
|
239 |
-
*
|
240 |
-
* @param $msg
|
241 |
-
* @return Promise\RejectedPromise
|
242 |
-
*/
|
243 |
-
private static function reject($msg)
|
244 |
-
{
|
245 |
-
return new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\RejectedPromise(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Exception\ConfigurationException($msg));
|
246 |
-
}
|
247 |
/**
|
248 |
* Unwraps a configuration object in whatever valid form it is in,
|
249 |
* always returning a ConfigurationInterface object.
|
@@ -264,8 +172,9 @@ class ConfigurationProvider
|
|
264 |
return $config;
|
265 |
} elseif (is_array($config) && isset($config['enabled'])) {
|
266 |
$client_id = isset($config['client_id']) ? $config['client_id'] : self::DEFAULT_CLIENT_ID;
|
|
|
267 |
$port = isset($config['port']) ? $config['port'] : self::DEFAULT_PORT;
|
268 |
-
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration($config['enabled'], $port, $client_id);
|
269 |
}
|
270 |
throw new \InvalidArgumentException('Not a valid CSM configuration ' . 'argument.');
|
271 |
}
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring;
|
4 |
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Exception\ConfigurationException;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface;
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
10 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
|
11 |
/**
|
42 |
* $config = $promise->wait();
|
43 |
* </code>
|
44 |
*/
|
45 |
+
class ConfigurationProvider extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface
|
46 |
{
|
|
|
47 |
const DEFAULT_CLIENT_ID = '';
|
48 |
const DEFAULT_ENABLED = false;
|
49 |
+
const DEFAULT_HOST = '127.0.0.1';
|
50 |
const DEFAULT_PORT = 31000;
|
51 |
const ENV_CLIENT_ID = 'AWS_CSM_CLIENT_ID';
|
52 |
const ENV_ENABLED = 'AWS_CSM_ENABLED';
|
53 |
+
const ENV_HOST = 'AWS_CSM_HOST';
|
54 |
const ENV_PORT = 'AWS_CSM_PORT';
|
55 |
const ENV_PROFILE = 'AWS_PROFILE';
|
56 |
+
public static $cacheKey = 'aws_cached_csm_config';
|
57 |
+
protected static $interfaceClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\ConfigurationInterface::class;
|
58 |
+
protected static $exceptionClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Exception\ConfigurationException::class;
|
59 |
/**
|
60 |
+
* Create a default config provider that first checks for environment
|
61 |
+
* variables, then checks for a specified profile in the environment-defined
|
62 |
+
* config file location (env variable is 'AWS_CONFIG_FILE', file location
|
63 |
+
* defaults to ~/.aws/config), then checks for the "default" profile in the
|
64 |
+
* environment-defined config file location, and failing those uses a default
|
65 |
+
* fallback set of configuration options.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
*
|
67 |
* This provider is automatically wrapped in a memoize function that caches
|
68 |
* previously provided config options.
|
69 |
*
|
70 |
+
* @param array $config
|
|
|
71 |
*
|
72 |
* @return callable
|
73 |
*/
|
76 |
$configProviders = [self::env(), self::ini(), self::fallback()];
|
77 |
$memo = self::memoize(call_user_func_array('self::chain', $configProviders));
|
78 |
if (isset($config['csm']) && $config['csm'] instanceof CacheInterface) {
|
79 |
+
return self::cache($memo, $config['csm'], self::$cacheKey);
|
80 |
}
|
81 |
return $memo;
|
82 |
}
|
91 |
// Use credentials from environment variables, if available
|
92 |
$enabled = getenv(self::ENV_ENABLED);
|
93 |
if ($enabled !== false) {
|
94 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration($enabled, getenv(self::ENV_HOST) ?: self::DEFAULT_HOST, getenv(self::ENV_PORT) ?: self::DEFAULT_PORT, getenv(self::ENV_CLIENT_ID) ?: self::DEFAULT_CLIENT_ID));
|
95 |
}
|
96 |
+
return self::reject('Could not find environment variable CSM config' . ' in ' . self::ENV_ENABLED . '/' . self::ENV_HOST . '/' . self::ENV_PORT . '/' . self::ENV_CLIENT_ID);
|
97 |
};
|
98 |
}
|
99 |
/**
|
104 |
public static function fallback()
|
105 |
{
|
106 |
return function () {
|
107 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration(self::DEFAULT_ENABLED, self::DEFAULT_HOST, self::DEFAULT_PORT, self::DEFAULT_CLIENT_ID));
|
108 |
};
|
109 |
}
|
110 |
/**
|
111 |
+
* Config provider that creates config using a config file whose location
|
112 |
+
* is specified by an environment variable 'AWS_CONFIG_FILE', defaulting to
|
113 |
+
* ~/.aws/config if not specified
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
*
|
115 |
* @param string|null $profile Profile to use. If not specified will use
|
116 |
+
* the "default" profile.
|
117 |
* @param string|null $filename If provided, uses a custom filename rather
|
118 |
+
* than looking in the default directory.
|
119 |
*
|
120 |
* @return callable
|
121 |
*/
|
122 |
public static function ini($profile = null, $filename = null)
|
123 |
{
|
124 |
+
$filename = $filename ?: self::getDefaultConfigFilename();
|
125 |
$profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'aws_csm');
|
126 |
return function () use($profile, $filename) {
|
127 |
if (!is_readable($filename)) {
|
128 |
return self::reject("Cannot read CSM config from {$filename}");
|
129 |
}
|
130 |
+
$data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($filename, true);
|
131 |
if ($data === false) {
|
132 |
return self::reject("Invalid config file: {$filename}");
|
133 |
}
|
137 |
if (!isset($data[$profile]['csm_enabled'])) {
|
138 |
return self::reject("Required CSM config values not present in \n INI profile '{$profile}' ({$filename})");
|
139 |
}
|
140 |
+
// host is optional
|
141 |
+
if (empty($data[$profile]['csm_host'])) {
|
142 |
+
$data[$profile]['csm_host'] = self::DEFAULT_HOST;
|
143 |
+
}
|
144 |
// port is optional
|
145 |
if (empty($data[$profile]['csm_port'])) {
|
146 |
$data[$profile]['csm_port'] = self::DEFAULT_PORT;
|
149 |
if (empty($data[$profile]['csm_client_id'])) {
|
150 |
$data[$profile]['csm_client_id'] = self::DEFAULT_CLIENT_ID;
|
151 |
}
|
152 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration($data[$profile]['csm_enabled'], $data[$profile]['csm_host'], $data[$profile]['csm_port'], $data[$profile]['csm_client_id']));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
153 |
};
|
154 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
/**
|
156 |
* Unwraps a configuration object in whatever valid form it is in,
|
157 |
* always returning a ConfigurationInterface object.
|
172 |
return $config;
|
173 |
} elseif (is_array($config) && isset($config['enabled'])) {
|
174 |
$client_id = isset($config['client_id']) ? $config['client_id'] : self::DEFAULT_CLIENT_ID;
|
175 |
+
$host = isset($config['host']) ? $config['host'] : self::DEFAULT_HOST;
|
176 |
$port = isset($config['port']) ? $config['port'] : self::DEFAULT_PORT;
|
177 |
+
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientSideMonitoring\Configuration($config['enabled'], $host, $port, $client_id);
|
178 |
}
|
179 |
throw new \InvalidArgumentException('Not a valid CSM configuration ' . 'argument.');
|
180 |
}
|
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient;
|
6 |
+
/**
|
7 |
+
* This client is used to interact with the **Amazon CloudFront** service.
|
8 |
+
*
|
9 |
+
* @method \Aws\Result createCloudFrontOriginAccessIdentity(array $args = [])
|
10 |
+
* @method \GuzzleHttp\Promise\Promise createCloudFrontOriginAccessIdentityAsync(array $args = [])
|
11 |
+
* @method \Aws\Result createDistribution(array $args = [])
|
12 |
+
* @method \GuzzleHttp\Promise\Promise createDistributionAsync(array $args = [])
|
13 |
+
* @method \Aws\Result createInvalidation(array $args = [])
|
14 |
+
* @method \GuzzleHttp\Promise\Promise createInvalidationAsync(array $args = [])
|
15 |
+
* @method \Aws\Result createStreamingDistribution(array $args = [])
|
16 |
+
* @method \GuzzleHttp\Promise\Promise createStreamingDistributionAsync(array $args = [])
|
17 |
+
* @method \Aws\Result deleteCloudFrontOriginAccessIdentity(array $args = [])
|
18 |
+
* @method \GuzzleHttp\Promise\Promise deleteCloudFrontOriginAccessIdentityAsync(array $args = [])
|
19 |
+
* @method \Aws\Result deleteDistribution(array $args = [])
|
20 |
+
* @method \GuzzleHttp\Promise\Promise deleteDistributionAsync(array $args = [])
|
21 |
+
* @method \Aws\Result deleteStreamingDistribution(array $args = [])
|
22 |
+
* @method \GuzzleHttp\Promise\Promise deleteStreamingDistributionAsync(array $args = [])
|
23 |
+
* @method \Aws\Result getCloudFrontOriginAccessIdentity(array $args = [])
|
24 |
+
* @method \GuzzleHttp\Promise\Promise getCloudFrontOriginAccessIdentityAsync(array $args = [])
|
25 |
+
* @method \Aws\Result getCloudFrontOriginAccessIdentityConfig(array $args = [])
|
26 |
+
* @method \GuzzleHttp\Promise\Promise getCloudFrontOriginAccessIdentityConfigAsync(array $args = [])
|
27 |
+
* @method \Aws\Result getDistribution(array $args = [])
|
28 |
+
* @method \GuzzleHttp\Promise\Promise getDistributionAsync(array $args = [])
|
29 |
+
* @method \Aws\Result getDistributionConfig(array $args = [])
|
30 |
+
* @method \GuzzleHttp\Promise\Promise getDistributionConfigAsync(array $args = [])
|
31 |
+
* @method \Aws\Result getInvalidation(array $args = [])
|
32 |
+
* @method \GuzzleHttp\Promise\Promise getInvalidationAsync(array $args = [])
|
33 |
+
* @method \Aws\Result getStreamingDistribution(array $args = [])
|
34 |
+
* @method \GuzzleHttp\Promise\Promise getStreamingDistributionAsync(array $args = [])
|
35 |
+
* @method \Aws\Result getStreamingDistributionConfig(array $args = [])
|
36 |
+
* @method \GuzzleHttp\Promise\Promise getStreamingDistributionConfigAsync(array $args = [])
|
37 |
+
* @method \Aws\Result listCloudFrontOriginAccessIdentities(array $args = [])
|
38 |
+
* @method \GuzzleHttp\Promise\Promise listCloudFrontOriginAccessIdentitiesAsync(array $args = [])
|
39 |
+
* @method \Aws\Result listDistributions(array $args = [])
|
40 |
+
* @method \GuzzleHttp\Promise\Promise listDistributionsAsync(array $args = [])
|
41 |
+
* @method \Aws\Result listDistributionsByWebACLId(array $args = [])
|
42 |
+
* @method \GuzzleHttp\Promise\Promise listDistributionsByWebACLIdAsync(array $args = [])
|
43 |
+
* @method \Aws\Result listInvalidations(array $args = [])
|
44 |
+
* @method \GuzzleHttp\Promise\Promise listInvalidationsAsync(array $args = [])
|
45 |
+
* @method \Aws\Result listStreamingDistributions(array $args = [])
|
46 |
+
* @method \GuzzleHttp\Promise\Promise listStreamingDistributionsAsync(array $args = [])
|
47 |
+
* @method \Aws\Result updateCloudFrontOriginAccessIdentity(array $args = [])
|
48 |
+
* @method \GuzzleHttp\Promise\Promise updateCloudFrontOriginAccessIdentityAsync(array $args = [])
|
49 |
+
* @method \Aws\Result updateDistribution(array $args = [])
|
50 |
+
* @method \GuzzleHttp\Promise\Promise updateDistributionAsync(array $args = [])
|
51 |
+
* @method \Aws\Result updateStreamingDistribution(array $args = [])
|
52 |
+
* @method \GuzzleHttp\Promise\Promise updateStreamingDistributionAsync(array $args = [])
|
53 |
+
* @method \Aws\Result createDistributionWithTags(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
54 |
+
* @method \GuzzleHttp\Promise\Promise createDistributionWithTagsAsync(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
55 |
+
* @method \Aws\Result createStreamingDistributionWithTags(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
56 |
+
* @method \GuzzleHttp\Promise\Promise createStreamingDistributionWithTagsAsync(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
57 |
+
* @method \Aws\Result listTagsForResource(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
58 |
+
* @method \GuzzleHttp\Promise\Promise listTagsForResourceAsync(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
59 |
+
* @method \Aws\Result tagResource(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
60 |
+
* @method \GuzzleHttp\Promise\Promise tagResourceAsync(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
61 |
+
* @method \Aws\Result untagResource(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
62 |
+
* @method \GuzzleHttp\Promise\Promise untagResourceAsync(array $args = []) (supported in versions 2016-08-01, 2016-08-20, 2016-09-07, 2016-09-29, 2016-11-25, 2017-03-25, 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
63 |
+
* @method \Aws\Result deleteServiceLinkedRole(array $args = []) (supported in versions 2017-03-25)
|
64 |
+
* @method \GuzzleHttp\Promise\Promise deleteServiceLinkedRoleAsync(array $args = []) (supported in versions 2017-03-25)
|
65 |
+
* @method \Aws\Result createFieldLevelEncryptionConfig(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
66 |
+
* @method \GuzzleHttp\Promise\Promise createFieldLevelEncryptionConfigAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
67 |
+
* @method \Aws\Result createFieldLevelEncryptionProfile(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
68 |
+
* @method \GuzzleHttp\Promise\Promise createFieldLevelEncryptionProfileAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
69 |
+
* @method \Aws\Result createPublicKey(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
70 |
+
* @method \GuzzleHttp\Promise\Promise createPublicKeyAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
71 |
+
* @method \Aws\Result deleteFieldLevelEncryptionConfig(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
72 |
+
* @method \GuzzleHttp\Promise\Promise deleteFieldLevelEncryptionConfigAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
73 |
+
* @method \Aws\Result deleteFieldLevelEncryptionProfile(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
74 |
+
* @method \GuzzleHttp\Promise\Promise deleteFieldLevelEncryptionProfileAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
75 |
+
* @method \Aws\Result deletePublicKey(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
76 |
+
* @method \GuzzleHttp\Promise\Promise deletePublicKeyAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
77 |
+
* @method \Aws\Result getFieldLevelEncryption(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
78 |
+
* @method \GuzzleHttp\Promise\Promise getFieldLevelEncryptionAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
79 |
+
* @method \Aws\Result getFieldLevelEncryptionConfig(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
80 |
+
* @method \GuzzleHttp\Promise\Promise getFieldLevelEncryptionConfigAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
81 |
+
* @method \Aws\Result getFieldLevelEncryptionProfile(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
82 |
+
* @method \GuzzleHttp\Promise\Promise getFieldLevelEncryptionProfileAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
83 |
+
* @method \Aws\Result getFieldLevelEncryptionProfileConfig(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
84 |
+
* @method \GuzzleHttp\Promise\Promise getFieldLevelEncryptionProfileConfigAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
85 |
+
* @method \Aws\Result getPublicKey(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
86 |
+
* @method \GuzzleHttp\Promise\Promise getPublicKeyAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
87 |
+
* @method \Aws\Result getPublicKeyConfig(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
88 |
+
* @method \GuzzleHttp\Promise\Promise getPublicKeyConfigAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
89 |
+
* @method \Aws\Result listFieldLevelEncryptionConfigs(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
90 |
+
* @method \GuzzleHttp\Promise\Promise listFieldLevelEncryptionConfigsAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
91 |
+
* @method \Aws\Result listFieldLevelEncryptionProfiles(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
92 |
+
* @method \GuzzleHttp\Promise\Promise listFieldLevelEncryptionProfilesAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
93 |
+
* @method \Aws\Result listPublicKeys(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
94 |
+
* @method \GuzzleHttp\Promise\Promise listPublicKeysAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
95 |
+
* @method \Aws\Result updateFieldLevelEncryptionConfig(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
96 |
+
* @method \GuzzleHttp\Promise\Promise updateFieldLevelEncryptionConfigAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
97 |
+
* @method \Aws\Result updateFieldLevelEncryptionProfile(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
98 |
+
* @method \GuzzleHttp\Promise\Promise updateFieldLevelEncryptionProfileAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
99 |
+
* @method \Aws\Result updatePublicKey(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
100 |
+
* @method \GuzzleHttp\Promise\Promise updatePublicKeyAsync(array $args = []) (supported in versions 2017-10-30, 2018-06-18, 2018-11-05, 2019-03-26)
|
101 |
+
*/
|
102 |
+
class CloudFrontClient extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient
|
103 |
+
{
|
104 |
+
/**
|
105 |
+
* Create a signed Amazon CloudFront URL.
|
106 |
+
*
|
107 |
+
* This method accepts an array of configuration options:
|
108 |
+
*
|
109 |
+
* - url: (string) URL of the resource being signed (can include query
|
110 |
+
* string and wildcards). For example: rtmp://s5c39gqb8ow64r.cloudfront.net/videos/mp3_name.mp3
|
111 |
+
* http://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes
|
112 |
+
* - policy: (string) JSON policy. Use this option when creating a signed
|
113 |
+
* URL for a custom policy.
|
114 |
+
* - expires: (int) UTC Unix timestamp used when signing with a canned
|
115 |
+
* policy. Not required when passing a custom 'policy' option.
|
116 |
+
* - key_pair_id: (string) The ID of the key pair used to sign CloudFront
|
117 |
+
* URLs for private distributions.
|
118 |
+
* - private_key: (string) The filepath ot the private key used to sign
|
119 |
+
* CloudFront URLs for private distributions.
|
120 |
+
*
|
121 |
+
* @param array $options Array of configuration options used when signing
|
122 |
+
*
|
123 |
+
* @return string Signed URL with authentication parameters
|
124 |
+
* @throws \InvalidArgumentException if url, key_pair_id, or private_key
|
125 |
+
* were not specified.
|
126 |
+
* @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithStreamingDistributions.html
|
127 |
+
*/
|
128 |
+
public function getSignedUrl(array $options)
|
129 |
+
{
|
130 |
+
foreach (['url', 'key_pair_id', 'private_key'] as $required) {
|
131 |
+
if (!isset($options[$required])) {
|
132 |
+
throw new \InvalidArgumentException("{$required} is required");
|
133 |
+
}
|
134 |
+
}
|
135 |
+
$urlSigner = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront\UrlSigner($options['key_pair_id'], $options['private_key']);
|
136 |
+
return $urlSigner->getSignedUrl($options['url'], isset($options['expires']) ? $options['expires'] : null, isset($options['policy']) ? $options['policy'] : null);
|
137 |
+
}
|
138 |
+
/**
|
139 |
+
* Create a signed Amazon CloudFront cookie.
|
140 |
+
*
|
141 |
+
* This method accepts an array of configuration options:
|
142 |
+
*
|
143 |
+
* - url: (string) URL of the resource being signed (can include query
|
144 |
+
* string and wildcards). For example: http://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes
|
145 |
+
* - policy: (string) JSON policy. Use this option when creating a signed
|
146 |
+
* URL for a custom policy.
|
147 |
+
* - expires: (int) UTC Unix timestamp used when signing with a canned
|
148 |
+
* policy. Not required when passing a custom 'policy' option.
|
149 |
+
* - key_pair_id: (string) The ID of the key pair used to sign CloudFront
|
150 |
+
* URLs for private distributions.
|
151 |
+
* - private_key: (string) The filepath ot the private key used to sign
|
152 |
+
* CloudFront URLs for private distributions.
|
153 |
+
*
|
154 |
+
* @param array $options Array of configuration options used when signing
|
155 |
+
*
|
156 |
+
* @return array Key => value pairs of signed cookies to set
|
157 |
+
* @throws \InvalidArgumentException if url, key_pair_id, or private_key
|
158 |
+
* were not specified.
|
159 |
+
* @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithStreamingDistributions.html
|
160 |
+
*/
|
161 |
+
public function getSignedCookie(array $options)
|
162 |
+
{
|
163 |
+
foreach (['key_pair_id', 'private_key'] as $required) {
|
164 |
+
if (!isset($options[$required])) {
|
165 |
+
throw new \InvalidArgumentException("{$required} is required");
|
166 |
+
}
|
167 |
+
}
|
168 |
+
$cookieSigner = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront\CookieSigner($options['key_pair_id'], $options['private_key']);
|
169 |
+
return $cookieSigner->getSignedCookie(isset($options['url']) ? $options['url'] : null, isset($options['expires']) ? $options['expires'] : null, isset($options['policy']) ? $options['policy'] : null);
|
170 |
+
}
|
171 |
+
}
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront;
|
4 |
+
|
5 |
+
class CookieSigner
|
6 |
+
{
|
7 |
+
/** @var Signer */
|
8 |
+
private $signer;
|
9 |
+
private static $schemes = ['http' => true, 'https' => true];
|
10 |
+
/**
|
11 |
+
* @param $keyPairId string ID of the key pair
|
12 |
+
* @param $privateKey string Path to the private key used for signing
|
13 |
+
*
|
14 |
+
* @throws \RuntimeException if the openssl extension is missing
|
15 |
+
* @throws \InvalidArgumentException if the private key cannot be found.
|
16 |
+
*/
|
17 |
+
public function __construct($keyPairId, $privateKey)
|
18 |
+
{
|
19 |
+
$this->signer = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront\Signer($keyPairId, $privateKey);
|
20 |
+
}
|
21 |
+
/**
|
22 |
+
* Create a signed Amazon CloudFront Cookie.
|
23 |
+
*
|
24 |
+
* @param string $url URL to sign (can include query string
|
25 |
+
* and wildcards). Not required
|
26 |
+
* when passing a custom $policy.
|
27 |
+
* @param string|integer|null $expires UTC Unix timestamp used when signing
|
28 |
+
* with a canned policy. Not required
|
29 |
+
* when passing a custom $policy.
|
30 |
+
* @param string $policy JSON policy. Use this option when
|
31 |
+
* creating a signed cookie for a custom
|
32 |
+
* policy.
|
33 |
+
*
|
34 |
+
* @return array The authenticated cookie parameters
|
35 |
+
* @throws \InvalidArgumentException if the URL provided is invalid
|
36 |
+
* @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html
|
37 |
+
*/
|
38 |
+
public function getSignedCookie($url = null, $expires = null, $policy = null)
|
39 |
+
{
|
40 |
+
if ($url) {
|
41 |
+
$this->validateUrl($url);
|
42 |
+
}
|
43 |
+
$cookieParameters = [];
|
44 |
+
$signature = $this->signer->getSignature($url, $expires, $policy);
|
45 |
+
foreach ($signature as $key => $value) {
|
46 |
+
$cookieParameters["CloudFront-{$key}"] = $value;
|
47 |
+
}
|
48 |
+
return $cookieParameters;
|
49 |
+
}
|
50 |
+
private function validateUrl($url)
|
51 |
+
{
|
52 |
+
$scheme = str_replace('*', '', explode('://', $url)[0]);
|
53 |
+
if (empty(self::$schemes[strtolower($scheme)])) {
|
54 |
+
throw new \InvalidArgumentException('Invalid or missing URI scheme');
|
55 |
+
}
|
56 |
+
}
|
57 |
+
}
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront\Exception;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException;
|
6 |
+
/**
|
7 |
+
* Represents an error interacting with the Amazon CloudFront service.
|
8 |
+
*/
|
9 |
+
class CloudFrontException extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException
|
10 |
+
{
|
11 |
+
}
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @internal
|
7 |
+
*/
|
8 |
+
class Signer
|
9 |
+
{
|
10 |
+
private $keyPairId;
|
11 |
+
private $pkHandle;
|
12 |
+
/**
|
13 |
+
* A signer for creating the signature values used in CloudFront signed URLs
|
14 |
+
* and signed cookies.
|
15 |
+
*
|
16 |
+
* @param $keyPairId string ID of the key pair
|
17 |
+
* @param $privateKey string Path to the private key used for signing
|
18 |
+
* @param $passphrase string Passphrase to private key file, if one exists
|
19 |
+
*
|
20 |
+
* @throws \RuntimeException if the openssl extension is missing
|
21 |
+
* @throws \InvalidArgumentException if the private key cannot be found.
|
22 |
+
*/
|
23 |
+
public function __construct($keyPairId, $privateKey, $passphrase = "")
|
24 |
+
{
|
25 |
+
if (!extension_loaded('openssl')) {
|
26 |
+
//@codeCoverageIgnoreStart
|
27 |
+
throw new \RuntimeException('The openssl extension is required to ' . 'sign CloudFront urls.');
|
28 |
+
//@codeCoverageIgnoreEnd
|
29 |
+
}
|
30 |
+
$this->keyPairId = $keyPairId;
|
31 |
+
if (!($this->pkHandle = openssl_pkey_get_private($privateKey, $passphrase))) {
|
32 |
+
if (!file_exists($privateKey)) {
|
33 |
+
throw new \InvalidArgumentException("PK file not found: {$privateKey}");
|
34 |
+
} else {
|
35 |
+
$this->pkHandle = openssl_pkey_get_private("file://{$privateKey}", $passphrase);
|
36 |
+
if (!$this->pkHandle) {
|
37 |
+
throw new \InvalidArgumentException(openssl_error_string());
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
41 |
+
}
|
42 |
+
public function __destruct()
|
43 |
+
{
|
44 |
+
$this->pkHandle && openssl_pkey_free($this->pkHandle);
|
45 |
+
}
|
46 |
+
/**
|
47 |
+
* Create the values used to construct signed URLs and cookies.
|
48 |
+
*
|
49 |
+
* @param string $resource The CloudFront resource to which
|
50 |
+
* this signature will grant access.
|
51 |
+
* Not used when a custom policy is
|
52 |
+
* provided.
|
53 |
+
* @param string|integer|null $expires UTC Unix timestamp used when
|
54 |
+
* signing with a canned policy.
|
55 |
+
* Not required when passing a
|
56 |
+
* custom $policy.
|
57 |
+
* @param string $policy JSON policy. Use this option when
|
58 |
+
* creating a signature for a custom
|
59 |
+
* policy.
|
60 |
+
*
|
61 |
+
* @return array The values needed to construct a signed URL or cookie
|
62 |
+
* @throws \InvalidArgumentException when not provided either a policy or a
|
63 |
+
* resource and a expires
|
64 |
+
*
|
65 |
+
* @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html
|
66 |
+
*/
|
67 |
+
public function getSignature($resource = null, $expires = null, $policy = null)
|
68 |
+
{
|
69 |
+
$signatureHash = [];
|
70 |
+
if ($policy) {
|
71 |
+
$policy = preg_replace('/\\s/s', '', $policy);
|
72 |
+
$signatureHash['Policy'] = $this->encode($policy);
|
73 |
+
} elseif ($resource && $expires) {
|
74 |
+
$expires = (int) $expires;
|
75 |
+
// Handle epoch passed as string
|
76 |
+
$policy = $this->createCannedPolicy($resource, $expires);
|
77 |
+
$signatureHash['Expires'] = $expires;
|
78 |
+
} else {
|
79 |
+
throw new \InvalidArgumentException('Either a policy or a resource' . ' and an expiration time must be provided.');
|
80 |
+
}
|
81 |
+
$signatureHash['Signature'] = $this->encode($this->sign($policy));
|
82 |
+
$signatureHash['Key-Pair-Id'] = $this->keyPairId;
|
83 |
+
return $signatureHash;
|
84 |
+
}
|
85 |
+
private function createCannedPolicy($resource, $expiration)
|
86 |
+
{
|
87 |
+
return json_encode(['Statement' => [['Resource' => $resource, 'Condition' => ['DateLessThan' => ['AWS:EpochTime' => $expiration]]]]], JSON_UNESCAPED_SLASHES);
|
88 |
+
}
|
89 |
+
private function sign($policy)
|
90 |
+
{
|
91 |
+
$signature = '';
|
92 |
+
openssl_sign($policy, $signature, $this->pkHandle);
|
93 |
+
return $signature;
|
94 |
+
}
|
95 |
+
private function encode($policy)
|
96 |
+
{
|
97 |
+
return strtr(base64_encode($policy), '+=/', '-_~');
|
98 |
+
}
|
99 |
+
}
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface;
|
8 |
+
/**
|
9 |
+
* Creates signed URLs for Amazon CloudFront resources.
|
10 |
+
*/
|
11 |
+
class UrlSigner
|
12 |
+
{
|
13 |
+
private $signer;
|
14 |
+
/**
|
15 |
+
* @param $keyPairId string ID of the key pair
|
16 |
+
* @param $privateKey string Path to the private key used for signing
|
17 |
+
*
|
18 |
+
* @throws \RuntimeException if the openssl extension is missing
|
19 |
+
* @throws \InvalidArgumentException if the private key cannot be found.
|
20 |
+
*/
|
21 |
+
public function __construct($keyPairId, $privateKey)
|
22 |
+
{
|
23 |
+
$this->signer = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CloudFront\Signer($keyPairId, $privateKey);
|
24 |
+
}
|
25 |
+
/**
|
26 |
+
* Create a signed Amazon CloudFront URL.
|
27 |
+
*
|
28 |
+
* Keep in mind that URLs meant for use in media/flash players may have
|
29 |
+
* different requirements for URL formats (e.g. some require that the
|
30 |
+
* extension be removed, some require the file name to be prefixed
|
31 |
+
* - mp4:<path>, some require you to add "/cfx/st" into your URL).
|
32 |
+
*
|
33 |
+
* @param string $url URL to sign (can include query
|
34 |
+
* string string and wildcards)
|
35 |
+
* @param string|integer|null $expires UTC Unix timestamp used when signing
|
36 |
+
* with a canned policy. Not required
|
37 |
+
* when passing a custom $policy.
|
38 |
+
* @param string $policy JSON policy. Use this option when
|
39 |
+
* creating a signed URL for a custom
|
40 |
+
* policy.
|
41 |
+
*
|
42 |
+
* @return string The file URL with authentication parameters
|
43 |
+
* @throws \InvalidArgumentException if the URL provided is invalid
|
44 |
+
* @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/WorkingWithStreamingDistributions.html
|
45 |
+
*/
|
46 |
+
public function getSignedUrl($url, $expires = null, $policy = null)
|
47 |
+
{
|
48 |
+
// Determine the scheme of the url
|
49 |
+
$urlSections = explode('://', $url);
|
50 |
+
if (count($urlSections) < 2) {
|
51 |
+
throw new \InvalidArgumentException("Invalid URL: {$url}");
|
52 |
+
}
|
53 |
+
// Get the real scheme by removing wildcards from the scheme
|
54 |
+
$scheme = str_replace('*', '', $urlSections[0]);
|
55 |
+
$uri = new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri($scheme . '://' . $urlSections[1]);
|
56 |
+
$query = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\parse_query($uri->getQuery(), PHP_QUERY_RFC3986);
|
57 |
+
$signature = $this->signer->getSignature($this->createResource($scheme, (string) $uri), $expires, $policy);
|
58 |
+
$uri = $uri->withQuery(http_build_query($query + $signature, null, '&', PHP_QUERY_RFC3986));
|
59 |
+
return $scheme === 'rtmp' ? $this->createRtmpUrl($uri) : (string) $uri;
|
60 |
+
}
|
61 |
+
private function createRtmpUrl(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface $uri)
|
62 |
+
{
|
63 |
+
// Use a relative URL when creating Flash player URLs
|
64 |
+
$result = ltrim($uri->getPath(), '/');
|
65 |
+
if ($query = $uri->getQuery()) {
|
66 |
+
$result .= '?' . $query;
|
67 |
+
}
|
68 |
+
return $result;
|
69 |
+
}
|
70 |
+
/**
|
71 |
+
* @param $scheme
|
72 |
+
* @param $url
|
73 |
+
*
|
74 |
+
* @return string
|
75 |
+
*/
|
76 |
+
private function createResource($scheme, $url)
|
77 |
+
{
|
78 |
+
switch ($scheme) {
|
79 |
+
case 'http':
|
80 |
+
case 'http*':
|
81 |
+
case 'https':
|
82 |
+
return $url;
|
83 |
+
case 'rtmp':
|
84 |
+
$parts = parse_url($url);
|
85 |
+
$pathParts = pathinfo($parts['path']);
|
86 |
+
$resource = ltrim($pathParts['dirname'] . '/' . $pathParts['basename'], '/');
|
87 |
+
// Add a query string if present.
|
88 |
+
if (isset($parts['query'])) {
|
89 |
+
$resource .= "?{$parts['query']}";
|
90 |
+
}
|
91 |
+
return $resource;
|
92 |
+
}
|
93 |
+
throw new \InvalidArgumentException("Invalid URI scheme: {$scheme}. " . "Scheme must be one of: http, https, or rtmp");
|
94 |
+
}
|
95 |
+
}
|
@@ -29,6 +29,9 @@ class Command implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInter
|
|
29 |
if (!isset($this->data['@http'])) {
|
30 |
$this->data['@http'] = [];
|
31 |
}
|
|
|
|
|
|
|
32 |
}
|
33 |
public function __clone()
|
34 |
{
|
29 |
if (!isset($this->data['@http'])) {
|
30 |
$this->data['@http'] = [];
|
31 |
}
|
32 |
+
if (!isset($this->data['@context'])) {
|
33 |
+
$this->data['@context'] = [];
|
34 |
+
}
|
35 |
}
|
36 |
public function __clone()
|
37 |
{
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
4 |
+
|
5 |
+
interface ConfigurationProviderInterface
|
6 |
+
{
|
7 |
+
/**
|
8 |
+
* Create a default config provider
|
9 |
+
*
|
10 |
+
* @param array $config
|
11 |
+
* @return callable
|
12 |
+
*/
|
13 |
+
public static function defaultProvider(array $config = []);
|
14 |
+
}
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Result;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sts\StsClient;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
10 |
+
/**
|
11 |
+
* Credential provider that provides credentials via assuming a role with a web identity
|
12 |
+
* More Information, see: https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-sts-2011-06-15.html#assumerolewithwebidentity
|
13 |
+
*/
|
14 |
+
class AssumeRoleWithWebIdentityCredentialProvider
|
15 |
+
{
|
16 |
+
const ERROR_MSG = "Missing required 'AssumeRoleWithWebIdentityCredentialProvider' configuration option: ";
|
17 |
+
const ENV_RETRIES = 'AWS_METADATA_SERVICE_NUM_ATTEMPTS';
|
18 |
+
/** @var string */
|
19 |
+
private $tokenFile;
|
20 |
+
/** @var string */
|
21 |
+
private $arn;
|
22 |
+
/** @var string */
|
23 |
+
private $session;
|
24 |
+
/** @var StsClient */
|
25 |
+
private $client;
|
26 |
+
/** @var integer */
|
27 |
+
private $retries;
|
28 |
+
/** @var integer */
|
29 |
+
private $attempts;
|
30 |
+
/**
|
31 |
+
* The constructor attempts to load config from environment variables.
|
32 |
+
* If not set, the following config options are used:
|
33 |
+
* - WebIdentityTokenFile: full path of token filename
|
34 |
+
* - RoleArn: arn of role to be assumed
|
35 |
+
* - SessionName: (optional) set by SDK if not provided
|
36 |
+
*
|
37 |
+
* @param array $config Configuration options
|
38 |
+
* @throws \InvalidArgumentException
|
39 |
+
*/
|
40 |
+
public function __construct(array $config = [])
|
41 |
+
{
|
42 |
+
if (!isset($config['RoleArn'])) {
|
43 |
+
throw new \InvalidArgumentException(self::ERROR_MSG . "'RoleArn'.");
|
44 |
+
}
|
45 |
+
$this->arn = $config['RoleArn'];
|
46 |
+
if (!isset($config['WebIdentityTokenFile'])) {
|
47 |
+
throw new \InvalidArgumentException(self::ERROR_MSG . "'WebIdentityTokenFile'.");
|
48 |
+
}
|
49 |
+
$this->tokenFile = $config['WebIdentityTokenFile'];
|
50 |
+
if (!preg_match("/^\\w\\:|^\\/|^\\\\/", $this->tokenFile)) {
|
51 |
+
throw new \InvalidArgumentException("'WebIdentityTokenFile' must be an absolute path.");
|
52 |
+
}
|
53 |
+
$this->retries = (int) getenv(self::ENV_RETRIES) ?: (isset($config['retries']) ? $config['retries'] : 3);
|
54 |
+
$this->attempts = 0;
|
55 |
+
$this->session = isset($config['SessionName']) ? $config['SessionName'] : 'aws-sdk-php-' . round(microtime(true) * 1000);
|
56 |
+
$region = isset($config['region']) ? $config['region'] : 'us-east-1';
|
57 |
+
if (isset($config['client'])) {
|
58 |
+
$this->client = $config['client'];
|
59 |
+
} else {
|
60 |
+
$this->client = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sts\StsClient(['credentials' => false, 'region' => $region, 'version' => 'latest']);
|
61 |
+
}
|
62 |
+
}
|
63 |
+
/**
|
64 |
+
* Loads assume role with web identity credentials.
|
65 |
+
*
|
66 |
+
* @return Promise\PromiseInterface
|
67 |
+
*/
|
68 |
+
public function __invoke()
|
69 |
+
{
|
70 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\coroutine(function () {
|
71 |
+
$client = $this->client;
|
72 |
+
$result = null;
|
73 |
+
while ($result == null) {
|
74 |
+
try {
|
75 |
+
$token = file_get_contents($this->tokenFile);
|
76 |
+
} catch (\Exception $exception) {
|
77 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException("Error reading WebIdentityTokenFile from " . $this->tokenFile, 0, $exception);
|
78 |
+
}
|
79 |
+
$assumeParams = ['RoleArn' => $this->arn, 'RoleSessionName' => $this->session, 'WebIdentityToken' => $token];
|
80 |
+
try {
|
81 |
+
$result = $client->assumeRoleWithWebIdentity($assumeParams);
|
82 |
+
} catch (AwsException $e) {
|
83 |
+
if ($e->getAwsErrorCode() == 'InvalidIdentityToken') {
|
84 |
+
if ($this->attempts < $this->retries) {
|
85 |
+
sleep(pow(1.2, $this->attempts));
|
86 |
+
} else {
|
87 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException("InvalidIdentityToken, retries exhausted");
|
88 |
+
}
|
89 |
+
} else {
|
90 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException("Error assuming role from web identity credentials", 0, $e);
|
91 |
+
}
|
92 |
+
} catch (\Exception $e) {
|
93 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException("Error retrieving web identity credentials: " . $e->getMessage() . " (" . $e->getCode() . ")");
|
94 |
+
}
|
95 |
+
$this->attempts++;
|
96 |
+
}
|
97 |
+
(yield $this->client->createCredentials($result));
|
98 |
+
});
|
99 |
+
}
|
100 |
+
}
|
@@ -3,8 +3,10 @@
|
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials;
|
4 |
|
5 |
use Aws;
|
|
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException;
|
|
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
9 |
/**
|
10 |
* Credential providers are functions that accept no arguments and return a
|
@@ -42,17 +44,22 @@ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
|
42 |
*/
|
43 |
class CredentialProvider
|
44 |
{
|
|
|
45 |
const ENV_KEY = 'AWS_ACCESS_KEY_ID';
|
|
|
|
|
46 |
const ENV_SECRET = 'AWS_SECRET_ACCESS_KEY';
|
47 |
const ENV_SESSION = 'AWS_SESSION_TOKEN';
|
48 |
-
const
|
49 |
/**
|
50 |
* Create a default credential provider that first checks for environment
|
51 |
* variables, then checks for the "default" profile in ~/.aws/credentials,
|
52 |
* then checks for "profile default" profile in ~/.aws/config (which is
|
53 |
* the default profile of AWS CLI), then tries to make a GET Request to
|
54 |
-
* fetch credentials if Ecs environment variable is presented,
|
55 |
-
*
|
|
|
|
|
56 |
*
|
57 |
* This provider is automatically wrapped in a memoize function that caches
|
58 |
* previously provided credentials.
|
@@ -64,9 +71,22 @@ class CredentialProvider
|
|
64 |
*/
|
65 |
public static function defaultProvider(array $config = [])
|
66 |
{
|
67 |
-
$
|
68 |
-
$
|
69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
}
|
71 |
/**
|
72 |
* Create a credential provider function from a set of static credentials.
|
@@ -153,8 +173,6 @@ class CredentialProvider
|
|
153 |
* instance of Aws\CacheInterface. Forwards calls when no credentials found
|
154 |
* in cache and updates cache with the results.
|
155 |
*
|
156 |
-
* Defaults to using a simple file-based cache when none provided.
|
157 |
-
*
|
158 |
* @param callable $provider Credentials provider function to wrap
|
159 |
* @param CacheInterface $cache Cache to store credentials
|
160 |
* @param string|null $cacheKey (optional) Cache key to use
|
@@ -231,6 +249,49 @@ class CredentialProvider
|
|
231 |
{
|
232 |
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\AssumeRoleCredentialProvider($config);
|
233 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
/**
|
235 |
* Credentials provider that creates credentials using an ini file stored
|
236 |
* in the current user's home directory.
|
@@ -239,24 +300,51 @@ class CredentialProvider
|
|
239 |
* the "default" profile in "~/.aws/credentials".
|
240 |
* @param string|null $filename If provided, uses a custom filename rather
|
241 |
* than looking in the home directory.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
242 |
*
|
243 |
* @return callable
|
244 |
*/
|
245 |
-
public static function ini($profile = null, $filename = null)
|
246 |
{
|
247 |
$filename = $filename ?: self::getHomeDir() . '/.aws/credentials';
|
248 |
$profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
|
249 |
-
return function () use($profile, $filename) {
|
|
|
|
|
|
|
250 |
if (!is_readable($filename)) {
|
251 |
return self::reject("Cannot read credentials from {$filename}");
|
252 |
}
|
253 |
-
$data =
|
254 |
if ($data === false) {
|
255 |
return self::reject("Invalid credentials file: {$filename}");
|
256 |
}
|
257 |
if (!isset($data[$profile])) {
|
258 |
return self::reject("'{$profile}' not found in credentials file");
|
259 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
260 |
if (!isset($data[$profile]['aws_access_key_id']) || !isset($data[$profile]['aws_secret_access_key'])) {
|
261 |
return self::reject("No credentials present in INI profile " . "'{$profile}' ({$filename})");
|
262 |
}
|
@@ -267,40 +355,92 @@ class CredentialProvider
|
|
267 |
};
|
268 |
}
|
269 |
/**
|
270 |
-
*
|
271 |
-
* in
|
272 |
-
* - credentials from environment variables
|
273 |
-
* - 'default' profile in '.aws/credentials' file
|
274 |
-
* - 'profile default' profile in '.aws/config' file
|
275 |
*
|
276 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
277 |
*/
|
278 |
-
|
279 |
{
|
280 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
281 |
}
|
282 |
/**
|
283 |
-
*
|
284 |
-
* for the remote endpoints such as EC2 or ECS Roles.
|
285 |
-
*
|
286 |
-
* @param array $config Array of configuration data.
|
287 |
*
|
288 |
-
* @return
|
289 |
-
* @see Aws\Credentials\InstanceProfileProvider for $config details.
|
290 |
-
* @see Aws\Credentials\EcsCredentialProvider for $config details.
|
291 |
*/
|
292 |
-
private static function
|
293 |
{
|
294 |
-
|
295 |
-
|
|
|
|
|
|
|
296 |
}
|
297 |
-
$
|
298 |
-
if (isset($
|
299 |
-
|
300 |
-
|
301 |
-
|
|
|
|
|
|
|
|
|
302 |
}
|
303 |
-
|
|
|
|
|
304 |
}
|
305 |
/**
|
306 |
* Gets the environment's HOME directory if available.
|
@@ -318,6 +458,49 @@ class CredentialProvider
|
|
318 |
$homePath = getenv('HOMEPATH');
|
319 |
return $homeDrive && $homePath ? $homeDrive . $homePath : null;
|
320 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
321 |
private static function reject($msg)
|
322 |
{
|
323 |
return new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\RejectedPromise(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($msg));
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials;
|
4 |
|
5 |
use Aws;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sts\StsClient;
|
10 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
11 |
/**
|
12 |
* Credential providers are functions that accept no arguments and return a
|
44 |
*/
|
45 |
class CredentialProvider
|
46 |
{
|
47 |
+
const ENV_ARN = 'AWS_ROLE_ARN';
|
48 |
const ENV_KEY = 'AWS_ACCESS_KEY_ID';
|
49 |
+
const ENV_PROFILE = 'AWS_PROFILE';
|
50 |
+
const ENV_ROLE_SESSION_NAME = 'AWS_ROLE_SESSION_NAME';
|
51 |
const ENV_SECRET = 'AWS_SECRET_ACCESS_KEY';
|
52 |
const ENV_SESSION = 'AWS_SESSION_TOKEN';
|
53 |
+
const ENV_TOKEN_FILE = 'AWS_WEB_IDENTITY_TOKEN_FILE';
|
54 |
/**
|
55 |
* Create a default credential provider that first checks for environment
|
56 |
* variables, then checks for the "default" profile in ~/.aws/credentials,
|
57 |
* then checks for "profile default" profile in ~/.aws/config (which is
|
58 |
* the default profile of AWS CLI), then tries to make a GET Request to
|
59 |
+
* fetch credentials if Ecs environment variable is presented, then checks
|
60 |
+
* for credential_process in the "default" profile in ~/.aws/credentials,
|
61 |
+
* then for credential_process in the "default profile" profile in
|
62 |
+
* ~/.aws/config, and finally checks for EC2 instance profile credentials.
|
63 |
*
|
64 |
* This provider is automatically wrapped in a memoize function that caches
|
65 |
* previously provided credentials.
|
71 |
*/
|
72 |
public static function defaultProvider(array $config = [])
|
73 |
{
|
74 |
+
$cacheable = ['web_identity', 'ecs', 'process_credentials', 'process_config', 'instance'];
|
75 |
+
$defaultChain = ['env' => self::env(), 'web_identity' => self::assumeRoleWithWebIdentityCredentialProvider($config), 'ini' => self::ini(), 'ini_config' => self::ini('profile default', self::getHomeDir() . '/.aws/config')];
|
76 |
+
if (!empty(getenv(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\EcsCredentialProvider::ENV_URI))) {
|
77 |
+
$defaultChain['ecs'] = self::ecsCredentials($config);
|
78 |
+
}
|
79 |
+
$defaultChain['process_credentials'] = self::process();
|
80 |
+
$defaultChain['process_config'] = self::process('profile default', self::getHomeDir() . '/.aws/config');
|
81 |
+
$defaultChain['instance'] = self::instanceProfile($config);
|
82 |
+
if (isset($config['credentials']) && $config['credentials'] instanceof CacheInterface) {
|
83 |
+
foreach ($cacheable as $provider) {
|
84 |
+
if (isset($defaultChain[$provider])) {
|
85 |
+
$defaultChain[$provider] = self::cache($defaultChain[$provider], $config['credentials'], 'aws_cached_' . $provider . '_credentials');
|
86 |
+
}
|
87 |
+
}
|
88 |
+
}
|
89 |
+
return self::memoize(call_user_func_array('self::chain', $defaultChain));
|
90 |
}
|
91 |
/**
|
92 |
* Create a credential provider function from a set of static credentials.
|
173 |
* instance of Aws\CacheInterface. Forwards calls when no credentials found
|
174 |
* in cache and updates cache with the results.
|
175 |
*
|
|
|
|
|
176 |
* @param callable $provider Credentials provider function to wrap
|
177 |
* @param CacheInterface $cache Cache to store credentials
|
178 |
* @param string|null $cacheKey (optional) Cache key to use
|
249 |
{
|
250 |
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\AssumeRoleCredentialProvider($config);
|
251 |
}
|
252 |
+
/**
|
253 |
+
* Credential provider that creates credentials by assuming role from a
|
254 |
+
* Web Identity Token
|
255 |
+
*
|
256 |
+
* @param array $config Array of configuration data
|
257 |
+
* @return callable
|
258 |
+
* @see Aws\Credentials\AssumeRoleWithWebIdentityCredentialProvider for
|
259 |
+
* $config details.
|
260 |
+
*/
|
261 |
+
public static function assumeRoleWithWebIdentityCredentialProvider(array $config = [])
|
262 |
+
{
|
263 |
+
return function () use($config) {
|
264 |
+
$arnFromEnv = getenv(self::ENV_ARN);
|
265 |
+
$tokenFromEnv = getenv(self::ENV_TOKEN_FILE);
|
266 |
+
$stsClient = isset($config['stsClient']) ? $config['stsClient'] : null;
|
267 |
+
$region = isset($config['region']) ? $config['region'] : null;
|
268 |
+
if ($tokenFromEnv && $arnFromEnv) {
|
269 |
+
$sessionName = getenv(self::ENV_ROLE_SESSION_NAME) ? getenv(self::ENV_ROLE_SESSION_NAME) : null;
|
270 |
+
$provider = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\AssumeRoleWithWebIdentityCredentialProvider(['RoleArn' => $arnFromEnv, 'WebIdentityTokenFile' => $tokenFromEnv, 'SessionName' => $sessionName, 'client' => $stsClient, 'region' => $region]);
|
271 |
+
return $provider();
|
272 |
+
}
|
273 |
+
$profileName = getenv(self::ENV_PROFILE) ?: 'default';
|
274 |
+
if (isset($config['filename'])) {
|
275 |
+
$profiles = self::loadProfiles($config['filename']);
|
276 |
+
} else {
|
277 |
+
$profiles = self::loadDefaultProfiles();
|
278 |
+
}
|
279 |
+
if (isset($profiles[$profileName])) {
|
280 |
+
$profile = $profiles[$profileName];
|
281 |
+
if (isset($profile['region'])) {
|
282 |
+
$region = $profile['region'];
|
283 |
+
}
|
284 |
+
if (isset($profile['web_identity_token_file']) && isset($profile['role_arn'])) {
|
285 |
+
$sessionName = isset($profile['role_session_name']) ? $profile['role_session_name'] : null;
|
286 |
+
$provider = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\AssumeRoleWithWebIdentityCredentialProvider(['RoleArn' => $profile['role_arn'], 'WebIdentityTokenFile' => $profile['web_identity_token_file'], 'SessionName' => $sessionName, 'client' => $stsClient, 'region' => $region]);
|
287 |
+
return $provider();
|
288 |
+
}
|
289 |
+
} else {
|
290 |
+
return self::reject("Unknown profile: {$profileName}");
|
291 |
+
}
|
292 |
+
return self::reject("No RoleArn or WebIdentityTokenFile specified");
|
293 |
+
};
|
294 |
+
}
|
295 |
/**
|
296 |
* Credentials provider that creates credentials using an ini file stored
|
297 |
* in the current user's home directory.
|
300 |
* the "default" profile in "~/.aws/credentials".
|
301 |
* @param string|null $filename If provided, uses a custom filename rather
|
302 |
* than looking in the home directory.
|
303 |
+
* @param array|null $config If provided, may contain the following:
|
304 |
+
* preferStaticCredentials: If true, prefer static
|
305 |
+
* credentials to role_arn if both are present
|
306 |
+
* disableAssumeRole: If true, disable support for
|
307 |
+
* roles that assume an IAM role. If true and role profile
|
308 |
+
* is selected, an error is raised.
|
309 |
+
* stsClient: StsClient used to assume role specified in profile
|
310 |
*
|
311 |
* @return callable
|
312 |
*/
|
313 |
+
public static function ini($profile = null, $filename = null, array $config = [])
|
314 |
{
|
315 |
$filename = $filename ?: self::getHomeDir() . '/.aws/credentials';
|
316 |
$profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
|
317 |
+
return function () use($profile, $filename, $config) {
|
318 |
+
$preferStaticCredentials = isset($config['preferStaticCredentials']) ? $config['preferStaticCredentials'] : false;
|
319 |
+
$disableAssumeRole = isset($config['disableAssumeRole']) ? $config['disableAssumeRole'] : false;
|
320 |
+
$stsClient = isset($config['stsClient']) ? $config['stsClient'] : null;
|
321 |
if (!is_readable($filename)) {
|
322 |
return self::reject("Cannot read credentials from {$filename}");
|
323 |
}
|
324 |
+
$data = self::loadProfiles($filename);
|
325 |
if ($data === false) {
|
326 |
return self::reject("Invalid credentials file: {$filename}");
|
327 |
}
|
328 |
if (!isset($data[$profile])) {
|
329 |
return self::reject("'{$profile}' not found in credentials file");
|
330 |
}
|
331 |
+
/*
|
332 |
+
In the CLI, the presence of both a role_arn and static credentials have
|
333 |
+
different meanings depending on how many profiles have been visited. For
|
334 |
+
the first profile processed, role_arn takes precedence over any static
|
335 |
+
credentials, but for all subsequent profiles, static credentials are
|
336 |
+
used if present, and only in their absence will the profile's
|
337 |
+
source_profile and role_arn keys be used to load another set of
|
338 |
+
credentials. This bool is intended to yield compatible behaviour in this
|
339 |
+
sdk.
|
340 |
+
*/
|
341 |
+
$preferStaticCredentialsToRoleArn = $preferStaticCredentials && isset($data[$profile]['aws_access_key_id']) && isset($data[$profile]['aws_secret_access_key']);
|
342 |
+
if (isset($data[$profile]['role_arn']) && !$preferStaticCredentialsToRoleArn) {
|
343 |
+
if ($disableAssumeRole) {
|
344 |
+
return self::reject("Role assumption profiles are disabled. " . "Failed to load profile " . $profile);
|
345 |
+
}
|
346 |
+
return self::loadRoleProfile($data, $profile, $filename, $stsClient);
|
347 |
+
}
|
348 |
if (!isset($data[$profile]['aws_access_key_id']) || !isset($data[$profile]['aws_secret_access_key'])) {
|
349 |
return self::reject("No credentials present in INI profile " . "'{$profile}' ({$filename})");
|
350 |
}
|
355 |
};
|
356 |
}
|
357 |
/**
|
358 |
+
* Credentials provider that creates credentials using a process configured in
|
359 |
+
* ini file stored in the current user's home directory.
|
|
|
|
|
|
|
360 |
*
|
361 |
+
* @param string|null $profile Profile to use. If not specified will use
|
362 |
+
* the "default" profile in "~/.aws/credentials".
|
363 |
+
* @param string|null $filename If provided, uses a custom filename rather
|
364 |
+
* than looking in the home directory.
|
365 |
+
*
|
366 |
+
* @return callable
|
367 |
*/
|
368 |
+
public static function process($profile = null, $filename = null)
|
369 |
{
|
370 |
+
$filename = $filename ?: self::getHomeDir() . '/.aws/credentials';
|
371 |
+
$profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
|
372 |
+
return function () use($profile, $filename) {
|
373 |
+
if (!is_readable($filename)) {
|
374 |
+
return self::reject("Cannot read process credentials from {$filename}");
|
375 |
+
}
|
376 |
+
$data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($filename, true, INI_SCANNER_RAW);
|
377 |
+
if ($data === false) {
|
378 |
+
return self::reject("Invalid credentials file: {$filename}");
|
379 |
+
}
|
380 |
+
if (!isset($data[$profile])) {
|
381 |
+
return self::reject("'{$profile}' not found in credentials file");
|
382 |
+
}
|
383 |
+
if (!isset($data[$profile]['credential_process'])) {
|
384 |
+
return self::reject("No credential_process present in INI profile " . "'{$profile}' ({$filename})");
|
385 |
+
}
|
386 |
+
$credentialProcess = $data[$profile]['credential_process'];
|
387 |
+
$json = shell_exec($credentialProcess);
|
388 |
+
$processData = json_decode($json, true);
|
389 |
+
// Only support version 1
|
390 |
+
if (isset($processData['Version'])) {
|
391 |
+
if ($processData['Version'] !== 1) {
|
392 |
+
return self::reject("credential_process does not return Version == 1");
|
393 |
+
}
|
394 |
+
}
|
395 |
+
if (!isset($processData['AccessKeyId']) || !isset($processData['SecretAccessKey'])) {
|
396 |
+
return self::reject("credential_process does not return valid credentials");
|
397 |
+
}
|
398 |
+
if (isset($processData['Expiration'])) {
|
399 |
+
try {
|
400 |
+
$expiration = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult($processData['Expiration']);
|
401 |
+
} catch (\Exception $e) {
|
402 |
+
return self::reject("credential_process returned invalid expiration");
|
403 |
+
}
|
404 |
+
$now = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult();
|
405 |
+
if ($expiration < $now) {
|
406 |
+
return self::reject("credential_process returned expired credentials");
|
407 |
+
}
|
408 |
+
$expires = $expiration->getTimestamp();
|
409 |
+
} else {
|
410 |
+
$expires = null;
|
411 |
+
}
|
412 |
+
if (empty($processData['SessionToken'])) {
|
413 |
+
$processData['SessionToken'] = null;
|
414 |
+
}
|
415 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\Credentials($processData['AccessKeyId'], $processData['SecretAccessKey'], $processData['SessionToken'], $expires));
|
416 |
+
};
|
417 |
}
|
418 |
/**
|
419 |
+
* Assumes role for profile that includes role_arn
|
|
|
|
|
|
|
420 |
*
|
421 |
+
* @return callable
|
|
|
|
|
422 |
*/
|
423 |
+
private static function loadRoleProfile($profiles, $profileName, $filename, $stsClient)
|
424 |
{
|
425 |
+
$roleProfile = $profiles[$profileName];
|
426 |
+
$roleArn = isset($roleProfile['role_arn']) ? $roleProfile['role_arn'] : '';
|
427 |
+
$roleSessionName = isset($roleProfile['role_session_name']) ? $roleProfile['role_session_name'] : 'aws-sdk-php-' . round(microtime(true) * 1000);
|
428 |
+
if (empty($profiles[$profileName]['source_profile'])) {
|
429 |
+
return self::reject("source_profile is not set using profile " . $profileName);
|
430 |
}
|
431 |
+
$sourceProfileName = $roleProfile['source_profile'];
|
432 |
+
if (!isset($profiles[$sourceProfileName])) {
|
433 |
+
return self::reject("source_profile " . $sourceProfileName . " using profile " . $profileName . " does not exist");
|
434 |
+
}
|
435 |
+
$sourceRegion = isset($profiles[$sourceProfileName]['region']) ? $profiles[$sourceProfileName]['region'] : 'us-east-1';
|
436 |
+
if (empty($stsClient)) {
|
437 |
+
$config = ['preferStaticCredentials' => true];
|
438 |
+
$sourceCredentials = call_user_func(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialProvider::ini($sourceProfileName, $filename, $config))->wait();
|
439 |
+
$stsClient = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sts\StsClient(['credentials' => $sourceCredentials, 'region' => $sourceRegion, 'version' => '2011-06-15']);
|
440 |
}
|
441 |
+
$result = $stsClient->assumeRole(['RoleArn' => $roleArn, 'RoleSessionName' => $roleSessionName]);
|
442 |
+
$creds = $stsClient->createCredentials($result);
|
443 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for($creds);
|
444 |
}
|
445 |
/**
|
446 |
* Gets the environment's HOME directory if available.
|
458 |
$homePath = getenv('HOMEPATH');
|
459 |
return $homeDrive && $homePath ? $homeDrive . $homePath : null;
|
460 |
}
|
461 |
+
/**
|
462 |
+
* Gets profiles from specified $filename, or default ini files.
|
463 |
+
*/
|
464 |
+
private static function loadProfiles($filename)
|
465 |
+
{
|
466 |
+
$profileData = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($filename, true, INI_SCANNER_RAW);
|
467 |
+
// If loading .aws/credentials, also load .aws/config when AWS_SDK_LOAD_NONDEFAULT_CONFIG is set
|
468 |
+
if ($filename === self::getHomeDir() . '/.aws/credentials' && getenv('AWS_SDK_LOAD_NONDEFAULT_CONFIG')) {
|
469 |
+
$configFilename = self::getHomeDir() . '/.aws/config';
|
470 |
+
$configProfileData = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($configFilename, true, INI_SCANNER_RAW);
|
471 |
+
foreach ($configProfileData as $name => $profile) {
|
472 |
+
// standardize config profile names
|
473 |
+
$name = str_replace('profile ', '', $name);
|
474 |
+
if (!isset($profileData[$name])) {
|
475 |
+
$profileData[$name] = $profile;
|
476 |
+
}
|
477 |
+
}
|
478 |
+
}
|
479 |
+
return $profileData;
|
480 |
+
}
|
481 |
+
/**
|
482 |
+
* Gets profiles from ~/.aws/credentials and ~/.aws/config ini files
|
483 |
+
*/
|
484 |
+
private static function loadDefaultProfiles()
|
485 |
+
{
|
486 |
+
$profiles = [];
|
487 |
+
$credFile = self::getHomeDir() . '/.aws/credentials';
|
488 |
+
$configFile = self::getHomeDir() . '/.aws/config';
|
489 |
+
if (file_exists($credFile)) {
|
490 |
+
$profiles = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($credFile, true, INI_SCANNER_RAW);
|
491 |
+
}
|
492 |
+
if (file_exists($configFile)) {
|
493 |
+
$configProfileData = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($configFile, true, INI_SCANNER_RAW);
|
494 |
+
foreach ($configProfileData as $name => $profile) {
|
495 |
+
// standardize config profile names
|
496 |
+
$name = str_replace('profile ', '', $name);
|
497 |
+
if (!isset($profiles[$name])) {
|
498 |
+
$profiles[$name] = $profile;
|
499 |
+
}
|
500 |
+
}
|
501 |
+
}
|
502 |
+
return $profiles;
|
503 |
+
}
|
504 |
private static function reject($msg)
|
505 |
{
|
506 |
return new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\RejectedPromise(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($msg));
|
@@ -14,8 +14,11 @@ class EcsCredentialProvider
|
|
14 |
{
|
15 |
const SERVER_URI = 'http://169.254.170.2';
|
16 |
const ENV_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
|
|
|
17 |
/** @var callable */
|
18 |
private $client;
|
|
|
|
|
19 |
/**
|
20 |
* The constructor accepts following options:
|
21 |
* - timeout: (optional) Connection timeout, in seconds, default 1.0
|
@@ -25,7 +28,7 @@ class EcsCredentialProvider
|
|
25 |
*/
|
26 |
public function __construct(array $config = [])
|
27 |
{
|
28 |
-
$this->timeout = isset($config['timeout']) ? $config['timeout'] : 1.0;
|
29 |
$this->client = isset($config['client']) ? $config['client'] : \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_http_handler();
|
30 |
}
|
31 |
/**
|
14 |
{
|
15 |
const SERVER_URI = 'http://169.254.170.2';
|
16 |
const ENV_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
|
17 |
+
const ENV_TIMEOUT = 'AWS_METADATA_SERVICE_TIMEOUT';
|
18 |
/** @var callable */
|
19 |
private $client;
|
20 |
+
/** @var float|mixed */
|
21 |
+
private $timeout;
|
22 |
/**
|
23 |
* The constructor accepts following options:
|
24 |
* - timeout: (optional) Connection timeout, in seconds, default 1.0
|
28 |
*/
|
29 |
public function __construct(array $config = [])
|
30 |
{
|
31 |
+
$this->timeout = (double) getenv(self::ENV_TIMEOUT) ?: (isset($config['timeout']) ? $config['timeout'] : 1.0);
|
32 |
$this->client = isset($config['client']) ? $config['client'] : \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_http_handler();
|
33 |
}
|
34 |
/**
|
@@ -3,34 +3,51 @@
|
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials;
|
4 |
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException;
|
|
|
|
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
|
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request;
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
10 |
/**
|
11 |
-
* Credential provider that provides credentials from the EC2 metadata
|
12 |
*/
|
13 |
class InstanceProfileProvider
|
14 |
{
|
15 |
const SERVER_URI = 'http://169.254.169.254/latest/';
|
16 |
const CRED_PATH = 'meta-data/iam/security-credentials/';
|
|
|
17 |
const ENV_DISABLE = 'AWS_EC2_METADATA_DISABLED';
|
|
|
|
|
18 |
/** @var string */
|
19 |
private $profile;
|
20 |
/** @var callable */
|
21 |
private $client;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
/**
|
23 |
* The constructor accepts the following options:
|
24 |
*
|
25 |
* - timeout: Connection timeout, in seconds.
|
26 |
* - profile: Optional EC2 profile name, if known.
|
|
|
27 |
*
|
28 |
* @param array $config Configuration options.
|
29 |
*/
|
30 |
public function __construct(array $config = [])
|
31 |
{
|
32 |
-
$this->timeout = isset($config['timeout']) ? $config['timeout'] : 1.0;
|
33 |
$this->profile = isset($config['profile']) ? $config['profile'] : null;
|
|
|
|
|
34 |
$this->client = isset($config['client']) ? $config['client'] : \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_http_handler();
|
35 |
}
|
36 |
/**
|
@@ -41,42 +58,124 @@ class InstanceProfileProvider
|
|
41 |
public function __invoke()
|
42 |
{
|
43 |
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\coroutine(function () {
|
44 |
-
|
45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
}
|
47 |
-
$json = (yield $this->request(self::CRED_PATH . $this->profile));
|
48 |
-
$result = $this->decodeResult($json);
|
49 |
(yield new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\Credentials($result['AccessKeyId'], $result['SecretAccessKey'], $result['Token'], strtotime($result['Expiration'])));
|
50 |
});
|
51 |
}
|
52 |
/**
|
53 |
* @param string $url
|
|
|
|
|
54 |
* @return PromiseInterface Returns a promise that is fulfilled with the
|
55 |
* body of the response as a string.
|
56 |
*/
|
57 |
-
private function request($url)
|
58 |
{
|
59 |
$disabled = getenv(self::ENV_DISABLE) ?: false;
|
60 |
if (strcasecmp($disabled, 'true') === 0) {
|
61 |
-
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($this->createErrorMessage('EC2 metadata
|
62 |
}
|
63 |
$fn = $this->client;
|
64 |
-
$request = new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
return $fn($request, ['timeout' => $this->timeout])->then(function (\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response) {
|
66 |
return (string) $response->getBody();
|
67 |
})->otherwise(function (array $reason) {
|
68 |
$reason = $reason['exception'];
|
|
|
|
|
|
|
69 |
$msg = $reason->getMessage();
|
70 |
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($this->createErrorMessage($msg));
|
71 |
});
|
72 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
private function createErrorMessage($previous)
|
74 |
{
|
75 |
-
return "Error retrieving credentials from the instance profile " . "metadata
|
76 |
}
|
77 |
private function decodeResult($response)
|
78 |
{
|
79 |
$result = json_decode($response, true);
|
|
|
|
|
|
|
80 |
if ($result['Code'] !== 'Success') {
|
81 |
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException('Unexpected instance profile ' . 'response code: ' . $result['Code']);
|
82 |
}
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials;
|
4 |
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\InvalidJsonException;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sdk;
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Exception\RequestException;
|
10 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request;
|
11 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
|
12 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
13 |
/**
|
14 |
+
* Credential provider that provides credentials from the EC2 metadata service.
|
15 |
*/
|
16 |
class InstanceProfileProvider
|
17 |
{
|
18 |
const SERVER_URI = 'http://169.254.169.254/latest/';
|
19 |
const CRED_PATH = 'meta-data/iam/security-credentials/';
|
20 |
+
const TOKEN_PATH = 'api/token';
|
21 |
const ENV_DISABLE = 'AWS_EC2_METADATA_DISABLED';
|
22 |
+
const ENV_TIMEOUT = 'AWS_METADATA_SERVICE_TIMEOUT';
|
23 |
+
const ENV_RETRIES = 'AWS_METADATA_SERVICE_NUM_ATTEMPTS';
|
24 |
/** @var string */
|
25 |
private $profile;
|
26 |
/** @var callable */
|
27 |
private $client;
|
28 |
+
/** @var int */
|
29 |
+
private $retries;
|
30 |
+
/** @var int */
|
31 |
+
private $attempts;
|
32 |
+
/** @var float|mixed */
|
33 |
+
private $timeout;
|
34 |
+
/** @var bool */
|
35 |
+
private $secureMode = true;
|
36 |
/**
|
37 |
* The constructor accepts the following options:
|
38 |
*
|
39 |
* - timeout: Connection timeout, in seconds.
|
40 |
* - profile: Optional EC2 profile name, if known.
|
41 |
+
* - retries: Optional number of retries to be attempted.
|
42 |
*
|
43 |
* @param array $config Configuration options.
|
44 |
*/
|
45 |
public function __construct(array $config = [])
|
46 |
{
|
47 |
+
$this->timeout = (double) getenv(self::ENV_TIMEOUT) ?: (isset($config['timeout']) ? $config['timeout'] : 1.0);
|
48 |
$this->profile = isset($config['profile']) ? $config['profile'] : null;
|
49 |
+
$this->retries = (int) getenv(self::ENV_RETRIES) ?: (isset($config['retries']) ? $config['retries'] : 3);
|
50 |
+
$this->attempts = 0;
|
51 |
$this->client = isset($config['client']) ? $config['client'] : \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_http_handler();
|
52 |
}
|
53 |
/**
|
58 |
public function __invoke()
|
59 |
{
|
60 |
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\coroutine(function () {
|
61 |
+
// Retrieve token or switch out of secure mode
|
62 |
+
$token = null;
|
63 |
+
while ($this->secureMode && is_null($token)) {
|
64 |
+
try {
|
65 |
+
$token = (yield $this->request(self::TOKEN_PATH, 'PUT', ['x-aws-ec2-metadata-token-ttl-seconds' => 21600]));
|
66 |
+
} catch (RequestException $e) {
|
67 |
+
if (empty($e->getResponse()) || !in_array($e->getResponse()->getStatusCode(), [400, 500, 502, 503, 504])) {
|
68 |
+
$this->secureMode = false;
|
69 |
+
} else {
|
70 |
+
$this->handleRetryableException($e, [], $this->createErrorMessage('Error retrieving metadata token'));
|
71 |
+
}
|
72 |
+
}
|
73 |
+
$this->attempts++;
|
74 |
+
}
|
75 |
+
// Set token header only for secure mode
|
76 |
+
$headers = [];
|
77 |
+
if ($this->secureMode) {
|
78 |
+
$headers = ['x-aws-ec2-metadata-token' => $token];
|
79 |
+
}
|
80 |
+
// Retrieve profile
|
81 |
+
while (!$this->profile) {
|
82 |
+
try {
|
83 |
+
$this->profile = (yield $this->request(self::CRED_PATH, 'GET', $headers));
|
84 |
+
} catch (RequestException $e) {
|
85 |
+
// 401 indicates insecure flow not supported, switch to
|
86 |
+
// attempting secure mode for subsequent calls
|
87 |
+
if (!empty($this->getExceptionStatusCode($e)) && $this->getExceptionStatusCode($e) === 401) {
|
88 |
+
$this->secureMode = true;
|
89 |
+
}
|
90 |
+
$this->handleRetryableException($e, ['blacklist' => [401, 403]], $this->createErrorMessage($e->getMessage()));
|
91 |
+
}
|
92 |
+
$this->attempts++;
|
93 |
+
}
|
94 |
+
// Retrieve credentials
|
95 |
+
$result = null;
|
96 |
+
while ($result == null) {
|
97 |
+
try {
|
98 |
+
$json = (yield $this->request(self::CRED_PATH . $this->profile, 'GET', $headers));
|
99 |
+
$result = $this->decodeResult($json);
|
100 |
+
} catch (InvalidJsonException $e) {
|
101 |
+
$this->handleRetryableException($e, ['blacklist' => [401, 403]], $this->createErrorMessage('Invalid JSON response, retries exhausted'));
|
102 |
+
} catch (RequestException $e) {
|
103 |
+
// 401 indicates insecure flow not supported, switch to
|
104 |
+
// attempting secure mode for subsequent calls
|
105 |
+
if (!empty($this->getExceptionStatusCode($e)) && $this->getExceptionStatusCode($e) === 401) {
|
106 |
+
$this->secureMode = true;
|
107 |
+
}
|
108 |
+
$this->handleRetryableException($e, ['blacklist' => [401, 403]], $this->createErrorMessage($e->getMessage()));
|
109 |
+
}
|
110 |
+
$this->attempts++;
|
111 |
}
|
|
|
|
|
112 |
(yield new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\Credentials($result['AccessKeyId'], $result['SecretAccessKey'], $result['Token'], strtotime($result['Expiration'])));
|
113 |
});
|
114 |
}
|
115 |
/**
|
116 |
* @param string $url
|
117 |
+
* @param string $method
|
118 |
+
* @param array $headers
|
119 |
* @return PromiseInterface Returns a promise that is fulfilled with the
|
120 |
* body of the response as a string.
|
121 |
*/
|
122 |
+
private function request($url, $method = 'GET', $headers = [])
|
123 |
{
|
124 |
$disabled = getenv(self::ENV_DISABLE) ?: false;
|
125 |
if (strcasecmp($disabled, 'true') === 0) {
|
126 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($this->createErrorMessage('EC2 metadata service access disabled'));
|
127 |
}
|
128 |
$fn = $this->client;
|
129 |
+
$request = new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request($method, self::SERVER_URI . $url);
|
130 |
+
$userAgent = 'aws-sdk-php/' . \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sdk::VERSION;
|
131 |
+
if (defined('HHVM_VERSION')) {
|
132 |
+
$userAgent .= ' HHVM/' . HHVM_VERSION;
|
133 |
+
}
|
134 |
+
$userAgent .= ' ' . \DeliciousBrains\WP_Offload_Media\Aws3\Aws\default_user_agent();
|
135 |
+
$request = $request->withHeader('User-Agent', $userAgent);
|
136 |
+
foreach ($headers as $key => $value) {
|
137 |
+
$request = $request->withHeader($key, $value);
|
138 |
+
}
|
139 |
return $fn($request, ['timeout' => $this->timeout])->then(function (\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response) {
|
140 |
return (string) $response->getBody();
|
141 |
})->otherwise(function (array $reason) {
|
142 |
$reason = $reason['exception'];
|
143 |
+
if ($reason instanceof \GuzzleHttp\Exception\RequestException) {
|
144 |
+
throw $reason;
|
145 |
+
}
|
146 |
$msg = $reason->getMessage();
|
147 |
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($this->createErrorMessage($msg));
|
148 |
});
|
149 |
}
|
150 |
+
private function handleRetryableException(\Exception $e, $retryOptions, $message)
|
151 |
+
{
|
152 |
+
$isRetryable = true;
|
153 |
+
if (!empty($status = $this->getExceptionStatusCode($e)) && isset($retryOptions['blacklist']) && in_array($status, $retryOptions['blacklist'])) {
|
154 |
+
$isRetryable = false;
|
155 |
+
}
|
156 |
+
if ($isRetryable && $this->attempts < $this->retries) {
|
157 |
+
sleep(pow(1.2, $this->attempts));
|
158 |
+
} else {
|
159 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException($message);
|
160 |
+
}
|
161 |
+
}
|
162 |
+
private function getExceptionStatusCode(\Exception $e)
|
163 |
+
{
|
164 |
+
if (method_exists($e, 'getResponse') && !empty($e->getResponse())) {
|
165 |
+
return $e->getResponse()->getStatusCode();
|
166 |
+
}
|
167 |
+
return null;
|
168 |
+
}
|
169 |
private function createErrorMessage($previous)
|
170 |
{
|
171 |
+
return "Error retrieving credentials from the instance profile " . "metadata service. ({$previous})";
|
172 |
}
|
173 |
private function decodeResult($response)
|
174 |
{
|
175 |
$result = json_decode($response, true);
|
176 |
+
if (json_last_error() > 0) {
|
177 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\InvalidJsonException();
|
178 |
+
}
|
179 |
if ($result['Code'] !== 'Success') {
|
180 |
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\CredentialsException('Unexpected instance profile ' . 'response code: ' . $result['Code']);
|
181 |
}
|
@@ -4,6 +4,7 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto;
|
|
4 |
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\LimitStream;
|
|
|
7 |
trait DecryptionTrait
|
8 |
{
|
9 |
/**
|
@@ -50,7 +51,7 @@ trait DecryptionTrait
|
|
50 |
*
|
51 |
* @internal
|
52 |
*/
|
53 |
-
|
54 |
{
|
55 |
$cipherOptions['Iv'] = base64_decode($envelope[\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope::IV_HEADER]);
|
56 |
$cipherOptions['TagLength'] = $envelope[\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] / 8;
|
@@ -61,7 +62,7 @@ trait DecryptionTrait
|
|
61 |
unset($cek);
|
62 |
return $decryptionSteam;
|
63 |
}
|
64 |
-
private function getTagFromCiphertextStream(\DeliciousBrains\WP_Offload_Media\Aws3\
|
65 |
{
|
66 |
$cipherTextSize = $cipherText->getSize();
|
67 |
if ($cipherTextSize == null || $cipherTextSize <= 0) {
|
@@ -69,7 +70,7 @@ trait DecryptionTrait
|
|
69 |
}
|
70 |
return (string) new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\LimitStream($cipherText, $tagLength, $cipherTextSize - $tagLength);
|
71 |
}
|
72 |
-
private function getStrippedCiphertextStream(\DeliciousBrains\WP_Offload_Media\Aws3\
|
73 |
{
|
74 |
$cipherTextSize = $cipherText->getSize();
|
75 |
if ($cipherTextSize == null || $cipherTextSize <= 0) {
|
4 |
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\LimitStream;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\StreamInterface;
|
8 |
trait DecryptionTrait
|
9 |
{
|
10 |
/**
|
51 |
*
|
52 |
* @internal
|
53 |
*/
|
54 |
+
public function decrypt($cipherText, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MaterialsProvider $provider, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope $envelope, array $cipherOptions = [])
|
55 |
{
|
56 |
$cipherOptions['Iv'] = base64_decode($envelope[\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope::IV_HEADER]);
|
57 |
$cipherOptions['TagLength'] = $envelope[\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] / 8;
|
62 |
unset($cek);
|
63 |
return $decryptionSteam;
|
64 |
}
|
65 |
+
private function getTagFromCiphertextStream(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\StreamInterface $cipherText, $tagLength)
|
66 |
{
|
67 |
$cipherTextSize = $cipherText->getSize();
|
68 |
if ($cipherTextSize == null || $cipherTextSize <= 0) {
|
70 |
}
|
71 |
return (string) new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\LimitStream($cipherText, $tagLength, $cipherTextSize - $tagLength);
|
72 |
}
|
73 |
+
private function getStrippedCiphertextStream(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\StreamInterface $cipherText, $tagLength)
|
74 |
{
|
75 |
$cipherTextSize = $cipherText->getSize();
|
76 |
if ($cipherTextSize == null || $cipherTextSize <= 0) {
|
@@ -42,7 +42,7 @@ trait EncryptionTrait
|
|
42 |
*
|
43 |
* @internal
|
44 |
*/
|
45 |
-
|
46 |
{
|
47 |
$materialsDescription = $provider->getMaterialsDescription();
|
48 |
$cipherOptions = array_intersect_key($cipherOptions, self::$allowedOptions);
|
42 |
*
|
43 |
* @internal
|
44 |
*/
|
45 |
+
public function encrypt(\DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Stream $plaintext, array $cipherOptions, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MaterialsProvider $provider, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Crypto\MetadataEnvelope $envelope)
|
46 |
{
|
47 |
$materialsDescription = $provider->getMaterialsDescription();
|
48 |
$cipherOptions = array_intersect_key($cipherOptions, self::$allowedOptions);
|
@@ -4,6 +4,8 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint;
|
|
4 |
|
5 |
use ArrayAccess;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasDataTrait;
|
|
|
|
|
7 |
use InvalidArgumentException as Iae;
|
8 |
/**
|
9 |
* Default implementation of an AWS partition.
|
@@ -11,6 +13,7 @@ use InvalidArgumentException as Iae;
|
|
11 |
final class Partition implements \ArrayAccess, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionInterface
|
12 |
{
|
13 |
use HasDataTrait;
|
|
|
14 |
/**
|
15 |
* The partition constructor accepts the following options:
|
16 |
*
|
@@ -48,6 +51,14 @@ final class Partition implements \ArrayAccess, \DeliciousBrains\WP_Offload_Media
|
|
48 |
{
|
49 |
return $this->data['partition'];
|
50 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
public function isRegionMatch($region, $service)
|
52 |
{
|
53 |
if (isset($this->data['regions'][$region]) || isset($this->data['services'][$service]['endpoints'][$region])) {
|
@@ -74,12 +85,13 @@ final class Partition implements \ArrayAccess, \DeliciousBrains\WP_Offload_Media
|
|
74 |
$service = isset($args['service']) ? $args['service'] : '';
|
75 |
$region = isset($args['region']) ? $args['region'] : '';
|
76 |
$scheme = isset($args['scheme']) ? $args['scheme'] : 'https';
|
77 |
-
$
|
|
|
78 |
return ['endpoint' => "{$scheme}://" . $this->formatEndpoint(isset($data['hostname']) ? $data['hostname'] : '', $service, $region), 'signatureVersion' => $this->getSignatureVersion($data), 'signingRegion' => isset($data['credentialScope']['region']) ? $data['credentialScope']['region'] : $region, 'signingName' => isset($data['credentialScope']['service']) ? $data['credentialScope']['service'] : $service];
|
79 |
}
|
80 |
-
private function getEndpointData($service, $region)
|
81 |
{
|
82 |
-
$resolved = $this->resolveRegion($service, $region);
|
83 |
$data = isset($this->data['services'][$service]['endpoints'][$resolved]) ? $this->data['services'][$service]['endpoints'][$resolved] : [];
|
84 |
$data += isset($this->data['services'][$service]['defaults']) ? $this->data['services'][$service]['defaults'] : [];
|
85 |
$data += isset($this->data['defaults']) ? $this->data['defaults'] : [];
|
@@ -91,9 +103,9 @@ final class Partition implements \ArrayAccess, \DeliciousBrains\WP_Offload_Media
|
|
91 |
$possibilities = array_intersect($supportedBySdk, isset($data['signatureVersions']) ? $data['signatureVersions'] : ['v4']);
|
92 |
return array_shift($possibilities);
|
93 |
}
|
94 |
-
private function resolveRegion($service, $region)
|
95 |
{
|
96 |
-
if ($this->isServicePartitionGlobal($service)) {
|
97 |
return $this->getPartitionEndpoint($service);
|
98 |
}
|
99 |
return $region;
|
@@ -102,6 +114,32 @@ final class Partition implements \ArrayAccess, \DeliciousBrains\WP_Offload_Media
|
|
102 |
{
|
103 |
return isset($this->data['services'][$service]['isRegionalized']) && false === $this->data['services'][$service]['isRegionalized'] && isset($this->data['services'][$service]['partitionEndpoint']);
|
104 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
private function getPartitionEndpoint($service)
|
106 |
{
|
107 |
return $this->data['services'][$service]['partitionEndpoint'];
|
4 |
|
5 |
use ArrayAccess;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasDataTrait;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sts\RegionalEndpoints\ConfigurationProvider;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationProvider as S3ConfigurationProvider;
|
9 |
use InvalidArgumentException as Iae;
|
10 |
/**
|
11 |
* Default implementation of an AWS partition.
|
13 |
final class Partition implements \ArrayAccess, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionInterface
|
14 |
{
|
15 |
use HasDataTrait;
|
16 |
+
private $stsLegacyGlobalRegions = ['ap-northeast-1', 'ap-south-1', 'ap-southeast-1', 'ap-southeast-2', 'aws-global', 'ca-central-1', 'eu-central-1', 'eu-north-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'sa-east-1', 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2'];
|
17 |
/**
|
18 |
* The partition constructor accepts the following options:
|
19 |
*
|
51 |
{
|
52 |
return $this->data['partition'];
|
53 |
}
|
54 |
+
/**
|
55 |
+
* @internal
|
56 |
+
* @return mixed
|
57 |
+
*/
|
58 |
+
public function getDnsSuffix()
|
59 |
+
{
|
60 |
+
return $this->data['dnsSuffix'];
|
61 |
+
}
|
62 |
public function isRegionMatch($region, $service)
|
63 |
{
|
64 |
if (isset($this->data['regions'][$region]) || isset($this->data['services'][$service]['endpoints'][$region])) {
|
85 |
$service = isset($args['service']) ? $args['service'] : '';
|
86 |
$region = isset($args['region']) ? $args['region'] : '';
|
87 |
$scheme = isset($args['scheme']) ? $args['scheme'] : 'https';
|
88 |
+
$options = isset($args['options']) ? $args['options'] : [];
|
89 |
+
$data = $this->getEndpointData($service, $region, $options);
|
90 |
return ['endpoint' => "{$scheme}://" . $this->formatEndpoint(isset($data['hostname']) ? $data['hostname'] : '', $service, $region), 'signatureVersion' => $this->getSignatureVersion($data), 'signingRegion' => isset($data['credentialScope']['region']) ? $data['credentialScope']['region'] : $region, 'signingName' => isset($data['credentialScope']['service']) ? $data['credentialScope']['service'] : $service];
|
91 |
}
|
92 |
+
private function getEndpointData($service, $region, $options)
|
93 |
{
|
94 |
+
$resolved = $this->resolveRegion($service, $region, $options);
|
95 |
$data = isset($this->data['services'][$service]['endpoints'][$resolved]) ? $this->data['services'][$service]['endpoints'][$resolved] : [];
|
96 |
$data += isset($this->data['services'][$service]['defaults']) ? $this->data['services'][$service]['defaults'] : [];
|
97 |
$data += isset($this->data['defaults']) ? $this->data['defaults'] : [];
|
103 |
$possibilities = array_intersect($supportedBySdk, isset($data['signatureVersions']) ? $data['signatureVersions'] : ['v4']);
|
104 |
return array_shift($possibilities);
|
105 |
}
|
106 |
+
private function resolveRegion($service, $region, $options)
|
107 |
{
|
108 |
+
if ($this->isServicePartitionGlobal($service) || $this->isStsLegacyEndpointUsed($service, $region, $options) || $this->isS3LegacyEndpointUsed($service, $region, $options)) {
|
109 |
return $this->getPartitionEndpoint($service);
|
110 |
}
|
111 |
return $region;
|
114 |
{
|
115 |
return isset($this->data['services'][$service]['isRegionalized']) && false === $this->data['services'][$service]['isRegionalized'] && isset($this->data['services'][$service]['partitionEndpoint']);
|
116 |
}
|
117 |
+
/**
|
118 |
+
* STS legacy endpoints used for valid regions unless option is explicitly
|
119 |
+
* set to 'regional'
|
120 |
+
*
|
121 |
+
* @param string $service
|
122 |
+
* @param string $region
|
123 |
+
* @param array $options
|
124 |
+
* @return bool
|
125 |
+
*/
|
126 |
+
private function isStsLegacyEndpointUsed($service, $region, $options)
|
127 |
+
{
|
128 |
+
return $service === 'sts' && in_array($region, $this->stsLegacyGlobalRegions) && (empty($options['sts_regional_endpoints']) || \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Sts\RegionalEndpoints\ConfigurationProvider::unwrap($options['sts_regional_endpoints'])->getEndpointsType() !== 'regional');
|
129 |
+
}
|
130 |
+
/**
|
131 |
+
* S3 legacy us-east-1 endpoint used for valid regions unless option is explicitly
|
132 |
+
* set to 'regional'
|
133 |
+
*
|
134 |
+
* @param string $service
|
135 |
+
* @param string $region
|
136 |
+
* @param array $options
|
137 |
+
* @return bool
|
138 |
+
*/
|
139 |
+
private function isS3LegacyEndpointUsed($service, $region, $options)
|
140 |
+
{
|
141 |
+
return $service === 's3' && $region === 'us-east-1' && (empty($options['s3_us_east_1_regional_endpoint']) || \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationProvider::unwrap($options['s3_us_east_1_regional_endpoint'])->getEndpointsType() !== 'regional');
|
142 |
+
}
|
143 |
private function getPartitionEndpoint($service)
|
144 |
{
|
145 |
return $this->data['services'][$service]['partitionEndpoint'];
|
@@ -9,16 +9,34 @@ class PartitionEndpointProvider
|
|
9 |
private $partitions;
|
10 |
/** @var string */
|
11 |
private $defaultPartition;
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
{
|
14 |
$this->partitions = array_map(function (array $definition) {
|
15 |
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\Partition($definition);
|
16 |
}, array_values($partitions));
|
17 |
$this->defaultPartition = $defaultPartition;
|
|
|
18 |
}
|
19 |
public function __invoke(array $args = [])
|
20 |
{
|
21 |
$partition = $this->getPartition(isset($args['region']) ? $args['region'] : '', isset($args['service']) ? $args['service'] : '');
|
|
|
22 |
return $partition($args);
|
23 |
}
|
24 |
/**
|
@@ -58,14 +76,15 @@ class PartitionEndpointProvider
|
|
58 |
/**
|
59 |
* Creates and returns the default SDK partition provider.
|
60 |
*
|
|
|
61 |
* @return PartitionEndpointProvider
|
62 |
*/
|
63 |
-
public static function defaultProvider()
|
64 |
{
|
65 |
$data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json(__DIR__ . '/../data/endpoints.json');
|
66 |
$prefixData = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json(__DIR__ . '/../data/endpoints_prefix_history.json');
|
67 |
$mergedData = self::mergePrefixData($data, $prefixData);
|
68 |
-
return new self($mergedData['partitions']);
|
69 |
}
|
70 |
/**
|
71 |
* Copy endpoint data for other prefixes used by a given service
|
9 |
private $partitions;
|
10 |
/** @var string */
|
11 |
private $defaultPartition;
|
12 |
+
/** @var array */
|
13 |
+
private $options;
|
14 |
+
/**
|
15 |
+
* The 'options' parameter accepts the following arguments:
|
16 |
+
*
|
17 |
+
* - sts_regional_endpoints: For STS legacy regions, set to 'regional' to
|
18 |
+
* use regional endpoints, 'legacy' to use the legacy global endpoint.
|
19 |
+
* Defaults to 'legacy'.
|
20 |
+
* - s3_us_east_1_regional_endpoint: For S3 us-east-1 region, set to 'regional'
|
21 |
+
* to use the regional endpoint, 'legacy' to use the legacy global endpoint.
|
22 |
+
* Defaults to 'legacy'.
|
23 |
+
*
|
24 |
+
* @param array $partitions
|
25 |
+
* @param string $defaultPartition
|
26 |
+
* @param array $options
|
27 |
+
*/
|
28 |
+
public function __construct(array $partitions, $defaultPartition = 'aws', $options = [])
|
29 |
{
|
30 |
$this->partitions = array_map(function (array $definition) {
|
31 |
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\Partition($definition);
|
32 |
}, array_values($partitions));
|
33 |
$this->defaultPartition = $defaultPartition;
|
34 |
+
$this->options = $options;
|
35 |
}
|
36 |
public function __invoke(array $args = [])
|
37 |
{
|
38 |
$partition = $this->getPartition(isset($args['region']) ? $args['region'] : '', isset($args['service']) ? $args['service'] : '');
|
39 |
+
$args['options'] = $this->options;
|
40 |
return $partition($args);
|
41 |
}
|
42 |
/**
|
76 |
/**
|
77 |
* Creates and returns the default SDK partition provider.
|
78 |
*
|
79 |
+
* @param array $options
|
80 |
* @return PartitionEndpointProvider
|
81 |
*/
|
82 |
+
public static function defaultProvider($options = [])
|
83 |
{
|
84 |
$data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json(__DIR__ . '/../data/endpoints.json');
|
85 |
$prefixData = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json(__DIR__ . '/../data/endpoints_prefix_history.json');
|
86 |
$mergedData = self::mergePrefixData($data, $prefixData);
|
87 |
+
return new self($mergedData['partitions'], 'aws', $options);
|
88 |
}
|
89 |
/**
|
90 |
* Copy endpoint data for other prefixes used by a given service
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery;
|
4 |
+
|
5 |
+
class Configuration implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationInterface
|
6 |
+
{
|
7 |
+
private $cacheLimit;
|
8 |
+
private $enabled;
|
9 |
+
public function __construct($enabled, $cacheLimit = 1000)
|
10 |
+
{
|
11 |
+
$this->cacheLimit = filter_var($cacheLimit, FILTER_VALIDATE_INT);
|
12 |
+
if ($this->cacheLimit == false || $this->cacheLimit < 1) {
|
13 |
+
throw new \InvalidArgumentException("'cache_limit' value must be a positive integer.");
|
14 |
+
}
|
15 |
+
// Unparsable $enabled flag errs on the side of disabling endpoint discovery
|
16 |
+
$this->enabled = filter_var($enabled, FILTER_VALIDATE_BOOLEAN);
|
17 |
+
}
|
18 |
+
/**
|
19 |
+
* {@inheritdoc}
|
20 |
+
*/
|
21 |
+
public function isEnabled()
|
22 |
+
{
|
23 |
+
return $this->enabled;
|
24 |
+
}
|
25 |
+
/**
|
26 |
+
* {@inheritdoc}
|
27 |
+
*/
|
28 |
+
public function getCacheLimit()
|
29 |
+
{
|
30 |
+
return $this->cacheLimit;
|
31 |
+
}
|
32 |
+
/**
|
33 |
+
* {@inheritdoc}
|
34 |
+
*/
|
35 |
+
public function toArray()
|
36 |
+
{
|
37 |
+
return ['enabled' => $this->isEnabled(), 'cache_limit' => $this->getCacheLimit()];
|
38 |
+
}
|
39 |
+
}
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Provides access to endpoint discovery configuration options:
|
7 |
+
* 'enabled', 'cache_limit'
|
8 |
+
*/
|
9 |
+
interface ConfigurationInterface
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
* Checks whether or not endpoint discovery is enabled.
|
13 |
+
*
|
14 |
+
* @return bool
|
15 |
+
*/
|
16 |
+
public function isEnabled();
|
17 |
+
/**
|
18 |
+
* Returns the cache limit, if available.
|
19 |
+
*
|
20 |
+
* @return string|null
|
21 |
+
*/
|
22 |
+
public function getCacheLimit();
|
23 |
+
/**
|
24 |
+
* Returns the configuration as an associative array
|
25 |
+
*
|
26 |
+
* @return array
|
27 |
+
*/
|
28 |
+
public function toArray();
|
29 |
+
}
|
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Exception\ConfigurationException;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
10 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
|
11 |
+
/**
|
12 |
+
* A configuration provider is a function that returns a promise that is
|
13 |
+
* fulfilled with a {@see \Aws\EndpointDiscovery\ConfigurationInterface}
|
14 |
+
* or rejected with an {@see \Aws\EndpointDiscovery\Exception\ConfigurationException}.
|
15 |
+
*
|
16 |
+
* <code>
|
17 |
+
* use Aws\EndpointDiscovery\ConfigurationProvider;
|
18 |
+
* $provider = ConfigurationProvider::defaultProvider();
|
19 |
+
* // Returns a ConfigurationInterface or throws.
|
20 |
+
* $config = $provider()->wait();
|
21 |
+
* </code>
|
22 |
+
*
|
23 |
+
* Configuration providers can be composed to create configuration using
|
24 |
+
* conditional logic that can create different configurations in different
|
25 |
+
* environments. You can compose multiple providers into a single provider using
|
26 |
+
* {@see Aws\EndpointDiscovery\ConfigurationProvider::chain}. This function
|
27 |
+
* accepts providers as variadic arguments and returns a new function that will
|
28 |
+
* invoke each provider until a successful configuration is returned.
|
29 |
+
*
|
30 |
+
* <code>
|
31 |
+
* // First try an INI file at this location.
|
32 |
+
* $a = ConfigurationProvider::ini(null, '/path/to/file.ini');
|
33 |
+
* // Then try an INI file at this location.
|
34 |
+
* $b = ConfigurationProvider::ini(null, '/path/to/other-file.ini');
|
35 |
+
* // Then try loading from environment variables.
|
36 |
+
* $c = ConfigurationProvider::env();
|
37 |
+
* // Combine the three providers together.
|
38 |
+
* $composed = ConfigurationProvider::chain($a, $b, $c);
|
39 |
+
* // Returns a promise that is fulfilled with a configuration or throws.
|
40 |
+
* $promise = $composed();
|
41 |
+
* // Wait on the configuration to resolve.
|
42 |
+
* $config = $promise->wait();
|
43 |
+
* </code>
|
44 |
+
*/
|
45 |
+
class ConfigurationProvider extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface
|
46 |
+
{
|
47 |
+
const DEFAULT_ENABLED = false;
|
48 |
+
const DEFAULT_CACHE_LIMIT = 1000;
|
49 |
+
const ENV_ENABLED = 'AWS_ENDPOINT_DISCOVERY_ENABLED';
|
50 |
+
const ENV_ENABLED_ALT = 'AWS_ENABLE_ENDPOINT_DISCOVERY';
|
51 |
+
const ENV_PROFILE = 'AWS_PROFILE';
|
52 |
+
public static $cacheKey = 'aws_cached_endpoint_discovery_config';
|
53 |
+
protected static $interfaceClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationInterface::class;
|
54 |
+
protected static $exceptionClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Exception\ConfigurationException::class;
|
55 |
+
/**
|
56 |
+
* Create a default config provider that first checks for environment
|
57 |
+
* variables, then checks for a specified profile in the environment-defined
|
58 |
+
* config file location (env variable is 'AWS_CONFIG_FILE', file location
|
59 |
+
* defaults to ~/.aws/config), then checks for the "default" profile in the
|
60 |
+
* environment-defined config file location, and failing those uses a default
|
61 |
+
* fallback set of configuration options.
|
62 |
+
*
|
63 |
+
* This provider is automatically wrapped in a memoize function that caches
|
64 |
+
* previously provided config options.
|
65 |
+
*
|
66 |
+
* @param array $config
|
67 |
+
*
|
68 |
+
* @return callable
|
69 |
+
*/
|
70 |
+
public static function defaultProvider(array $config = [])
|
71 |
+
{
|
72 |
+
$configProviders = [self::env(), self::ini(), self::fallback()];
|
73 |
+
$memo = self::memoize(call_user_func_array('self::chain', $configProviders));
|
74 |
+
if (isset($config['endpoint_discovery']) && $config['endpoint_discovery'] instanceof CacheInterface) {
|
75 |
+
return self::cache($memo, $config['endpoint_discovery'], self::$cacheKey);
|
76 |
+
}
|
77 |
+
return $memo;
|
78 |
+
}
|
79 |
+
/**
|
80 |
+
* Provider that creates config from environment variables.
|
81 |
+
*
|
82 |
+
* @param $cacheLimit
|
83 |
+
* @return callable
|
84 |
+
*/
|
85 |
+
public static function env($cacheLimit = self::DEFAULT_CACHE_LIMIT)
|
86 |
+
{
|
87 |
+
return function () use($cacheLimit) {
|
88 |
+
// Use config from environment variables, if available
|
89 |
+
$enabled = getenv(self::ENV_ENABLED);
|
90 |
+
if ($enabled === false || $enabled === '') {
|
91 |
+
$enabled = getenv(self::ENV_ENABLED_ALT);
|
92 |
+
}
|
93 |
+
if ($enabled !== false && $enabled !== '') {
|
94 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Configuration($enabled, $cacheLimit));
|
95 |
+
}
|
96 |
+
return self::reject('Could not find environment variable config' . ' in ' . self::ENV_ENABLED);
|
97 |
+
};
|
98 |
+
}
|
99 |
+
/**
|
100 |
+
* Fallback config options when other sources are not set.
|
101 |
+
*
|
102 |
+
* @return callable
|
103 |
+
*/
|
104 |
+
public static function fallback()
|
105 |
+
{
|
106 |
+
return function () {
|
107 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Configuration(self::DEFAULT_ENABLED, self::DEFAULT_CACHE_LIMIT));
|
108 |
+
};
|
109 |
+
}
|
110 |
+
/**
|
111 |
+
* Config provider that creates config using a config file whose location
|
112 |
+
* is specified by an environment variable 'AWS_CONFIG_FILE', defaulting to
|
113 |
+
* ~/.aws/config if not specified
|
114 |
+
*
|
115 |
+
* @param string|null $profile Profile to use. If not specified will use
|
116 |
+
* the "default" profile.
|
117 |
+
* @param string|null $filename If provided, uses a custom filename rather
|
118 |
+
* than looking in the default directory.
|
119 |
+
* @param int $cacheLimit
|
120 |
+
*
|
121 |
+
* @return callable
|
122 |
+
*/
|
123 |
+
public static function ini($profile = null, $filename = null, $cacheLimit = self::DEFAULT_CACHE_LIMIT)
|
124 |
+
{
|
125 |
+
$filename = $filename ?: self::getDefaultConfigFilename();
|
126 |
+
$profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
|
127 |
+
return function () use($profile, $filename, $cacheLimit) {
|
128 |
+
if (!is_readable($filename)) {
|
129 |
+
return self::reject("Cannot read configuration from {$filename}");
|
130 |
+
}
|
131 |
+
$data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($filename, true);
|
132 |
+
if ($data === false) {
|
133 |
+
return self::reject("Invalid config file: {$filename}");
|
134 |
+
}
|
135 |
+
if (!isset($data[$profile])) {
|
136 |
+
return self::reject("'{$profile}' not found in config file");
|
137 |
+
}
|
138 |
+
if (!isset($data[$profile]['endpoint_discovery_enabled'])) {
|
139 |
+
return self::reject("Required endpoint discovery config values \n not present in INI profile '{$profile}' ({$filename})");
|
140 |
+
}
|
141 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Configuration($data[$profile]['endpoint_discovery_enabled'], $cacheLimit));
|
142 |
+
};
|
143 |
+
}
|
144 |
+
/**
|
145 |
+
* Unwraps a configuration object in whatever valid form it is in,
|
146 |
+
* always returning a ConfigurationInterface object.
|
147 |
+
*
|
148 |
+
* @param mixed $config
|
149 |
+
* @return ConfigurationInterface
|
150 |
+
* @throws \InvalidArgumentException
|
151 |
+
*/
|
152 |
+
public static function unwrap($config)
|
153 |
+
{
|
154 |
+
if (is_callable($config)) {
|
155 |
+
$config = $config();
|
156 |
+
}
|
157 |
+
if ($config instanceof PromiseInterface) {
|
158 |
+
$config = $config->wait();
|
159 |
+
}
|
160 |
+
if ($config instanceof ConfigurationInterface) {
|
161 |
+
return $config;
|
162 |
+
} elseif (is_array($config) && isset($config['enabled'])) {
|
163 |
+
if (isset($config['cache_limit'])) {
|
164 |
+
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Configuration($config['enabled'], $config['cache_limit']);
|
165 |
+
}
|
166 |
+
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Configuration($config['enabled'], self::DEFAULT_CACHE_LIMIT);
|
167 |
+
}
|
168 |
+
throw new \InvalidArgumentException('Not a valid endpoint_discovery ' . 'configuration argument.');
|
169 |
+
}
|
170 |
+
}
|
@@ -0,0 +1,240 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException;
|
10 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException;
|
11 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\LruArrayCache;
|
12 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware;
|
13 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
|
14 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface;
|
15 |
+
class EndpointDiscoveryMiddleware
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* @var CacheInterface
|
19 |
+
*/
|
20 |
+
private static $cache;
|
21 |
+
private static $discoveryCooldown = 60;
|
22 |
+
private $args;
|
23 |
+
private $client;
|
24 |
+
private $config;
|
25 |
+
private $discoveryTimes = [];
|
26 |
+
private $nextHandler;
|
27 |
+
private $service;
|
28 |
+
public static function wrap($client, $args, $config)
|
29 |
+
{
|
30 |
+
return function (callable $handler) use($client, $args, $config) {
|
31 |
+
return new static($handler, $client, $args, $config);
|
32 |
+
};
|
33 |
+
}
|
34 |
+
public function __construct(callable $handler, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient $client, array $args, $config)
|
35 |
+
{
|
36 |
+
$this->nextHandler = $handler;
|
37 |
+
$this->client = $client;
|
38 |
+
$this->args = $args;
|
39 |
+
$this->service = $client->getApi();
|
40 |
+
$this->config = $config;
|
41 |
+
}
|
42 |
+
public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
|
43 |
+
{
|
44 |
+
$nextHandler = $this->nextHandler;
|
45 |
+
$op = $this->service->getOperation($cmd->getName())->toArray();
|
46 |
+
// Continue only if endpointdiscovery trait is set
|
47 |
+
if (isset($op['endpointdiscovery'])) {
|
48 |
+
$config = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\ConfigurationProvider::unwrap($this->config);
|
49 |
+
$isRequired = !empty($op['endpointdiscovery']['required']);
|
50 |
+
// Continue only if required by operation or enabled by config
|
51 |
+
if ($isRequired || $config->isEnabled()) {
|
52 |
+
if (isset($op['endpointoperation'])) {
|
53 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException('This operation is ' . 'contradictorily marked both as using endpoint discovery ' . 'and being the endpoint discovery operation. Please ' . 'verify the accuracy of your model files.');
|
54 |
+
}
|
55 |
+
// Original endpoint may be used if discovery optional
|
56 |
+
$originalUri = $request->getUri();
|
57 |
+
$identifiers = $this->getIdentifiers($op);
|
58 |
+
$cacheKey = $this->getCacheKey($this->client->getCredentials()->wait(), $cmd, $identifiers);
|
59 |
+
// Check/create cache
|
60 |
+
if (!isset(self::$cache)) {
|
61 |
+
self::$cache = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\LruArrayCache($config->getCacheLimit());
|
62 |
+
}
|
63 |
+
if (empty($endpointList = self::$cache->get($cacheKey))) {
|
64 |
+
$endpointList = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\EndpointList([]);
|
65 |
+
}
|
66 |
+
$endpoint = $endpointList->getActive();
|
67 |
+
// Retrieve endpoints if there is no active endpoint
|
68 |
+
if (empty($endpoint)) {
|
69 |
+
try {
|
70 |
+
$endpoint = $this->discoverEndpoint($cacheKey, $cmd, $identifiers);
|
71 |
+
} catch (\Exception $e) {
|
72 |
+
// Use cached endpoint, expired or active, if any remain
|
73 |
+
$endpoint = $endpointList->getEndpoint();
|
74 |
+
if (empty($endpoint)) {
|
75 |
+
return $this->handleDiscoveryException($isRequired, $originalUri, $e, $cmd, $request);
|
76 |
+
}
|
77 |
+
}
|
78 |
+
}
|
79 |
+
$request = $this->modifyRequest($request, $endpoint);
|
80 |
+
$g = function ($value) use($cacheKey, $cmd, $identifiers, $isRequired, $originalUri, $request, &$endpoint, &$g) {
|
81 |
+
if ($value instanceof AwsException && ($value->getAwsErrorCode() == 'InvalidEndpointException' || $value->getStatusCode() == 421)) {
|
82 |
+
return $this->handleInvalidEndpoint($cacheKey, $cmd, $identifiers, $isRequired, $originalUri, $request, $value, $endpoint, $g);
|
83 |
+
}
|
84 |
+
return $value;
|
85 |
+
};
|
86 |
+
return $nextHandler($cmd, $request)->otherwise($g);
|
87 |
+
}
|
88 |
+
}
|
89 |
+
return $nextHandler($cmd, $request);
|
90 |
+
}
|
91 |
+
private function discoverEndpoint($cacheKey, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, array $identifiers)
|
92 |
+
{
|
93 |
+
$discCmd = $this->getDiscoveryCommand($cmd, $identifiers);
|
94 |
+
$this->discoveryTimes[$cacheKey] = time();
|
95 |
+
$result = $this->client->execute($discCmd);
|
96 |
+
if (isset($result['Endpoints'])) {
|
97 |
+
$endpointData = [];
|
98 |
+
foreach ($result['Endpoints'] as $datum) {
|
99 |
+
$endpointData[$datum['Address']] = time() + $datum['CachePeriodInMinutes'] * 60;
|
100 |
+
}
|
101 |
+
$endpointList = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\EndpointList($endpointData);
|
102 |
+
self::$cache->set($cacheKey, $endpointList);
|
103 |
+
return $endpointList->getEndpoint();
|
104 |
+
}
|
105 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException('The endpoint discovery operation ' . 'yielded a response that did not contain properly formatted ' . 'endpoint data.');
|
106 |
+
}
|
107 |
+
private function getCacheKey(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface $creds, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, array $identifiers)
|
108 |
+
{
|
109 |
+
$key = $this->service->getServiceName() . '_' . $creds->getAccessKeyId();
|
110 |
+
if (!empty($identifiers)) {
|
111 |
+
$key .= '_' . $cmd->getName();
|
112 |
+
foreach ($identifiers as $identifier) {
|
113 |
+
$key .= "_{$cmd[$identifier]}";
|
114 |
+
}
|
115 |
+
}
|
116 |
+
return $key;
|
117 |
+
}
|
118 |
+
private function getDiscoveryCommand(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, array $identifiers)
|
119 |
+
{
|
120 |
+
foreach ($this->service->getOperations() as $op) {
|
121 |
+
if (isset($op['endpointoperation'])) {
|
122 |
+
$endpointOperation = $op->toArray()['name'];
|
123 |
+
break;
|
124 |
+
}
|
125 |
+
}
|
126 |
+
if (!isset($endpointOperation)) {
|
127 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException('This command is set to use ' . 'endpoint discovery, but no endpoint discovery operation was ' . 'found. Please verify the accuracy of your model files.');
|
128 |
+
}
|
129 |
+
$params = [];
|
130 |
+
if (!empty($identifiers)) {
|
131 |
+
$params['Operation'] = $cmd->getName();
|
132 |
+
$params['Identifiers'] = [];
|
133 |
+
foreach ($identifiers as $identifier) {
|
134 |
+
$params['Identifiers'][$identifier] = $cmd[$identifier];
|
135 |
+
}
|
136 |
+
}
|
137 |
+
$command = $this->client->getCommand($endpointOperation, $params);
|
138 |
+
$command->getHandlerList()->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::mapRequest(function (\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $r) {
|
139 |
+
return $r->withHeader('x-amz-api-version', $this->service->getApiVersion());
|
140 |
+
}), 'x-amz-api-version-header');
|
141 |
+
return $command;
|
142 |
+
}
|
143 |
+
private function getIdentifiers(array $operation)
|
144 |
+
{
|
145 |
+
$inputShape = $this->service->getShapeMap()->resolve($operation['input'])->toArray();
|
146 |
+
$identifiers = [];
|
147 |
+
foreach ($inputShape['members'] as $key => $member) {
|
148 |
+
if (!empty($member['endpointdiscoveryid'])) {
|
149 |
+
$identifiers[] = $key;
|
150 |
+
}
|
151 |
+
}
|
152 |
+
return $identifiers;
|
153 |
+
}
|
154 |
+
private function handleDiscoveryException($isRequired, $originalUri, \Exception $e, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
|
155 |
+
{
|
156 |
+
// If no cached endpoints and discovery required,
|
157 |
+
// throw exception
|
158 |
+
if ($isRequired) {
|
159 |
+
$message = 'The endpoint required for this service is currently ' . 'unable to be retrieved, and your request can not be fulfilled ' . 'unless you manually specify an endpoint.';
|
160 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException($message, $cmd, ['code' => 'EndpointDiscoveryException', 'message' => $message], $e);
|
161 |
+
}
|
162 |
+
// If discovery isn't required, use original endpoint
|
163 |
+
return $this->useOriginalUri($originalUri, $cmd, $request);
|
164 |
+
}
|
165 |
+
private function handleInvalidEndpoint($cacheKey, $cmd, $identifiers, $isRequired, $originalUri, $request, $value, &$endpoint, &$g)
|
166 |
+
{
|
167 |
+
$nextHandler = $this->nextHandler;
|
168 |
+
$endpointList = self::$cache->get($cacheKey);
|
169 |
+
if ($endpointList instanceof EndpointList) {
|
170 |
+
// Remove invalid endpoint from cached list
|
171 |
+
$endpointList->remove($endpoint);
|
172 |
+
// If possible, get another cached endpoint
|
173 |
+
$newEndpoint = $endpointList->getEndpoint();
|
174 |
+
}
|
175 |
+
if (empty($newEndpoint)) {
|
176 |
+
// If no more cached endpoints, make discovery call
|
177 |
+
// if none made within cooldown for given key
|
178 |
+
if (time() - $this->discoveryTimes[$cacheKey] < self::$discoveryCooldown) {
|
179 |
+
// If no more cached endpoints and it's required,
|
180 |
+
// fail with original exception
|
181 |
+
if ($isRequired) {
|
182 |
+
return $value;
|
183 |
+
}
|
184 |
+
// Use original endpoint if not required
|
185 |
+
return $this->useOriginalUri($originalUri, $cmd, $request);
|
186 |
+
}
|
187 |
+
$newEndpoint = $this->discoverEndpoint($cacheKey, $cmd, $identifiers);
|
188 |
+
}
|
189 |
+
$endpoint = $newEndpoint;
|
190 |
+
$request = $this->modifyRequest($request, $endpoint);
|
191 |
+
return $nextHandler($cmd, $request)->otherwise($g);
|
192 |
+
}
|
193 |
+
private function modifyRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, $endpoint)
|
194 |
+
{
|
195 |
+
$parsed = $this->parseEndpoint($endpoint);
|
196 |
+
if (!empty($request->getHeader('User-Agent'))) {
|
197 |
+
$userAgent = $request->getHeader('User-Agent')[0];
|
198 |
+
if (strpos($userAgent, 'endpoint-discovery') === false) {
|
199 |
+
$userAgent = $userAgent . ' endpoint-discovery';
|
200 |
+
}
|
201 |
+
} else {
|
202 |
+
$userAgent = 'endpoint-discovery';
|
203 |
+
}
|
204 |
+
return $request->withUri($request->getUri()->withHost($parsed['host'])->withPath($parsed['path']))->withHeader('User-Agent', $userAgent);
|
205 |
+
}
|
206 |
+
/**
|
207 |
+
* Parses an endpoint returned from the discovery API into an array with
|
208 |
+
* 'host' and 'path' keys.
|
209 |
+
*
|
210 |
+
* @param $endpoint
|
211 |
+
* @return array
|
212 |
+
*/
|
213 |
+
private function parseEndpoint($endpoint)
|
214 |
+
{
|
215 |
+
$parsed = parse_url($endpoint);
|
216 |
+
// parse_url() will correctly parse full URIs with schemes
|
217 |
+
if (isset($parsed['host'])) {
|
218 |
+
return $parsed;
|
219 |
+
}
|
220 |
+
// parse_url() will put host & path in 'path' if scheme is not provided
|
221 |
+
if (isset($parsed['path'])) {
|
222 |
+
$split = explode('/', $parsed['path'], 2);
|
223 |
+
$parsed['host'] = $split[0];
|
224 |
+
if (isset($split[1])) {
|
225 |
+
$parsed['path'] = $split[1];
|
226 |
+
} else {
|
227 |
+
$parsed['path'] = '';
|
228 |
+
}
|
229 |
+
return $parsed;
|
230 |
+
}
|
231 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException("The supplied endpoint '" . "{$endpoint}' is invalid.");
|
232 |
+
}
|
233 |
+
private function useOriginalUri(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface $uri, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
|
234 |
+
{
|
235 |
+
$nextHandler = $this->nextHandler;
|
236 |
+
$endpoint = $uri->getHost() . $uri->getPath();
|
237 |
+
$request = $this->modifyRequest($request, $endpoint);
|
238 |
+
return $nextHandler($cmd, $request);
|
239 |
+
}
|
240 |
+
}
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery;
|
4 |
+
|
5 |
+
class EndpointList
|
6 |
+
{
|
7 |
+
private $active;
|
8 |
+
private $expired = [];
|
9 |
+
public function __construct(array $endpoints)
|
10 |
+
{
|
11 |
+
$this->active = $endpoints;
|
12 |
+
reset($this->active);
|
13 |
+
}
|
14 |
+
/**
|
15 |
+
* Gets an active (unexpired) endpoint. Returns null if none found.
|
16 |
+
*
|
17 |
+
* @return null|string
|
18 |
+
*/
|
19 |
+
public function getActive()
|
20 |
+
{
|
21 |
+
if (count($this->active) < 1) {
|
22 |
+
return null;
|
23 |
+
}
|
24 |
+
while (time() > current($this->active)) {
|
25 |
+
$key = key($this->active);
|
26 |
+
$this->expired[$key] = current($this->active);
|
27 |
+
$this->increment($this->active);
|
28 |
+
unset($this->active[$key]);
|
29 |
+
if (count($this->active) < 1) {
|
30 |
+
return null;
|
31 |
+
}
|
32 |
+
}
|
33 |
+
$active = key($this->active);
|
34 |
+
$this->increment($this->active);
|
35 |
+
return $active;
|
36 |
+
}
|
37 |
+
/**
|
38 |
+
* Gets an active endpoint if possible, then an expired endpoint if possible.
|
39 |
+
* Returns null if no endpoints found.
|
40 |
+
*
|
41 |
+
* @return null|string
|
42 |
+
*/
|
43 |
+
public function getEndpoint()
|
44 |
+
{
|
45 |
+
if (!empty($active = $this->getActive())) {
|
46 |
+
return $active;
|
47 |
+
}
|
48 |
+
return $this->getExpired();
|
49 |
+
}
|
50 |
+
/**
|
51 |
+
* Removes an endpoint from both lists.
|
52 |
+
*
|
53 |
+
* @param string $key
|
54 |
+
*/
|
55 |
+
public function remove($key)
|
56 |
+
{
|
57 |
+
unset($this->active[$key]);
|
58 |
+
unset($this->expired[$key]);
|
59 |
+
}
|
60 |
+
/**
|
61 |
+
* Get an expired endpoint. Returns null if none found.
|
62 |
+
*
|
63 |
+
* @return null|string
|
64 |
+
*/
|
65 |
+
private function getExpired()
|
66 |
+
{
|
67 |
+
if (count($this->expired) < 1) {
|
68 |
+
return null;
|
69 |
+
}
|
70 |
+
$expired = key($this->expired);
|
71 |
+
$this->increment($this->expired);
|
72 |
+
return $expired;
|
73 |
+
}
|
74 |
+
private function increment(&$array)
|
75 |
+
{
|
76 |
+
if (next($array) === false) {
|
77 |
+
reset($array);
|
78 |
+
}
|
79 |
+
}
|
80 |
+
}
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\EndpointDiscovery\Exception;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
|
7 |
+
/**
|
8 |
+
* Represents an error interacting with configuration for endpoint discovery
|
9 |
+
*/
|
10 |
+
class ConfigurationException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface
|
11 |
+
{
|
12 |
+
use HasMonitoringEventsTrait;
|
13 |
+
}
|
@@ -14,6 +14,10 @@ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Log\InvalidArgumentException;
|
|
14 |
*/
|
15 |
class EndpointParameterMiddleware
|
16 |
{
|
|
|
|
|
|
|
|
|
17 |
/**
|
18 |
* Create a middleware wrapper function
|
19 |
*
|
14 |
*/
|
15 |
class EndpointParameterMiddleware
|
16 |
{
|
17 |
+
/** @var callable */
|
18 |
+
private $nextHandler;
|
19 |
+
/** @var Service */
|
20 |
+
private $service;
|
21 |
/**
|
22 |
* Create a middleware wrapper function
|
23 |
*
|
@@ -2,18 +2,21 @@
|
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception;
|
4 |
|
|
|
|
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface;
|
|
|
|
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
|
10 |
-
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
|
11 |
-
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
|
12 |
/**
|
13 |
* Represents an AWS exception that is thrown when a command fails.
|
14 |
*/
|
15 |
-
class AwsException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface
|
16 |
{
|
|
|
17 |
use HasMonitoringEventsTrait;
|
18 |
/** @var ResponseInterface */
|
19 |
private $response;
|
@@ -35,6 +38,7 @@ class AwsException extends \RuntimeException implements \DeliciousBrains\WP_Offl
|
|
35 |
*/
|
36 |
public function __construct($message, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, array $context = [], \Exception $previous = null)
|
37 |
{
|
|
|
38 |
$this->command = $command;
|
39 |
$this->response = isset($context['response']) ? $context['response'] : null;
|
40 |
$this->request = isset($context['request']) ? $context['request'] : null;
|
@@ -195,4 +199,16 @@ class AwsException extends \RuntimeException implements \DeliciousBrains\WP_Offl
|
|
195 |
{
|
196 |
$this->maxRetriesExceeded = true;
|
197 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
}
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception;
|
4 |
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasDataTrait;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface;
|
10 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
|
11 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\JmesPath\Env as JmesPath;
|
12 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
13 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
|
|
|
|
|
14 |
/**
|
15 |
* Represents an AWS exception that is thrown when a command fails.
|
16 |
*/
|
17 |
+
class AwsException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResponseContainerInterface, \ArrayAccess
|
18 |
{
|
19 |
+
use HasDataTrait;
|
20 |
use HasMonitoringEventsTrait;
|
21 |
/** @var ResponseInterface */
|
22 |
private $response;
|
38 |
*/
|
39 |
public function __construct($message, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, array $context = [], \Exception $previous = null)
|
40 |
{
|
41 |
+
$this->data = isset($context['body']) ? $context['body'] : [];
|
42 |
$this->command = $command;
|
43 |
$this->response = isset($context['response']) ? $context['response'] : null;
|
44 |
$this->request = isset($context['request']) ? $context['request'] : null;
|
199 |
{
|
200 |
$this->maxRetriesExceeded = true;
|
201 |
}
|
202 |
+
public function hasKey($name)
|
203 |
+
{
|
204 |
+
return isset($this->data[$name]);
|
205 |
+
}
|
206 |
+
public function get($key)
|
207 |
+
{
|
208 |
+
return $this[$key];
|
209 |
+
}
|
210 |
+
public function search($expression)
|
211 |
+
{
|
212 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\JmesPath\Env::search($expression, $this->toArray());
|
213 |
+
}
|
214 |
}
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
|
7 |
+
class IncalculablePayloadException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface
|
8 |
+
{
|
9 |
+
use HasMonitoringEventsTrait;
|
10 |
+
}
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
|
7 |
+
class InvalidJsonException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface
|
8 |
+
{
|
9 |
+
use HasMonitoringEventsTrait;
|
10 |
+
}
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
|
7 |
+
class InvalidRegionException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface
|
8 |
+
{
|
9 |
+
use HasMonitoringEventsTrait;
|
10 |
+
}
|
@@ -25,7 +25,7 @@ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\StreamInterface as Ps
|
|
25 |
*/
|
26 |
class GuzzleHandler
|
27 |
{
|
28 |
-
private static $validOptions = ['proxy' => true, 'verify' => true, 'timeout' => true, 'debug' => true, 'connect_timeout' => true, 'stream' => true, 'delay' => true, 'sink' => true];
|
29 |
/** @var ClientInterface */
|
30 |
private $client;
|
31 |
/**
|
@@ -37,9 +37,9 @@ class GuzzleHandler
|
|
37 |
}
|
38 |
/**
|
39 |
* @param Psr7Request $request
|
40 |
-
* @param array
|
41 |
-
*
|
42 |
-
* @
|
43 |
*/
|
44 |
public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, array $options = [])
|
45 |
{
|
25 |
*/
|
26 |
class GuzzleHandler
|
27 |
{
|
28 |
+
private static $validOptions = ['proxy' => true, 'expect' => true, 'cert' => true, 'verify' => true, 'timeout' => true, 'debug' => true, 'connect_timeout' => true, 'stream' => true, 'delay' => true, 'sink' => true];
|
29 |
/** @var ClientInterface */
|
30 |
private $client;
|
31 |
/**
|
37 |
}
|
38 |
/**
|
39 |
* @param Psr7Request $request
|
40 |
+
* @param array $options
|
41 |
+
* @return Promise\Promise|Promise\PromiseInterface
|
42 |
+
* @throws \GuzzleHttp\Exception\GuzzleException
|
43 |
*/
|
44 |
public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, array $options = [])
|
45 |
{
|
@@ -19,6 +19,8 @@ class MultiRegionClient implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Aw
|
|
19 |
private $config;
|
20 |
/** @var HandlerList */
|
21 |
private $handlerList;
|
|
|
|
|
22 |
public static function getArguments()
|
23 |
{
|
24 |
$args = array_intersect_key(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientResolver::getDefaultArguments(), ['service' => true, 'region' => true]);
|
19 |
private $config;
|
20 |
/** @var HandlerList */
|
21 |
private $handlerList;
|
22 |
+
/** @var array */
|
23 |
+
private $aliases;
|
24 |
public static function getArguments()
|
25 |
{
|
26 |
$args = array_intersect_key(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientResolver::getDefaultArguments(), ['service' => true, 'region' => true]);
|
@@ -100,13 +100,27 @@ abstract class AbstractUploadManager implements \DeliciousBrains\WP_Offload_Medi
|
|
100 |
// Complete the multipart upload.
|
101 |
(yield $this->execCommand('complete', $this->getCompleteParams()));
|
102 |
$this->state->setStatus(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Multipart\UploadState::COMPLETED);
|
103 |
-
})->otherwise(
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
}
|
111 |
protected function getConfig()
|
112 |
{
|
100 |
// Complete the multipart upload.
|
101 |
(yield $this->execCommand('complete', $this->getCompleteParams()));
|
102 |
$this->state->setStatus(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Multipart\UploadState::COMPLETED);
|
103 |
+
})->otherwise($this->buildFailureCatch());
|
104 |
+
}
|
105 |
+
private function transformException($e)
|
106 |
+
{
|
107 |
+
// Throw errors from the operations as a specific Multipart error.
|
108 |
+
if ($e instanceof AwsException) {
|
109 |
+
$e = new $this->config['exception_class']($this->state, $e);
|
110 |
+
}
|
111 |
+
throw $e;
|
112 |
+
}
|
113 |
+
private function buildFailureCatch()
|
114 |
+
{
|
115 |
+
if (interface_exists("Throwable")) {
|
116 |
+
return function (\Throwable $e) {
|
117 |
+
return $this->transformException($e);
|
118 |
+
};
|
119 |
+
} else {
|
120 |
+
return function (\Exception $e) {
|
121 |
+
return $this->transformException($e);
|
122 |
+
};
|
123 |
+
}
|
124 |
}
|
125 |
protected function getConfig()
|
126 |
{
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\SimpleCache\CacheInterface as SimpleCacheInterface;
|
6 |
+
class Psr16CacheAdapter implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface
|
7 |
+
{
|
8 |
+
/** @var SimpleCacheInterface */
|
9 |
+
private $cache;
|
10 |
+
public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\SimpleCache\CacheInterface $cache)
|
11 |
+
{
|
12 |
+
$this->cache = $cache;
|
13 |
+
}
|
14 |
+
public function get($key)
|
15 |
+
{
|
16 |
+
return $this->cache->get($key);
|
17 |
+
}
|
18 |
+
public function set($key, $value, $ttl = 0)
|
19 |
+
{
|
20 |
+
$this->cache->set($key, $value, $ttl);
|
21 |
+
}
|
22 |
+
public function remove($key)
|
23 |
+
{
|
24 |
+
$this->cache->delete($key);
|
25 |
+
}
|
26 |
+
}
|
@@ -2,6 +2,7 @@
|
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
4 |
|
|
|
5 |
interface ResponseContainerInterface
|
6 |
{
|
7 |
/**
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
4 |
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
|
6 |
interface ResponseContainerInterface
|
7 |
{
|
8 |
/**
|
@@ -23,6 +23,9 @@ class RetryMiddleware
|
|
23 |
'RequestThrottled' => true,
|
24 |
'BandwidthLimitExceeded' => true,
|
25 |
'RequestThrottledException' => true,
|
|
|
|
|
|
|
26 |
];
|
27 |
private $decider;
|
28 |
private $delay;
|
@@ -92,6 +95,9 @@ class RetryMiddleware
|
|
92 |
}
|
93 |
}
|
94 |
if (!$error) {
|
|
|
|
|
|
|
95 |
return isset($statusCodes[$result['@metadata']['statusCode']]);
|
96 |
}
|
97 |
if (!$error instanceof AwsException) {
|
23 |
'RequestThrottled' => true,
|
24 |
'BandwidthLimitExceeded' => true,
|
25 |
'RequestThrottledException' => true,
|
26 |
+
'TooManyRequestsException' => true,
|
27 |
+
'IDPCommunicationError' => true,
|
28 |
+
'EC2ThrottledException' => true,
|
29 |
];
|
30 |
private $decider;
|
31 |
private $delay;
|
95 |
}
|
96 |
}
|
97 |
if (!$error) {
|
98 |
+
if (!isset($result['@metadata']['statusCode'])) {
|
99 |
+
return false;
|
100 |
+
}
|
101 |
return isset($statusCodes[$result['@metadata']['statusCode']]);
|
102 |
}
|
103 |
if (!$error instanceof AwsException) {
|
@@ -0,0 +1,200 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnInterface;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn;
|
10 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
|
11 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider;
|
12 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\InvalidRegionException;
|
13 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException;
|
14 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception;
|
15 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
|
16 |
+
/**
|
17 |
+
* Checks for access point ARN in members targeting BucketName, modifying
|
18 |
+
* endpoint as appropriate
|
19 |
+
*
|
20 |
+
* @internal
|
21 |
+
*/
|
22 |
+
class BucketEndpointArnMiddleware
|
23 |
+
{
|
24 |
+
/** @var Service */
|
25 |
+
private $service;
|
26 |
+
/** @var callable */
|
27 |
+
private $nextHandler;
|
28 |
+
/** @var string */
|
29 |
+
private $region;
|
30 |
+
/** @var $config */
|
31 |
+
private $config;
|
32 |
+
/** @var PartitionEndpointProvider */
|
33 |
+
private $partitionProvider;
|
34 |
+
/** @var array */
|
35 |
+
private $nonArnableCommands = ['CreateBucket'];
|
36 |
+
/**
|
37 |
+
* Create a middleware wrapper function.
|
38 |
+
*
|
39 |
+
* @param Service $service
|
40 |
+
* @param $region
|
41 |
+
* @param array $config
|
42 |
+
* @return callable
|
43 |
+
*/
|
44 |
+
public static function wrap(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $service, $region, array $config)
|
45 |
+
{
|
46 |
+
return function (callable $handler) use($service, $region, $config) {
|
47 |
+
return new self($handler, $service, $region, $config);
|
48 |
+
};
|
49 |
+
}
|
50 |
+
public function __construct(callable $nextHandler, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $service, $region, array $config = [])
|
51 |
+
{
|
52 |
+
$this->partitionProvider = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider::defaultProvider();
|
53 |
+
$this->region = $region;
|
54 |
+
$this->service = $service;
|
55 |
+
$this->config = $config;
|
56 |
+
$this->nextHandler = $nextHandler;
|
57 |
+
}
|
58 |
+
public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $cmd, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $req)
|
59 |
+
{
|
60 |
+
$nextHandler = $this->nextHandler;
|
61 |
+
$op = $this->service->getOperation($cmd->getName())->toArray();
|
62 |
+
if (!empty($op['input']['shape'])) {
|
63 |
+
$service = $this->service->toArray();
|
64 |
+
if (!empty($input = $service['shapes'][$op['input']['shape']])) {
|
65 |
+
foreach ($input['members'] as $key => $member) {
|
66 |
+
if ($member['shape'] === 'BucketName') {
|
67 |
+
$arnableKey = $key;
|
68 |
+
break;
|
69 |
+
}
|
70 |
+
}
|
71 |
+
if (!empty($arnableKey) && \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser::isArn($cmd[$arnableKey])) {
|
72 |
+
try {
|
73 |
+
// Throw for commands that do not support ARN inputs
|
74 |
+
if (in_array($cmd->getName(), $this->nonArnableCommands)) {
|
75 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception('ARN values cannot be used in the bucket field for' . ' the ' . $cmd->getName() . ' operation.', $cmd);
|
76 |
+
}
|
77 |
+
$arn = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser::parse($cmd[$arnableKey]);
|
78 |
+
$partition = $this->validateArn($arn);
|
79 |
+
$host = $this->generateAccessPointHost($arn, $req);
|
80 |
+
// Remove encoded bucket string from path
|
81 |
+
$path = $req->getUri()->getPath();
|
82 |
+
$encoded = rawurlencode($cmd[$arnableKey]);
|
83 |
+
$len = strlen($encoded) + 1;
|
84 |
+
if (substr($path, 0, $len) === "/{$encoded}") {
|
85 |
+
$path = substr($path, $len);
|
86 |
+
}
|
87 |
+
if (empty($path)) {
|
88 |
+
$path = '';
|
89 |
+
}
|
90 |
+
// Set modified request
|
91 |
+
$req = $req->withUri($req->getUri()->withHost($host)->withPath($path));
|
92 |
+
// Update signing region based on ARN data if configured to do so
|
93 |
+
if ($this->config['use_arn_region']->isUseArnRegion()) {
|
94 |
+
$region = $arn->getRegion();
|
95 |
+
} else {
|
96 |
+
$region = $this->region;
|
97 |
+
}
|
98 |
+
$endpointData = $partition(['region' => $region, 'service' => $arn->getService()]);
|
99 |
+
$cmd['@context']['signing_region'] = $endpointData['signingRegion'];
|
100 |
+
} catch (InvalidArnException $e) {
|
101 |
+
// Add context to ARN exception
|
102 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception('Bucket parameter parsed as ARN and failed with: ' . $e->getMessage(), $cmd, [], $e);
|
103 |
+
}
|
104 |
+
}
|
105 |
+
}
|
106 |
+
}
|
107 |
+
return $nextHandler($cmd, $req);
|
108 |
+
}
|
109 |
+
private function generateAccessPointHost(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn $arn, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $req)
|
110 |
+
{
|
111 |
+
$host = $arn->getResourceId() . '-' . $arn->getAccountId() . '.s3-accesspoint';
|
112 |
+
if (!empty($this->config['dual_stack'])) {
|
113 |
+
$host .= '.dualstack';
|
114 |
+
}
|
115 |
+
if (!empty($this->config['use_arn_region']->isUseArnRegion())) {
|
116 |
+
$region = $arn->getRegion();
|
117 |
+
} else {
|
118 |
+
$region = $this->region;
|
119 |
+
}
|
120 |
+
$host .= '.' . $region . '.' . $this->getPartitionSuffix($arn);
|
121 |
+
return $host;
|
122 |
+
}
|
123 |
+
private function getPartitionSuffix(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnInterface $arn)
|
124 |
+
{
|
125 |
+
$partition = $this->partitionProvider->getPartition($arn->getRegion(), $arn->getService());
|
126 |
+
return $partition->getDnsSuffix();
|
127 |
+
}
|
128 |
+
private function getSigningRegion($region)
|
129 |
+
{
|
130 |
+
$partition = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Endpoint\PartitionEndpointProvider::defaultProvider()->getPartition($region, 's3');
|
131 |
+
$data = $partition->toArray();
|
132 |
+
if (isset($data['services']['s3']['endpoints'][$region]['credentialScope']['region'])) {
|
133 |
+
return $data['services']['s3']['endpoints'][$region]['credentialScope']['region'];
|
134 |
+
}
|
135 |
+
return $region;
|
136 |
+
}
|
137 |
+
private function isMatchingSigningRegion($arnRegion, $clientRegion)
|
138 |
+
{
|
139 |
+
$arnRegion = strtolower($arnRegion);
|
140 |
+
$clientRegion = $this->stripPseudoRegions(strtolower($clientRegion));
|
141 |
+
if ($arnRegion === $clientRegion) {
|
142 |
+
return true;
|
143 |
+
}
|
144 |
+
if ($this->getSigningRegion($clientRegion) === $arnRegion) {
|
145 |
+
return true;
|
146 |
+
}
|
147 |
+
return false;
|
148 |
+
}
|
149 |
+
private function stripPseudoRegions($region)
|
150 |
+
{
|
151 |
+
return str_replace(['fips-', '-fips'], ['', ''], $region);
|
152 |
+
}
|
153 |
+
/**
|
154 |
+
* Validates an ARN, returning a partition object corresponding to the ARN
|
155 |
+
* if successful
|
156 |
+
*
|
157 |
+
* @param $arn
|
158 |
+
* @return \Aws\Endpoint\Partition
|
159 |
+
*/
|
160 |
+
private function validateArn($arn)
|
161 |
+
{
|
162 |
+
if ($arn instanceof AccessPointArn) {
|
163 |
+
// Accelerate is not supported with access points
|
164 |
+
if (!empty($this->config['accelerate'])) {
|
165 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException('Accelerate is currently not supported with access points.' . ' Please disable accelerate or do not supply an access' . ' point ARN.');
|
166 |
+
}
|
167 |
+
// Path-style is not supported with access points
|
168 |
+
if (!empty($this->config['path_style'])) {
|
169 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException('Path-style addressing is currently not supported with' . ' access points. Please disable path-style or do not' . ' supply an access point ARN.');
|
170 |
+
}
|
171 |
+
// Custom endpoint is not supported with access points
|
172 |
+
if (!is_null($this->config['endpoint'])) {
|
173 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedEndpointException('A custom endpoint has been supplied along with an access' . ' point ARN, and these are not compatible with each other.' . ' Please only use one or the other.');
|
174 |
+
}
|
175 |
+
// Get partitions for ARN and client region
|
176 |
+
$arnPart = $this->partitionProvider->getPartition($arn->getRegion(), 's3');
|
177 |
+
$clientPart = $this->partitionProvider->getPartition($this->region, 's3');
|
178 |
+
// If client partition not found, try removing pseudo-region qualifiers
|
179 |
+
if (!$clientPart->isRegionMatch($this->region, 's3')) {
|
180 |
+
$clientPart = $this->partitionProvider->getPartition($this->stripPseudoRegions($this->region), 's3');
|
181 |
+
}
|
182 |
+
// Verify that the partition matches for supplied partition and region
|
183 |
+
if ($arn->getPartition() !== $clientPart->getName()) {
|
184 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\InvalidRegionException('The supplied ARN partition' . " does not match the client's partition.");
|
185 |
+
}
|
186 |
+
if ($clientPart->getName() !== $arnPart->getName()) {
|
187 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\InvalidRegionException('The corresponding partition' . ' for the supplied ARN region does not match the' . " client's partition.");
|
188 |
+
}
|
189 |
+
// Ensure ARN region matches client region unless
|
190 |
+
// configured for using ARN region over client region
|
191 |
+
if (!$this->isMatchingSigningRegion($arn->getRegion(), $this->region)) {
|
192 |
+
if (empty($this->config['use_arn_region']) || !$this->config['use_arn_region']->isUseArnRegion()) {
|
193 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\InvalidRegionException('The region' . " specified in the ARN (" . $arn->getRegion() . ") does not match the client region (" . "{$this->region}).");
|
194 |
+
}
|
195 |
+
}
|
196 |
+
return $arnPart;
|
197 |
+
}
|
198 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException('Provided ARN was not' . ' a valid S3 access point ARN');
|
199 |
+
}
|
200 |
+
}
|
@@ -2,6 +2,7 @@
|
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
|
4 |
|
|
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Multipart\AbstractUploadManager;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
|
@@ -54,7 +55,12 @@ class MultipartCopy extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Multipart
|
|
54 |
*/
|
55 |
public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3ClientInterface $client, $source, array $config = [])
|
56 |
{
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
58 |
parent::__construct($client, array_change_key_case($config) + ['source_metadata' => null]);
|
59 |
}
|
60 |
/**
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
|
4 |
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Multipart\AbstractUploadManager;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
|
55 |
*/
|
56 |
public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3ClientInterface $client, $source, array $config = [])
|
57 |
{
|
58 |
+
if (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser::isArn($source)) {
|
59 |
+
$this->source = '';
|
60 |
+
} else {
|
61 |
+
$this->source = "/";
|
62 |
+
}
|
63 |
+
$this->source .= ltrim($source, '/');
|
64 |
parent::__construct($client, array_change_key_case($config) + ['source_metadata' => null]);
|
65 |
}
|
66 |
/**
|
@@ -35,7 +35,7 @@ class MultipartUploader extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Multi
|
|
35 |
* operations. The callback should have a function signature like
|
36 |
* `function (Aws\Command $command) {...}`.
|
37 |
* - bucket: (string, required) Name of the bucket to which the object is
|
38 |
-
* being uploaded.
|
39 |
* - concurrency: (int, default=int(5)) Maximum number of concurrent
|
40 |
* `UploadPart` operations allowed during the multipart upload.
|
41 |
* - key: (string, required) Key to use for the object being uploaded.
|
35 |
* operations. The callback should have a function signature like
|
36 |
* `function (Aws\Command $command) {...}`.
|
37 |
* - bucket: (string, required) Name of the bucket to which the object is
|
38 |
+
* being uploaded, or an S3 access point ARN.
|
39 |
* - concurrency: (int, default=int(5)) Maximum number of concurrent
|
40 |
* `UploadPart` operations allowed during the multipart upload.
|
41 |
* - key: (string, required) Key to use for the object being uploaded.
|
@@ -2,6 +2,8 @@
|
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
|
4 |
|
|
|
|
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\MultipartUploadException;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Result;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception;
|
@@ -95,6 +97,13 @@ class ObjectCopier implements \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\
|
|
95 |
}
|
96 |
private function getSourcePath()
|
97 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
$sourcePath = "/{$this->source['Bucket']}/" . rawurlencode($this->source['Key']);
|
99 |
if (isset($this->source['VersionId'])) {
|
100 |
$sourcePath .= "?versionId={$this->source['VersionId']}";
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
|
4 |
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\MultipartUploadException;
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Result;
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception;
|
97 |
}
|
98 |
private function getSourcePath()
|
99 |
{
|
100 |
+
if (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser::isArn($this->source['Bucket'])) {
|
101 |
+
try {
|
102 |
+
new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn($this->source['Bucket']);
|
103 |
+
} catch (\Exception $e) {
|
104 |
+
throw new \InvalidArgumentException('Provided ARN was a not a valid S3 access point ARN (' . $e->getMessage() . ')', 0, $e);
|
105 |
+
}
|
106 |
+
}
|
107 |
$sourcePath = "/{$this->source['Bucket']}/" . rawurlencode($this->source['Key']);
|
108 |
if (isset($this->source['VersionId'])) {
|
109 |
$sourcePath .= "?versionId={$this->source['VersionId']}";
|
@@ -22,7 +22,8 @@ class ObjectUploader implements \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHtt
|
|
22 |
/**
|
23 |
* @param S3ClientInterface $client The S3 Client used to execute
|
24 |
* the upload command(s).
|
25 |
-
* @param string $bucket Bucket to upload the object
|
|
|
26 |
* @param string $key Key of the object.
|
27 |
* @param mixed $body Object data to upload. Can be a
|
28 |
* StreamInterface, PHP stream
|
@@ -93,7 +94,7 @@ class ObjectUploader implements \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHtt
|
|
93 |
return false;
|
94 |
}
|
95 |
// If body >= 5 MB, then use multipart. [YES]
|
96 |
-
if ($body->isSeekable()) {
|
97 |
// If the body is seekable, just rewind the body.
|
98 |
$body->seek(0);
|
99 |
} else {
|
22 |
/**
|
23 |
* @param S3ClientInterface $client The S3 Client used to execute
|
24 |
* the upload command(s).
|
25 |
+
* @param string $bucket Bucket to upload the object, or
|
26 |
+
* an S3 access point ARN.
|
27 |
* @param string $key Key of the object.
|
28 |
* @param mixed $body Object data to upload. Can be a
|
29 |
* StreamInterface, PHP stream
|
94 |
return false;
|
95 |
}
|
96 |
// If body >= 5 MB, then use multipart. [YES]
|
97 |
+
if ($body->isSeekable() && $body->getMetadata('uri') !== 'php://input') {
|
98 |
// If the body is seekable, just rewind the body.
|
99 |
$body->seek(0);
|
100 |
} else {
|
@@ -40,7 +40,7 @@ class PutObjectUrlMiddleware
|
|
40 |
switch ($name) {
|
41 |
case 'PutObject':
|
42 |
case 'CopyObject':
|
43 |
-
$result['ObjectURL'] = $result['@metadata']['effectiveUri'];
|
44 |
break;
|
45 |
case 'CompleteMultipartUpload':
|
46 |
$result['ObjectURL'] = $result['Location'];
|
40 |
switch ($name) {
|
41 |
case 'PutObject':
|
42 |
case 'CopyObject':
|
43 |
+
$result['ObjectURL'] = isset($result['@metadata']['effectiveUri']) ? $result['@metadata']['effectiveUri'] : null;
|
44 |
break;
|
45 |
case 'CompleteMultipartUpload':
|
46 |
$result['ObjectURL'] = $result['Location'];
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint;
|
4 |
+
|
5 |
+
class Configuration implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationInterface
|
6 |
+
{
|
7 |
+
private $endpointsType;
|
8 |
+
public function __construct($endpointsType)
|
9 |
+
{
|
10 |
+
$this->endpointsType = strtolower($endpointsType);
|
11 |
+
if (!in_array($this->endpointsType, ['legacy', 'regional'])) {
|
12 |
+
throw new \InvalidArgumentException("Configuration parameter must either be 'legacy' or 'regional'.");
|
13 |
+
}
|
14 |
+
}
|
15 |
+
/**
|
16 |
+
* {@inheritdoc}
|
17 |
+
*/
|
18 |
+
public function getEndpointsType()
|
19 |
+
{
|
20 |
+
return $this->endpointsType;
|
21 |
+
}
|
22 |
+
/**
|
23 |
+
* {@inheritdoc}
|
24 |
+
*/
|
25 |
+
public function toArray()
|
26 |
+
{
|
27 |
+
return ['endpoints_type' => $this->getEndpointsType()];
|
28 |
+
}
|
29 |
+
}
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Provides access to S3 regional endpoints configuration options: endpoints_type
|
7 |
+
*/
|
8 |
+
interface ConfigurationInterface
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Returns the endpoints type
|
12 |
+
*
|
13 |
+
* @return string
|
14 |
+
*/
|
15 |
+
public function getEndpointsType();
|
16 |
+
/**
|
17 |
+
* Returns the configuration as an associative array
|
18 |
+
*
|
19 |
+
* @return array
|
20 |
+
*/
|
21 |
+
public function toArray();
|
22 |
+
}
|
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Exception\ConfigurationException;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
10 |
+
/**
|
11 |
+
* A configuration provider is a function that returns a promise that is
|
12 |
+
* fulfilled with a {@see \Aws\S3\RegionalEndpoint\ConfigurationInterface}
|
13 |
+
* or rejected with an {@see \Aws\S3\RegionalEndpoint\Exception\ConfigurationException}.
|
14 |
+
*
|
15 |
+
* <code>
|
16 |
+
* use Aws\S3\RegionalEndpoint\ConfigurationProvider;
|
17 |
+
* $provider = ConfigurationProvider::defaultProvider();
|
18 |
+
* // Returns a ConfigurationInterface or throws.
|
19 |
+
* $config = $provider()->wait();
|
20 |
+
* </code>
|
21 |
+
*
|
22 |
+
* Configuration providers can be composed to create configuration using
|
23 |
+
* conditional logic that can create different configurations in different
|
24 |
+
* environments. You can compose multiple providers into a single provider using
|
25 |
+
* {@see \Aws\S3\RegionalEndpoint\ConfigurationProvider::chain}. This function
|
26 |
+
* accepts providers as variadic arguments and returns a new function that will
|
27 |
+
* invoke each provider until a successful configuration is returned.
|
28 |
+
*
|
29 |
+
* <code>
|
30 |
+
* // First try an INI file at this location.
|
31 |
+
* $a = ConfigurationProvider::ini(null, '/path/to/file.ini');
|
32 |
+
* // Then try an INI file at this location.
|
33 |
+
* $b = ConfigurationProvider::ini(null, '/path/to/other-file.ini');
|
34 |
+
* // Then try loading from environment variables.
|
35 |
+
* $c = ConfigurationProvider::env();
|
36 |
+
* // Combine the three providers together.
|
37 |
+
* $composed = ConfigurationProvider::chain($a, $b, $c);
|
38 |
+
* // Returns a promise that is fulfilled with a configuration or throws.
|
39 |
+
* $promise = $composed();
|
40 |
+
* // Wait on the configuration to resolve.
|
41 |
+
* $config = $promise->wait();
|
42 |
+
* </code>
|
43 |
+
*/
|
44 |
+
class ConfigurationProvider extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface
|
45 |
+
{
|
46 |
+
const ENV_ENDPOINTS_TYPE = 'AWS_S3_US_EAST_1_REGIONAL_ENDPOINT';
|
47 |
+
const INI_ENDPOINTS_TYPE = 's3_us_east_1_regional_endpoint';
|
48 |
+
const DEFAULT_ENDPOINTS_TYPE = 'legacy';
|
49 |
+
public static $cacheKey = 'aws_s3_us_east_1_regional_endpoint_config';
|
50 |
+
protected static $interfaceClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationInterface::class;
|
51 |
+
protected static $exceptionClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Exception\ConfigurationException::class;
|
52 |
+
/**
|
53 |
+
* Create a default config provider that first checks for environment
|
54 |
+
* variables, then checks for a specified profile in the environment-defined
|
55 |
+
* config file location (env variable is 'AWS_CONFIG_FILE', file location
|
56 |
+
* defaults to ~/.aws/config), then checks for the "default" profile in the
|
57 |
+
* environment-defined config file location, and failing those uses a default
|
58 |
+
* fallback set of configuration options.
|
59 |
+
*
|
60 |
+
* This provider is automatically wrapped in a memoize function that caches
|
61 |
+
* previously provided config options.
|
62 |
+
*
|
63 |
+
* @param array $config
|
64 |
+
*
|
65 |
+
* @return callable
|
66 |
+
*/
|
67 |
+
public static function defaultProvider(array $config = [])
|
68 |
+
{
|
69 |
+
$configProviders = [self::env(), self::ini(), self::fallback()];
|
70 |
+
$memo = self::memoize(call_user_func_array('self::chain', $configProviders));
|
71 |
+
if (isset($config['s3_us_east_1_regional_endpoint']) && $config['s3_us_east_1_regional_endpoint'] instanceof CacheInterface) {
|
72 |
+
return self::cache($memo, $config['s3_us_east_1_regional_endpoint'], self::$cacheKey);
|
73 |
+
}
|
74 |
+
return $memo;
|
75 |
+
}
|
76 |
+
public static function env()
|
77 |
+
{
|
78 |
+
return function () {
|
79 |
+
// Use config from environment variables, if available
|
80 |
+
$endpointsType = getenv(self::ENV_ENDPOINTS_TYPE);
|
81 |
+
if (!empty($endpointsType)) {
|
82 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Configuration($endpointsType));
|
83 |
+
}
|
84 |
+
return self::reject('Could not find environment variable config' . ' in ' . self::ENV_ENDPOINTS_TYPE);
|
85 |
+
};
|
86 |
+
}
|
87 |
+
/**
|
88 |
+
* Config provider that creates config using a config file whose location
|
89 |
+
* is specified by an environment variable 'AWS_CONFIG_FILE', defaulting to
|
90 |
+
* ~/.aws/config if not specified
|
91 |
+
*
|
92 |
+
* @param string|null $profile Profile to use. If not specified will use
|
93 |
+
* the "default" profile.
|
94 |
+
* @param string|null $filename If provided, uses a custom filename rather
|
95 |
+
* than looking in the default directory.
|
96 |
+
*
|
97 |
+
* @return callable
|
98 |
+
*/
|
99 |
+
public static function ini($profile = null, $filename = null)
|
100 |
+
{
|
101 |
+
$filename = $filename ?: self::getDefaultConfigFilename();
|
102 |
+
$profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
|
103 |
+
return function () use($profile, $filename) {
|
104 |
+
if (!is_readable($filename)) {
|
105 |
+
return self::reject("Cannot read configuration from {$filename}");
|
106 |
+
}
|
107 |
+
$data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($filename, true);
|
108 |
+
if ($data === false) {
|
109 |
+
return self::reject("Invalid config file: {$filename}");
|
110 |
+
}
|
111 |
+
if (!isset($data[$profile])) {
|
112 |
+
return self::reject("'{$profile}' not found in config file");
|
113 |
+
}
|
114 |
+
if (!isset($data[$profile][self::INI_ENDPOINTS_TYPE])) {
|
115 |
+
return self::reject("Required S3 regional endpoint config values \n not present in INI profile '{$profile}' ({$filename})");
|
116 |
+
}
|
117 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Configuration($data[$profile][self::INI_ENDPOINTS_TYPE]));
|
118 |
+
};
|
119 |
+
}
|
120 |
+
/**
|
121 |
+
* Fallback config options when other sources are not set.
|
122 |
+
*
|
123 |
+
* @return callable
|
124 |
+
*/
|
125 |
+
public static function fallback()
|
126 |
+
{
|
127 |
+
return function () {
|
128 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Configuration(self::DEFAULT_ENDPOINTS_TYPE));
|
129 |
+
};
|
130 |
+
}
|
131 |
+
/**
|
132 |
+
* Unwraps a configuration object in whatever valid form it is in,
|
133 |
+
* always returning a ConfigurationInterface object.
|
134 |
+
*
|
135 |
+
* @param mixed $config
|
136 |
+
* @return ConfigurationInterface
|
137 |
+
* @throws \InvalidArgumentException
|
138 |
+
*/
|
139 |
+
public static function unwrap($config)
|
140 |
+
{
|
141 |
+
if (is_callable($config)) {
|
142 |
+
$config = $config();
|
143 |
+
}
|
144 |
+
if ($config instanceof Promise\PromiseInterface) {
|
145 |
+
$config = $config->wait();
|
146 |
+
}
|
147 |
+
if ($config instanceof ConfigurationInterface) {
|
148 |
+
return $config;
|
149 |
+
}
|
150 |
+
if (is_string($config)) {
|
151 |
+
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Configuration($config);
|
152 |
+
}
|
153 |
+
if (is_array($config) && isset($config['endpoints_type'])) {
|
154 |
+
return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Configuration($config['endpoints_type']);
|
155 |
+
}
|
156 |
+
throw new \InvalidArgumentException('Not a valid S3 regional endpoint ' . 'configuration argument.');
|
157 |
+
}
|
158 |
+
}
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\Exception;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
|
7 |
+
/**
|
8 |
+
* Represents an error interacting with configuration for sts regional endpoints
|
9 |
+
*/
|
10 |
+
class ConfigurationException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface
|
11 |
+
{
|
12 |
+
use HasMonitoringEventsTrait;
|
13 |
+
}
|
@@ -6,6 +6,7 @@ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider;
|
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DocModel;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient;
|
|
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientResolver;
|
10 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Command;
|
11 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException;
|
@@ -14,7 +15,13 @@ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware;
|
|
14 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\RetryMiddleware;
|
15 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
|
16 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
|
|
|
|
|
|
|
|
|
17 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Exception\RequestException;
|
|
|
|
|
18 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
|
19 |
/**
|
20 |
* Client used to interact with **Amazon Simple Storage Service (Amazon S3)**.
|
@@ -204,7 +211,7 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
|
|
204 |
$args = parent::getArguments();
|
205 |
$args['retries']['fn'] = [__CLASS__, '_applyRetryConfig'];
|
206 |
$args['api_provider']['fn'] = [__CLASS__, '_applyApiProvider'];
|
207 |
-
return $args + ['bucket_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to a hardcoded ' . 'bucket endpoint rather than create an endpoint as a ' . 'result of injecting the bucket into the URL. This ' . 'option is useful for interacting with CNAME endpoints.'], 'use_accelerate_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 Accelerate' . ' endpoint by default. Can be enabled or disabled on' . ' individual operations by setting' . ' \'@use_accelerate_endpoint\' to true or false. Note:' . ' you must enable S3 Accelerate on a bucket before it can' . ' be accessed via an Accelerate endpoint.', 'default' => false], 'use_dual_stack_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 Dual Stack' . ' endpoint by default, which enables IPv6 Protocol.' . ' Can be enabled or disabled on individual operations by setting' . ' \'@use_dual_stack_endpoint\' to true or false.', 'default' => false], 'use_path_style_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 path style' . ' endpoint by default.' . ' Can be enabled or disabled on individual operations by setting' . ' \'@use_path_style_endpoint\' to true or false.', 'default' => false]];
|
208 |
}
|
209 |
/**
|
210 |
* {@inheritdoc}
|
@@ -219,11 +226,28 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
|
|
219 |
* interacting with CNAME endpoints.
|
220 |
* - calculate_md5: (bool) Set to false to disable calculating an MD5
|
221 |
* for all Amazon S3 signed uploads.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
* - use_accelerate_endpoint: (bool) Set to true to send requests to an S3
|
223 |
* Accelerate endpoint by default. Can be enabled or disabled on
|
224 |
* individual operations by setting '@use_accelerate_endpoint' to true or
|
225 |
* false. Note: you must enable S3 Accelerate on a bucket before it can be
|
226 |
* accessed via an Accelerate endpoint.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
* - use_dual_stack_endpoint: (bool) Set to true to send requests to an S3
|
228 |
* Dual Stack endpoint by default, which enables IPv6 Protocol.
|
229 |
* Can be enabled or disabled on individual operations by setting
|
@@ -239,6 +263,11 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
|
|
239 |
*/
|
240 |
public function __construct(array $args)
|
241 |
{
|
|
|
|
|
|
|
|
|
|
|
242 |
parent::__construct($args);
|
243 |
$stack = $this->getHandlerList();
|
244 |
$stack->appendInit(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\SSECMiddleware::wrap($this->getEndpoint()->getScheme()), 's3.ssec');
|
@@ -250,6 +279,7 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
|
|
250 |
} else {
|
251 |
$stack->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3EndpointMiddleware::wrap($this->getRegion(), ['dual_stack' => $this->getConfig('use_dual_stack_endpoint'), 'accelerate' => $this->getConfig('use_accelerate_endpoint'), 'path_style' => $this->getConfig('use_path_style_endpoint')]), 's3.endpoint_middleware');
|
252 |
}
|
|
|
253 |
$stack->appendSign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\PutObjectUrlMiddleware::wrap(), 's3.put_object_url');
|
254 |
$stack->appendSign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\PermanentRedirectMiddleware::wrap(), 's3.permanent_redirect');
|
255 |
$stack->appendInit(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::sourceFile($this->getApi()), 's3.source_file');
|
@@ -274,14 +304,45 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
|
|
274 |
$bucketLen = strlen($bucket);
|
275 |
return $bucketLen >= 3 && $bucketLen <= 63 && !filter_var($bucket, FILTER_VALIDATE_IP) && preg_match('/^[a-z0-9]([a-z0-9\\-\\.]*[a-z0-9])?$/', $bucket);
|
276 |
}
|
277 |
-
public function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
{
|
279 |
$command = clone $command;
|
280 |
$command->getHandlerList()->remove('signer');
|
281 |
/** @var \Aws\Signature\SignatureInterface $signer */
|
282 |
$signer = call_user_func($this->getSignatureProvider(), $this->getConfig('signature_version'), $this->getConfig('signing_name'), $this->getConfig('signing_region'));
|
283 |
-
return $signer->presign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\serialize($command), $this->getCredentials()->wait(), $expires);
|
284 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
285 |
public function getObjectUrl($bucket, $key)
|
286 |
{
|
287 |
$command = $this->getCommand('GetObject', ['Bucket' => $bucket, 'Key' => $key]);
|
@@ -424,7 +485,7 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
|
|
424 |
/** @internal */
|
425 |
public static function _applyApiProvider($value, array &$args, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\HandlerList $list)
|
426 |
{
|
427 |
-
\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientResolver::_apply_api_provider($value, $args
|
428 |
$args['parser'] = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\GetBucketLocationParser(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\AmbiguousSuccessParser(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RetryableMalformedResponseParser($args['parser'], $args['exception_class']), $args['error_parser'], $args['exception_class']));
|
429 |
}
|
430 |
/**
|
@@ -469,4 +530,24 @@ class S3Client extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient impl
|
|
469 |
$docs['shapes']['ContentMD5']['append'] = '<div class="alert alert-info">The value will be computed on ' . 'your behalf.</div>';
|
470 |
return [new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service($api, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::defaultProvider()), new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DocModel($docs)];
|
471 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
472 |
}
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DocModel;
|
7 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AwsClient;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
|
10 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientResolver;
|
11 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Command;
|
12 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException;
|
15 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\RetryMiddleware;
|
16 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
|
17 |
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
|
18 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Configuration;
|
19 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\ConfigurationInterface;
|
20 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\ConfigurationProvider as UseArnRegionConfigurationProvider;
|
21 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationProvider;
|
22 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Exception\RequestException;
|
23 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\Promise;
|
24 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\PromiseInterface;
|
25 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
|
26 |
/**
|
27 |
* Client used to interact with **Amazon Simple Storage Service (Amazon S3)**.
|
211 |
$args = parent::getArguments();
|
212 |
$args['retries']['fn'] = [__CLASS__, '_applyRetryConfig'];
|
213 |
$args['api_provider']['fn'] = [__CLASS__, '_applyApiProvider'];
|
214 |
+
return $args + ['bucket_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to a hardcoded ' . 'bucket endpoint rather than create an endpoint as a ' . 'result of injecting the bucket into the URL. This ' . 'option is useful for interacting with CNAME endpoints.'], 'use_arn_region' => ['type' => 'config', 'valid' => ['bool', \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Configuration::class, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface::class, 'callable'], 'doc' => 'Set to true to allow passed in ARNs to override' . ' client region. Accepts...', 'fn' => [__CLASS__, '_apply_use_arn_region'], 'default' => [\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\ConfigurationProvider::class, 'defaultProvider']], 'use_accelerate_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 Accelerate' . ' endpoint by default. Can be enabled or disabled on' . ' individual operations by setting' . ' \'@use_accelerate_endpoint\' to true or false. Note:' . ' you must enable S3 Accelerate on a bucket before it can' . ' be accessed via an Accelerate endpoint.', 'default' => false], 'use_dual_stack_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 Dual Stack' . ' endpoint by default, which enables IPv6 Protocol.' . ' Can be enabled or disabled on individual operations by setting' . ' \'@use_dual_stack_endpoint\' to true or false.', 'default' => false], 'use_path_style_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 path style' . ' endpoint by default.' . ' Can be enabled or disabled on individual operations by setting' . ' \'@use_path_style_endpoint\' to true or false.', 'default' => false]];
|
215 |
}
|
216 |
/**
|
217 |
* {@inheritdoc}
|
226 |
* interacting with CNAME endpoints.
|
227 |
* - calculate_md5: (bool) Set to false to disable calculating an MD5
|
228 |
* for all Amazon S3 signed uploads.
|
229 |
+
* - s3_us_east_1_regional_endpoint:
|
230 |
+
* (Aws\S3\RegionalEndpoint\ConfigurationInterface|Aws\CacheInterface\|callable|string|array)
|
231 |
+
* Specifies whether to use regional or legacy endpoints for the us-east-1
|
232 |
+
* region. Provide an Aws\S3\RegionalEndpoint\ConfigurationInterface object, an
|
233 |
+
* instance of Aws\CacheInterface, a callable configuration provider used
|
234 |
+
* to create endpoint configuration, a string value of `legacy` or
|
235 |
+
* `regional`, or an associative array with the following keys:
|
236 |
+
* endpoint_types: (string) Set to `legacy` or `regional`, defaults to
|
237 |
+
* `legacy`
|
238 |
* - use_accelerate_endpoint: (bool) Set to true to send requests to an S3
|
239 |
* Accelerate endpoint by default. Can be enabled or disabled on
|
240 |
* individual operations by setting '@use_accelerate_endpoint' to true or
|
241 |
* false. Note: you must enable S3 Accelerate on a bucket before it can be
|
242 |
* accessed via an Accelerate endpoint.
|
243 |
+
* - use_arn_region: (Aws\S3\UseArnRegion\ConfigurationInterface,
|
244 |
+
* Aws\CacheInterface, bool, callable) Set to true to enable the client
|
245 |
+
* to use the region from a supplied ARN argument instead of the client's
|
246 |
+
* region. Provide an instance of Aws\S3\UseArnRegion\ConfigurationInterface,
|
247 |
+
* an instance of Aws\CacheInterface, a callable that provides a promise for
|
248 |
+
* a Configuration object, or a boolean value. Defaults to false (i.e.
|
249 |
+
* the SDK will not follow the ARN region if it conflicts with the client
|
250 |
+
* region and instead throw an error).
|
251 |
* - use_dual_stack_endpoint: (bool) Set to true to send requests to an S3
|
252 |
* Dual Stack endpoint by default, which enables IPv6 Protocol.
|
253 |
* Can be enabled or disabled on individual operations by setting
|
263 |
*/
|
264 |
public function __construct(array $args)
|
265 |
{
|
266 |
+
if (!isset($args['s3_us_east_1_regional_endpoint'])) {
|
267 |
+
$args['s3_us_east_1_regional_endpoint'] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationProvider::defaultProvider();
|
268 |
+
} elseif ($args['s3_us_east_1_regional_endpoint'] instanceof CacheInterface) {
|
269 |
+
$args['s3_us_east_1_regional_endpoint'] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RegionalEndpoint\ConfigurationProvider::defaultProvider($args);
|
270 |
+
}
|
271 |
parent::__construct($args);
|
272 |
$stack = $this->getHandlerList();
|
273 |
$stack->appendInit(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\SSECMiddleware::wrap($this->getEndpoint()->getScheme()), 's3.ssec');
|
279 |
} else {
|
280 |
$stack->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3EndpointMiddleware::wrap($this->getRegion(), ['dual_stack' => $this->getConfig('use_dual_stack_endpoint'), 'accelerate' => $this->getConfig('use_accelerate_endpoint'), 'path_style' => $this->getConfig('use_path_style_endpoint')]), 's3.endpoint_middleware');
|
281 |
}
|
282 |
+
$stack->appendBuild(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\BucketEndpointArnMiddleware::wrap($this->getApi(), $this->getRegion(), ['use_arn_region' => $this->getConfig('use_arn_region'), 'dual_stack' => $this->getConfig('use_dual_stack_endpoint'), 'accelerate' => $this->getConfig('use_accelerate_endpoint'), 'path_style' => $this->getConfig('use_path_style_endpoint'), 'endpoint' => isset($args['endpoint']) ? $args['endpoint'] : null]), 's3.bucket_endpoint_arn');
|
283 |
$stack->appendSign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\PutObjectUrlMiddleware::wrap(), 's3.put_object_url');
|
284 |
$stack->appendSign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\PermanentRedirectMiddleware::wrap(), 's3.permanent_redirect');
|
285 |
$stack->appendInit(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Middleware::sourceFile($this->getApi()), 's3.source_file');
|
304 |
$bucketLen = strlen($bucket);
|
305 |
return $bucketLen >= 3 && $bucketLen <= 63 && !filter_var($bucket, FILTER_VALIDATE_IP) && preg_match('/^[a-z0-9]([a-z0-9\\-\\.]*[a-z0-9])?$/', $bucket);
|
306 |
}
|
307 |
+
public static function _apply_use_arn_region($value, array &$args, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\HandlerList $list)
|
308 |
+
{
|
309 |
+
if ($value instanceof CacheInterface) {
|
310 |
+
$value = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\ConfigurationProvider::defaultProvider($args);
|
311 |
+
}
|
312 |
+
if (is_callable($value)) {
|
313 |
+
$value = $value();
|
314 |
+
}
|
315 |
+
if ($value instanceof PromiseInterface) {
|
316 |
+
$value = $value->wait();
|
317 |
+
}
|
318 |
+
if ($value instanceof ConfigurationInterface) {
|
319 |
+
$args['use_arn_region'] = $value;
|
320 |
+
} else {
|
321 |
+
// The Configuration class itself will validate other inputs
|
322 |
+
$args['use_arn_region'] = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Configuration($value);
|
323 |
+
}
|
324 |
+
}
|
325 |
+
public function createPresignedRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, $expires, array $options = [])
|
326 |
{
|
327 |
$command = clone $command;
|
328 |
$command->getHandlerList()->remove('signer');
|
329 |
/** @var \Aws\Signature\SignatureInterface $signer */
|
330 |
$signer = call_user_func($this->getSignatureProvider(), $this->getConfig('signature_version'), $this->getConfig('signing_name'), $this->getConfig('signing_region'));
|
331 |
+
return $signer->presign(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\serialize($command), $this->getCredentials()->wait(), $expires, $options);
|
332 |
}
|
333 |
+
/**
|
334 |
+
* Returns the URL to an object identified by its bucket and key.
|
335 |
+
*
|
336 |
+
* The URL returned by this method is not signed nor does it ensure that the
|
337 |
+
* bucket and key given to the method exist. If you need a signed URL, then
|
338 |
+
* use the {@see \Aws\S3\S3Client::createPresignedRequest} method and get
|
339 |
+
* the URI of the signed request.
|
340 |
+
*
|
341 |
+
* @param string $bucket The name of the bucket where the object is located
|
342 |
+
* @param string $key The key of the object
|
343 |
+
*
|
344 |
+
* @return string The URL to the object
|
345 |
+
*/
|
346 |
public function getObjectUrl($bucket, $key)
|
347 |
{
|
348 |
$command = $this->getCommand('GetObject', ['Bucket' => $bucket, 'Key' => $key]);
|
485 |
/** @internal */
|
486 |
public static function _applyApiProvider($value, array &$args, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\HandlerList $list)
|
487 |
{
|
488 |
+
\DeliciousBrains\WP_Offload_Media\Aws3\Aws\ClientResolver::_apply_api_provider($value, $args);
|
489 |
$args['parser'] = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\GetBucketLocationParser(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\AmbiguousSuccessParser(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\RetryableMalformedResponseParser($args['parser'], $args['exception_class']), $args['error_parser'], $args['exception_class']));
|
490 |
}
|
491 |
/**
|
530 |
$docs['shapes']['ContentMD5']['append'] = '<div class="alert alert-info">The value will be computed on ' . 'your behalf.</div>';
|
531 |
return [new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service($api, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ApiProvider::defaultProvider()), new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DocModel($docs)];
|
532 |
}
|
533 |
+
/**
|
534 |
+
* @internal
|
535 |
+
* @codeCoverageIgnore
|
536 |
+
*/
|
537 |
+
public static function addDocExamples($examples)
|
538 |
+
{
|
539 |
+
$getObjectExample = ['input' => ['Bucket' => 'arn:aws:s3:us-east-1:123456789012:accesspoint:myaccesspoint', 'Key' => 'my-key'], 'output' => ['Body' => 'class GuzzleHttp\\Psr7\\Stream#208 (7) {...}', 'ContentLength' => '11', 'ContentType' => 'application/octet-stream'], 'comments' => ['input' => '', 'output' => 'Simplified example output'], 'description' => 'The following example retrieves an object by referencing the bucket via an S3 accesss point ARN. Result output is simplified for the example.', 'id' => '', 'title' => 'To get an object via an S3 access point ARN'];
|
540 |
+
if (isset($examples['GetObject'])) {
|
541 |
+
$examples['GetObject'][] = $getObjectExample;
|
542 |
+
} else {
|
543 |
+
$examples['GetObject'] = [$getObjectExample];
|
544 |
+
}
|
545 |
+
$putObjectExample = ['input' => ['Bucket' => 'arn:aws:s3:us-east-1:123456789012:accesspoint:myaccesspoint', 'Key' => 'my-key', 'Body' => 'my-body'], 'output' => ['ObjectURL' => 'https://my-bucket.s3.us-east-1.amazonaws.com/my-key'], 'comments' => ['input' => '', 'output' => 'Simplified example output'], 'description' => 'The following example uploads an object by referencing the bucket via an S3 accesss point ARN. Result output is simplified for the example.', 'id' => '', 'title' => 'To upload an object via an S3 access point ARN'];
|
546 |
+
if (isset($examples['PutObject'])) {
|
547 |
+
$examples['PutObject'][] = $putObjectExample;
|
548 |
+
} else {
|
549 |
+
$examples['PutObject'] = [$putObjectExample];
|
550 |
+
}
|
551 |
+
return $examples;
|
552 |
+
}
|
553 |
}
|
@@ -22,11 +22,11 @@ interface S3ClientInterface extends AwsClientInterface
|
|
22 |
*
|
23 |
* @return RequestInterface
|
24 |
*/
|
25 |
-
public function createPresignedRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, $expires);
|
26 |
/**
|
27 |
* Returns the URL to an object identified by its bucket and key.
|
28 |
*
|
29 |
-
* The URL returned by this method is not signed nor does it ensure
|
30 |
* bucket and key given to the method exist. If you need a signed URL, then
|
31 |
* use the {@see \Aws\S3\S3Client::createPresignedRequest} method and get
|
32 |
* the URI of the signed request.
|
22 |
*
|
23 |
* @return RequestInterface
|
24 |
*/
|
25 |
+
public function createPresignedRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, $expires, array $options = []);
|
26 |
/**
|
27 |
* Returns the URL to an object identified by its bucket and key.
|
28 |
*
|
29 |
+
* The URL returned by this method is not signed nor does it ensure that the
|
30 |
* bucket and key given to the method exist. If you need a signed URL, then
|
31 |
* use the {@see \Aws\S3\S3Client::createPresignedRequest} method and get
|
32 |
* the URI of the signed request.
|
@@ -79,7 +79,7 @@ class S3EndpointMiddleware
|
|
79 |
}
|
80 |
private static function isRequestHostStyleCompatible(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
|
81 |
{
|
82 |
-
return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3Client::isBucketDnsCompatible($command['Bucket']) && ($request->getUri()->getScheme() === 'http' || strpos($command['Bucket'], '.') === false);
|
83 |
}
|
84 |
private function endpointPatternDecider(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
|
85 |
{
|
79 |
}
|
80 |
private static function isRequestHostStyleCompatible(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
|
81 |
{
|
82 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\S3Client::isBucketDnsCompatible($command['Bucket']) && ($request->getUri()->getScheme() === 'http' || strpos($command['Bucket'], '.') === false) && filter_var($request->getUri()->getHost(), FILTER_VALIDATE_IP) === false;
|
83 |
}
|
84 |
private function endpointPatternDecider(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
|
85 |
{
|
@@ -255,7 +255,7 @@ class S3MultiRegionClient extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Mul
|
|
255 |
};
|
256 |
};
|
257 |
}
|
258 |
-
public function createPresignedRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, $expires)
|
259 |
{
|
260 |
if (empty($command['Bucket'])) {
|
261 |
throw new \InvalidArgumentException('The S3\\MultiRegionClient' . ' cannot create presigned requests for commands without a' . ' specified bucket.');
|
255 |
};
|
256 |
};
|
257 |
}
|
258 |
+
public function createPresignedRequest(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, $expires, array $options = [])
|
259 |
{
|
260 |
if (empty($command['Bucket'])) {
|
261 |
throw new \InvalidArgumentException('The S3\\MultiRegionClient' . ' cannot create presigned requests for commands without a' . ' specified bucket.');
|
@@ -2,6 +2,9 @@
|
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
|
4 |
|
|
|
|
|
|
|
5 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
|
6 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface;
|
7 |
/**
|
@@ -24,10 +27,18 @@ class S3UriParser
|
|
24 |
* @param string|UriInterface $uri
|
25 |
*
|
26 |
* @return array
|
27 |
-
* @throws \InvalidArgumentException
|
28 |
*/
|
29 |
public function parse($uri)
|
30 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
$url = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\uri_for($uri);
|
32 |
if ($url->getScheme() == $this->streamWrapperScheme) {
|
33 |
return $this->parseStreamWrapper($url);
|
@@ -44,6 +55,14 @@ class S3UriParser
|
|
44 |
$result['region'] = $matches[2] == 'amazonaws' ? null : $matches[2];
|
45 |
return $result;
|
46 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
private function parseStreamWrapper(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface $url)
|
48 |
{
|
49 |
$result = self::$defaultResult;
|
2 |
|
3 |
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3;
|
4 |
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\Exception\InvalidArnException;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser;
|
8 |
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
|
9 |
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface;
|
10 |
/**
|
27 |
* @param string|UriInterface $uri
|
28 |
*
|
29 |
* @return array
|
30 |
+
* @throws \InvalidArgumentException|InvalidArnException
|
31 |
*/
|
32 |
public function parse($uri)
|
33 |
{
|
34 |
+
// Attempt to parse host component of uri as an ARN
|
35 |
+
$components = $this->parseS3UrlComponents($uri);
|
36 |
+
if (!empty($components)) {
|
37 |
+
if (\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\ArnParser::isArn($components['host'])) {
|
38 |
+
$arn = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Arn\S3\AccessPointArn($components['host']);
|
39 |
+
return ['bucket' => $components['host'], 'key' => $components['path'], 'path_style' => false, 'region' => $arn->getRegion()];
|
40 |
+
}
|
41 |
+
}
|
42 |
$url = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\uri_for($uri);
|
43 |
if ($url->getScheme() == $this->streamWrapperScheme) {
|
44 |
return $this->parseStreamWrapper($url);
|
55 |
$result['region'] = $matches[2] == 'amazonaws' ? null : $matches[2];
|
56 |
return $result;
|
57 |
}
|
58 |
+
private function parseS3UrlComponents($uri)
|
59 |
+
{
|
60 |
+
preg_match("/^([a-zA-Z0-9]*):\\/\\/([a-zA-Z0-9:-]*)\\/(.*)/", $uri, $components);
|
61 |
+
if (empty($components)) {
|
62 |
+
return [];
|
63 |
+
}
|
64 |
+
return ['scheme' => $components[1], 'host' => $components[2], 'path' => $components[3]];
|
65 |
+
}
|
66 |
private function parseStreamWrapper(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\UriInterface $url)
|
67 |
{
|
68 |
$result = self::$defaultResult;
|
@@ -83,6 +83,8 @@ class StreamWrapper
|
|
83 |
private $cache;
|
84 |
/** @var string The opened protocol (e.g., "s3") */
|
85 |
private $protocol = 's3';
|
|
|
|
|
86 |
/**
|
87 |
* Register the 's3://' stream wrapper
|
88 |
*
|
@@ -109,24 +111,28 @@ class StreamWrapper
|
|
109 |
}
|
110 |
public function stream_close()
|
111 |
{
|
|
|
|
|
|
|
112 |
$this->body = $this->cache = null;
|
113 |
}
|
114 |
public function stream_open($path, $mode, $options, &$opened_path)
|
115 |
{
|
116 |
$this->initProtocol($path);
|
|
|
117 |
$this->params = $this->getBucketKey($path);
|
118 |
$this->mode = rtrim($mode, 'bt');
|
119 |
if ($errors = $this->validate($path, $this->mode)) {
|
120 |
return $this->triggerError($errors);
|
121 |
}
|
122 |
-
return $this->boolCall(function ()
|
123 |
switch ($this->mode) {
|
124 |
case 'r':
|
125 |
-
return $this->openReadStream(
|
126 |
case 'a':
|
127 |
-
return $this->openAppendStream(
|
128 |
default:
|
129 |
-
return $this->openWriteStream(
|
130 |
}
|
131 |
});
|
132 |
}
|
@@ -136,6 +142,7 @@ class StreamWrapper
|
|
136 |
}
|
137 |
public function stream_flush()
|
138 |
{
|
|
|
139 |
if ($this->mode == 'r') {
|
140 |
return false;
|
141 |
}
|
@@ -367,7 +374,7 @@ class StreamWrapper
|
|
367 |
*/
|
368 |
public function dir_rewinddir()
|
369 |
{
|
370 |
-
$this->boolCall(function () {
|
371 |
$this->objectIterator = null;
|
372 |
$this->dir_opendir($this->openedPath, null);
|
373 |
return true;
|
@@ -760,6 +767,6 @@ class StreamWrapper
|
|
760 |
private function getSize()
|
761 |
{
|
762 |
$size = $this->body->getSize();
|
763 |
-
return $size
|
764 |
}
|
765 |
}
|
83 |
private $cache;
|
84 |
/** @var string The opened protocol (e.g., "s3") */
|
85 |
private $protocol = 's3';
|
86 |
+
/** @var bool Keeps track of whether stream has been flushed since opening */
|
87 |
+
private $isFlushed = false;
|
88 |
/**
|
89 |
* Register the 's3://' stream wrapper
|
90 |
*
|
111 |
}
|
112 |
public function stream_close()
|
113 |
{
|
114 |
+
if ($this->body->getSize() === 0 && !$this->isFlushed) {
|
115 |
+
$this->stream_flush();
|
116 |
+
}
|
117 |
$this->body = $this->cache = null;
|
118 |
}
|
119 |
public function stream_open($path, $mode, $options, &$opened_path)
|
120 |
{
|
121 |
$this->initProtocol($path);
|
122 |
+
$this->isFlushed = false;
|
123 |
$this->params = $this->getBucketKey($path);
|
124 |
$this->mode = rtrim($mode, 'bt');
|
125 |
if ($errors = $this->validate($path, $this->mode)) {
|
126 |
return $this->triggerError($errors);
|
127 |
}
|
128 |
+
return $this->boolCall(function () {
|
129 |
switch ($this->mode) {
|
130 |
case 'r':
|
131 |
+
return $this->openReadStream();
|
132 |
case 'a':
|
133 |
+
return $this->openAppendStream();
|
134 |
default:
|
135 |
+
return $this->openWriteStream();
|
136 |
}
|
137 |
});
|
138 |
}
|
142 |
}
|
143 |
public function stream_flush()
|
144 |
{
|
145 |
+
$this->isFlushed = true;
|
146 |
if ($this->mode == 'r') {
|
147 |
return false;
|
148 |
}
|
374 |
*/
|
375 |
public function dir_rewinddir()
|
376 |
{
|
377 |
+
return $this->boolCall(function () {
|
378 |
$this->objectIterator = null;
|
379 |
$this->dir_opendir($this->openedPath, null);
|
380 |
return true;
|
767 |
private function getSize()
|
768 |
{
|
769 |
$size = $this->body->getSize();
|
770 |
+
return !empty($size) ? $size : $this->size;
|
771 |
}
|
772 |
}
|
@@ -31,7 +31,8 @@ class Transfer implements \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Prom
|
|
31 |
* the path to a directory on disk to upload, an s3 scheme URI that contains
|
32 |
* the bucket and key (e.g., "s3://bucket/key"), or an \Iterator object
|
33 |
* that yields strings containing filenames that are the path to a file on
|
34 |
-
* disk or an s3 scheme URI. The
|
|
|
35 |
*
|
36 |
* When providing an iterator for the $source argument, you must also
|
37 |
* provide a 'base_dir' key value pair in the $options argument.
|
@@ -107,7 +108,9 @@ class Transfer implements \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Prom
|
|
107 |
if ($options['debug'] === true) {
|
108 |
$options['debug'] = fopen('php://output', 'w');
|
109 |
}
|
110 |
-
|
|
|
|
|
111 |
}
|
112 |
}
|
113 |
/**
|
31 |
* the path to a directory on disk to upload, an s3 scheme URI that contains
|
32 |
* the bucket and key (e.g., "s3://bucket/key"), or an \Iterator object
|
33 |
* that yields strings containing filenames that are the path to a file on
|
34 |
+
* disk or an s3 scheme URI. The bucket portion of the s3 URI may be an S3
|
35 |
+
* access point ARN. The "/key" portion of an s3 URI is optional.
|
36 |
*
|
37 |
* When providing an iterator for the $source argument, you must also
|
38 |
* provide a 'base_dir' key value pair in the $options argument.
|
108 |
if ($options['debug'] === true) {
|
109 |
$options['debug'] = fopen('php://output', 'w');
|
110 |
}
|
111 |
+
if (is_resource($options['debug'])) {
|
112 |
+
$this->addDebugToBefore($options['debug']);
|
113 |
+
}
|
114 |
}
|
115 |
}
|
116 |
/**
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion;
|
4 |
+
|
5 |
+
use Aws;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Exception\ConfigurationException;
|
7 |
+
class Configuration implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\ConfigurationInterface
|
8 |
+
{
|
9 |
+
private $useArnRegion;
|
10 |
+
public function __construct($useArnRegion)
|
11 |
+
{
|
12 |
+
$this->useArnRegion = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\boolean_value($useArnRegion);
|
13 |
+
if (is_null($this->useArnRegion)) {
|
14 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Exception\ConfigurationException("'use_arn_region' config option" . " must be a boolean value.");
|
15 |
+
}
|
16 |
+
}
|
17 |
+
/**
|
18 |
+
* {@inheritdoc}
|
19 |
+
*/
|
20 |
+
public function isUseArnRegion()
|
21 |
+
{
|
22 |
+
return $this->useArnRegion;
|
23 |
+
}
|
24 |
+
/**
|
25 |
+
* {@inheritdoc}
|
26 |
+
*/
|
27 |
+
public function toArray()
|
28 |
+
{
|
29 |
+
return ['use_arn_region' => $this->isUseArnRegion()];
|
30 |
+
}
|
31 |
+
}
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion;
|
4 |
+
|
5 |
+
interface ConfigurationInterface
|
6 |
+
{
|
7 |
+
/**
|
8 |
+
* Returns whether or not to use the ARN region if it differs from client
|
9 |
+
*
|
10 |
+
* @return bool
|
11 |
+
*/
|
12 |
+
public function isUseArnRegion();
|
13 |
+
/**
|
14 |
+
* Returns the configuration as an associative array
|
15 |
+
*
|
16 |
+
* @return array
|
17 |
+
*/
|
18 |
+
public function toArray();
|
19 |
+
}
|
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CacheInterface;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface;
|
8 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Exception\ConfigurationException;
|
9 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
10 |
+
/**
|
11 |
+
* A configuration provider is a function that returns a promise that is
|
12 |
+
* fulfilled with a {@see \Aws\S3\UseArnRegion\ConfigurationInterface}
|
13 |
+
* or rejected with an {@see \Aws\S3\UseArnRegion\Exception\ConfigurationException}.
|
14 |
+
*
|
15 |
+
* <code>
|
16 |
+
* use Aws\S3\UseArnRegion\ConfigurationProvider;
|
17 |
+
* $provider = ConfigurationProvider::defaultProvider();
|
18 |
+
* // Returns a ConfigurationInterface or throws.
|
19 |
+
* $config = $provider()->wait();
|
20 |
+
* </code>
|
21 |
+
*
|
22 |
+
* Configuration providers can be composed to create configuration using
|
23 |
+
* conditional logic that can create different configurations in different
|
24 |
+
* environments. You can compose multiple providers into a single provider using
|
25 |
+
* {@see Aws\S3\UseArnRegion\ConfigurationProvider::chain}. This function
|
26 |
+
* accepts providers as variadic arguments and returns a new function that will
|
27 |
+
* invoke each provider until a successful configuration is returned.
|
28 |
+
*
|
29 |
+
* <code>
|
30 |
+
* // First try an INI file at this location.
|
31 |
+
* $a = ConfigurationProvider::ini(null, '/path/to/file.ini');
|
32 |
+
* // Then try an INI file at this location.
|
33 |
+
* $b = ConfigurationProvider::ini(null, '/path/to/other-file.ini');
|
34 |
+
* // Then try loading from environment variables.
|
35 |
+
* $c = ConfigurationProvider::env();
|
36 |
+
* // Combine the three providers together.
|
37 |
+
* $composed = ConfigurationProvider::chain($a, $b, $c);
|
38 |
+
* // Returns a promise that is fulfilled with a configuration or throws.
|
39 |
+
* $promise = $composed();
|
40 |
+
* // Wait on the configuration to resolve.
|
41 |
+
* $config = $promise->wait();
|
42 |
+
* </code>
|
43 |
+
*/
|
44 |
+
class ConfigurationProvider extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\AbstractConfigurationProvider implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\ConfigurationProviderInterface
|
45 |
+
{
|
46 |
+
const ENV_USE_ARN_REGION = 'AWS_S3_USE_ARN_REGION';
|
47 |
+
const INI_USE_ARN_REGION = 's3_use_arn_region';
|
48 |
+
const DEFAULT_USE_ARN_REGION = false;
|
49 |
+
public static $cacheKey = 'aws_s3_use_arn_region_config';
|
50 |
+
protected static $interfaceClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\ConfigurationInterface::class;
|
51 |
+
protected static $exceptionClass = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Exception\ConfigurationException::class;
|
52 |
+
/**
|
53 |
+
* Create a default config provider that first checks for environment
|
54 |
+
* variables, then checks for a specified profile in the environment-defined
|
55 |
+
* config file location (env variable is 'AWS_CONFIG_FILE', file location
|
56 |
+
* defaults to ~/.aws/config), then checks for the "default" profile in the
|
57 |
+
* environment-defined config file location, and failing those uses a default
|
58 |
+
* fallback set of configuration options.
|
59 |
+
*
|
60 |
+
* This provider is automatically wrapped in a memoize function that caches
|
61 |
+
* previously provided config options.
|
62 |
+
*
|
63 |
+
* @param array $config
|
64 |
+
*
|
65 |
+
* @return callable
|
66 |
+
*/
|
67 |
+
public static function defaultProvider(array $config = [])
|
68 |
+
{
|
69 |
+
$configProviders = [self::env(), self::ini(), self::fallback()];
|
70 |
+
$memo = self::memoize(call_user_func_array('self::chain', $configProviders));
|
71 |
+
if (isset($config['use_arn_region']) && $config['use_arn_region'] instanceof CacheInterface) {
|
72 |
+
return self::cache($memo, $config['use_arn_region'], self::$cacheKey);
|
73 |
+
}
|
74 |
+
return $memo;
|
75 |
+
}
|
76 |
+
/**
|
77 |
+
* Provider that creates config from environment variables.
|
78 |
+
*
|
79 |
+
* @return callable
|
80 |
+
*/
|
81 |
+
public static function env()
|
82 |
+
{
|
83 |
+
return function () {
|
84 |
+
// Use config from environment variables, if available
|
85 |
+
$useArnRegion = getenv(self::ENV_USE_ARN_REGION);
|
86 |
+
if (!empty($useArnRegion)) {
|
87 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Configuration($useArnRegion));
|
88 |
+
}
|
89 |
+
return self::reject('Could not find environment variable config' . ' in ' . self::ENV_USE_ARN_REGION);
|
90 |
+
};
|
91 |
+
}
|
92 |
+
/**
|
93 |
+
* Config provider that creates config using a config file whose location
|
94 |
+
* is specified by an environment variable 'AWS_CONFIG_FILE', defaulting to
|
95 |
+
* ~/.aws/config if not specified
|
96 |
+
*
|
97 |
+
* @param string|null $profile Profile to use. If not specified will use
|
98 |
+
* the "default" profile.
|
99 |
+
* @param string|null $filename If provided, uses a custom filename rather
|
100 |
+
* than looking in the default directory.
|
101 |
+
*
|
102 |
+
* @return callable
|
103 |
+
*/
|
104 |
+
public static function ini($profile = null, $filename = null)
|
105 |
+
{
|
106 |
+
$filename = $filename ?: self::getDefaultConfigFilename();
|
107 |
+
$profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');
|
108 |
+
return function () use($profile, $filename) {
|
109 |
+
if (!is_readable($filename)) {
|
110 |
+
return self::reject("Cannot read configuration from {$filename}");
|
111 |
+
}
|
112 |
+
// Use INI_SCANNER_NORMAL instead of INI_SCANNER_TYPED for PHP 5.5 compatibility
|
113 |
+
$data = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\parse_ini_file($filename, true, INI_SCANNER_NORMAL);
|
114 |
+
if ($data === false) {
|
115 |
+
return self::reject("Invalid config file: {$filename}");
|
116 |
+
}
|
117 |
+
if (!isset($data[$profile])) {
|
118 |
+
return self::reject("'{$profile}' not found in config file");
|
119 |
+
}
|
120 |
+
if (!isset($data[$profile][self::INI_USE_ARN_REGION])) {
|
121 |
+
return self::reject("Required S3 Use Arn Region config values \n not present in INI profile '{$profile}' ({$filename})");
|
122 |
+
}
|
123 |
+
// INI_SCANNER_NORMAL parses false-y values as an empty string
|
124 |
+
if ($data[$profile][self::INI_USE_ARN_REGION] === "") {
|
125 |
+
$data[$profile][self::INI_USE_ARN_REGION] = false;
|
126 |
+
}
|
127 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Configuration($data[$profile][self::INI_USE_ARN_REGION]));
|
128 |
+
};
|
129 |
+
}
|
130 |
+
/**
|
131 |
+
* Fallback config options when other sources are not set.
|
132 |
+
*
|
133 |
+
* @return callable
|
134 |
+
*/
|
135 |
+
public static function fallback()
|
136 |
+
{
|
137 |
+
return function () {
|
138 |
+
return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise\promise_for(new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Configuration(self::DEFAULT_USE_ARN_REGION));
|
139 |
+
};
|
140 |
+
}
|
141 |
+
}
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\UseArnRegion\Exception;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\HasMonitoringEventsTrait;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface;
|
7 |
+
/**
|
8 |
+
* Represents an error interacting with configuration for S3's UseArnRegion
|
9 |
+
*/
|
10 |
+
class ConfigurationException extends \RuntimeException implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\MonitoringEventsInterface
|
11 |
+
{
|
12 |
+
use HasMonitoringEventsTrait;
|
13 |
+
}
|
@@ -7,6 +7,8 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
7 |
*
|
8 |
* @method \Aws\ACMPCA\ACMPCAClient createACMPCA(array $args = [])
|
9 |
* @method \Aws\MultiRegionClient createMultiRegionACMPCA(array $args = [])
|
|
|
|
|
10 |
* @method \Aws\Acm\AcmClient createAcm(array $args = [])
|
11 |
* @method \Aws\MultiRegionClient createMultiRegionAcm(array $args = [])
|
12 |
* @method \Aws\AlexaForBusiness\AlexaForBusinessClient createAlexaForBusiness(array $args = [])
|
@@ -19,6 +21,8 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
19 |
* @method \Aws\MultiRegionClient createMultiRegionApiGatewayManagementApi(array $args = [])
|
20 |
* @method \Aws\ApiGatewayV2\ApiGatewayV2Client createApiGatewayV2(array $args = [])
|
21 |
* @method \Aws\MultiRegionClient createMultiRegionApiGatewayV2(array $args = [])
|
|
|
|
|
22 |
* @method \Aws\AppMesh\AppMeshClient createAppMesh(array $args = [])
|
23 |
* @method \Aws\MultiRegionClient createMultiRegionAppMesh(array $args = [])
|
24 |
* @method \Aws\AppSync\AppSyncClient createAppSync(array $args = [])
|
@@ -27,14 +31,20 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
27 |
* @method \Aws\MultiRegionClient createMultiRegionApplicationAutoScaling(array $args = [])
|
28 |
* @method \Aws\ApplicationDiscoveryService\ApplicationDiscoveryServiceClient createApplicationDiscoveryService(array $args = [])
|
29 |
* @method \Aws\MultiRegionClient createMultiRegionApplicationDiscoveryService(array $args = [])
|
|
|
|
|
30 |
* @method \Aws\Appstream\AppstreamClient createAppstream(array $args = [])
|
31 |
* @method \Aws\MultiRegionClient createMultiRegionAppstream(array $args = [])
|
32 |
* @method \Aws\Athena\AthenaClient createAthena(array $args = [])
|
33 |
* @method \Aws\MultiRegionClient createMultiRegionAthena(array $args = [])
|
|
|
|
|
34 |
* @method \Aws\AutoScaling\AutoScalingClient createAutoScaling(array $args = [])
|
35 |
* @method \Aws\MultiRegionClient createMultiRegionAutoScaling(array $args = [])
|
36 |
* @method \Aws\AutoScalingPlans\AutoScalingPlansClient createAutoScalingPlans(array $args = [])
|
37 |
* @method \Aws\MultiRegionClient createMultiRegionAutoScalingPlans(array $args = [])
|
|
|
|
|
38 |
* @method \Aws\Batch\BatchClient createBatch(array $args = [])
|
39 |
* @method \Aws\MultiRegionClient createMultiRegionBatch(array $args = [])
|
40 |
* @method \Aws\Budgets\BudgetsClient createBudgets(array $args = [])
|
@@ -71,10 +81,18 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
71 |
* @method \Aws\MultiRegionClient createMultiRegionCodeCommit(array $args = [])
|
72 |
* @method \Aws\CodeDeploy\CodeDeployClient createCodeDeploy(array $args = [])
|
73 |
* @method \Aws\MultiRegionClient createMultiRegionCodeDeploy(array $args = [])
|
|
|
|
|
|
|
|
|
74 |
* @method \Aws\CodePipeline\CodePipelineClient createCodePipeline(array $args = [])
|
75 |
* @method \Aws\MultiRegionClient createMultiRegionCodePipeline(array $args = [])
|
76 |
* @method \Aws\CodeStar\CodeStarClient createCodeStar(array $args = [])
|
77 |
* @method \Aws\MultiRegionClient createMultiRegionCodeStar(array $args = [])
|
|
|
|
|
|
|
|
|
78 |
* @method \Aws\CognitoIdentity\CognitoIdentityClient createCognitoIdentity(array $args = [])
|
79 |
* @method \Aws\MultiRegionClient createMultiRegionCognitoIdentity(array $args = [])
|
80 |
* @method \Aws\CognitoIdentityProvider\CognitoIdentityProviderClient createCognitoIdentityProvider(array $args = [])
|
@@ -85,10 +103,14 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
85 |
* @method \Aws\MultiRegionClient createMultiRegionComprehend(array $args = [])
|
86 |
* @method \Aws\ComprehendMedical\ComprehendMedicalClient createComprehendMedical(array $args = [])
|
87 |
* @method \Aws\MultiRegionClient createMultiRegionComprehendMedical(array $args = [])
|
|
|
|
|
88 |
* @method \Aws\ConfigService\ConfigServiceClient createConfigService(array $args = [])
|
89 |
* @method \Aws\MultiRegionClient createMultiRegionConfigService(array $args = [])
|
90 |
* @method \Aws\Connect\ConnectClient createConnect(array $args = [])
|
91 |
* @method \Aws\MultiRegionClient createMultiRegionConnect(array $args = [])
|
|
|
|
|
92 |
* @method \Aws\CostExplorer\CostExplorerClient createCostExplorer(array $args = [])
|
93 |
* @method \Aws\MultiRegionClient createMultiRegionCostExplorer(array $args = [])
|
94 |
* @method \Aws\CostandUsageReportService\CostandUsageReportServiceClient createCostandUsageReportService(array $args = [])
|
@@ -97,12 +119,16 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
97 |
* @method \Aws\MultiRegionClient createMultiRegionDAX(array $args = [])
|
98 |
* @method \Aws\DLM\DLMClient createDLM(array $args = [])
|
99 |
* @method \Aws\MultiRegionClient createMultiRegionDLM(array $args = [])
|
|
|
|
|
100 |
* @method \Aws\DataPipeline\DataPipelineClient createDataPipeline(array $args = [])
|
101 |
* @method \Aws\MultiRegionClient createMultiRegionDataPipeline(array $args = [])
|
102 |
* @method \Aws\DataSync\DataSyncClient createDataSync(array $args = [])
|
103 |
* @method \Aws\MultiRegionClient createMultiRegionDataSync(array $args = [])
|
104 |
* @method \Aws\DatabaseMigrationService\DatabaseMigrationServiceClient createDatabaseMigrationService(array $args = [])
|
105 |
* @method \Aws\MultiRegionClient createMultiRegionDatabaseMigrationService(array $args = [])
|
|
|
|
|
106 |
* @method \Aws\DeviceFarm\DeviceFarmClient createDeviceFarm(array $args = [])
|
107 |
* @method \Aws\MultiRegionClient createMultiRegionDeviceFarm(array $args = [])
|
108 |
* @method \Aws\DirectConnect\DirectConnectClient createDirectConnect(array $args = [])
|
@@ -115,6 +141,10 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
115 |
* @method \Aws\MultiRegionClient createMultiRegionDynamoDb(array $args = [])
|
116 |
* @method \Aws\DynamoDbStreams\DynamoDbStreamsClient createDynamoDbStreams(array $args = [])
|
117 |
* @method \Aws\MultiRegionClient createMultiRegionDynamoDbStreams(array $args = [])
|
|
|
|
|
|
|
|
|
118 |
* @method \Aws\EKS\EKSClient createEKS(array $args = [])
|
119 |
* @method \Aws\MultiRegionClient createMultiRegionEKS(array $args = [])
|
120 |
* @method \Aws\Ec2\Ec2Client createEc2(array $args = [])
|
@@ -129,6 +159,8 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
129 |
* @method \Aws\MultiRegionClient createMultiRegionElastiCache(array $args = [])
|
130 |
* @method \Aws\ElasticBeanstalk\ElasticBeanstalkClient createElasticBeanstalk(array $args = [])
|
131 |
* @method \Aws\MultiRegionClient createMultiRegionElasticBeanstalk(array $args = [])
|
|
|
|
|
132 |
* @method \Aws\ElasticLoadBalancing\ElasticLoadBalancingClient createElasticLoadBalancing(array $args = [])
|
133 |
* @method \Aws\MultiRegionClient createMultiRegionElasticLoadBalancing(array $args = [])
|
134 |
* @method \Aws\ElasticLoadBalancingV2\ElasticLoadBalancingV2Client createElasticLoadBalancingV2(array $args = [])
|
@@ -139,12 +171,20 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
139 |
* @method \Aws\MultiRegionClient createMultiRegionElasticsearchService(array $args = [])
|
140 |
* @method \Aws\Emr\EmrClient createEmr(array $args = [])
|
141 |
* @method \Aws\MultiRegionClient createMultiRegionEmr(array $args = [])
|
|
|
|
|
142 |
* @method \Aws\FMS\FMSClient createFMS(array $args = [])
|
143 |
* @method \Aws\MultiRegionClient createMultiRegionFMS(array $args = [])
|
144 |
* @method \Aws\FSx\FSxClient createFSx(array $args = [])
|
145 |
* @method \Aws\MultiRegionClient createMultiRegionFSx(array $args = [])
|
146 |
* @method \Aws\Firehose\FirehoseClient createFirehose(array $args = [])
|
147 |
* @method \Aws\MultiRegionClient createMultiRegionFirehose(array $args = [])
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
* @method \Aws\GameLift\GameLiftClient createGameLift(array $args = [])
|
149 |
* @method \Aws\MultiRegionClient createMultiRegionGameLift(array $args = [])
|
150 |
* @method \Aws\Glacier\GlacierClient createGlacier(array $args = [])
|
@@ -155,6 +195,8 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
155 |
* @method \Aws\MultiRegionClient createMultiRegionGlue(array $args = [])
|
156 |
* @method \Aws\Greengrass\GreengrassClient createGreengrass(array $args = [])
|
157 |
* @method \Aws\MultiRegionClient createMultiRegionGreengrass(array $args = [])
|
|
|
|
|
158 |
* @method \Aws\GuardDuty\GuardDutyClient createGuardDuty(array $args = [])
|
159 |
* @method \Aws\MultiRegionClient createMultiRegionGuardDuty(array $args = [])
|
160 |
* @method \Aws\Health\HealthClient createHealth(array $args = [])
|
@@ -171,8 +213,16 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
171 |
* @method \Aws\MultiRegionClient createMultiRegionIoT1ClickProjects(array $args = [])
|
172 |
* @method \Aws\IoTAnalytics\IoTAnalyticsClient createIoTAnalytics(array $args = [])
|
173 |
* @method \Aws\MultiRegionClient createMultiRegionIoTAnalytics(array $args = [])
|
|
|
|
|
|
|
|
|
174 |
* @method \Aws\IoTJobsDataPlane\IoTJobsDataPlaneClient createIoTJobsDataPlane(array $args = [])
|
175 |
* @method \Aws\MultiRegionClient createMultiRegionIoTJobsDataPlane(array $args = [])
|
|
|
|
|
|
|
|
|
176 |
* @method \Aws\Iot\IotClient createIot(array $args = [])
|
177 |
* @method \Aws\MultiRegionClient createMultiRegionIot(array $args = [])
|
178 |
* @method \Aws\IotDataPlane\IotDataPlaneClient createIotDataPlane(array $args = [])
|
@@ -191,8 +241,12 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
191 |
* @method \Aws\MultiRegionClient createMultiRegionKinesisVideoArchivedMedia(array $args = [])
|
192 |
* @method \Aws\KinesisVideoMedia\KinesisVideoMediaClient createKinesisVideoMedia(array $args = [])
|
193 |
* @method \Aws\MultiRegionClient createMultiRegionKinesisVideoMedia(array $args = [])
|
|
|
|
|
194 |
* @method \Aws\Kms\KmsClient createKms(array $args = [])
|
195 |
* @method \Aws\MultiRegionClient createMultiRegionKms(array $args = [])
|
|
|
|
|
196 |
* @method \Aws\Lambda\LambdaClient createLambda(array $args = [])
|
197 |
* @method \Aws\MultiRegionClient createMultiRegionLambda(array $args = [])
|
198 |
* @method \Aws\LexModelBuildingService\LexModelBuildingServiceClient createLexModelBuildingService(array $args = [])
|
@@ -211,6 +265,10 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
211 |
* @method \Aws\MultiRegionClient createMultiRegionMachineLearning(array $args = [])
|
212 |
* @method \Aws\Macie\MacieClient createMacie(array $args = [])
|
213 |
* @method \Aws\MultiRegionClient createMultiRegionMacie(array $args = [])
|
|
|
|
|
|
|
|
|
214 |
* @method \Aws\MarketplaceCommerceAnalytics\MarketplaceCommerceAnalyticsClient createMarketplaceCommerceAnalytics(array $args = [])
|
215 |
* @method \Aws\MultiRegionClient createMultiRegionMarketplaceCommerceAnalytics(array $args = [])
|
216 |
* @method \Aws\MarketplaceEntitlementService\MarketplaceEntitlementServiceClient createMarketplaceEntitlementService(array $args = [])
|
@@ -225,6 +283,8 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
225 |
* @method \Aws\MultiRegionClient createMultiRegionMediaLive(array $args = [])
|
226 |
* @method \Aws\MediaPackage\MediaPackageClient createMediaPackage(array $args = [])
|
227 |
* @method \Aws\MultiRegionClient createMultiRegionMediaPackage(array $args = [])
|
|
|
|
|
228 |
* @method \Aws\MediaStore\MediaStoreClient createMediaStore(array $args = [])
|
229 |
* @method \Aws\MultiRegionClient createMultiRegionMediaStore(array $args = [])
|
230 |
* @method \Aws\MediaStoreData\MediaStoreDataClient createMediaStoreData(array $args = [])
|
@@ -233,18 +293,30 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
233 |
* @method \Aws\MultiRegionClient createMultiRegionMediaTailor(array $args = [])
|
234 |
* @method \Aws\MigrationHub\MigrationHubClient createMigrationHub(array $args = [])
|
235 |
* @method \Aws\MultiRegionClient createMultiRegionMigrationHub(array $args = [])
|
|
|
|
|
236 |
* @method \Aws\Mobile\MobileClient createMobile(array $args = [])
|
237 |
* @method \Aws\MultiRegionClient createMultiRegionMobile(array $args = [])
|
238 |
* @method \Aws\Neptune\NeptuneClient createNeptune(array $args = [])
|
239 |
* @method \Aws\MultiRegionClient createMultiRegionNeptune(array $args = [])
|
|
|
|
|
240 |
* @method \Aws\OpsWorks\OpsWorksClient createOpsWorks(array $args = [])
|
241 |
* @method \Aws\MultiRegionClient createMultiRegionOpsWorks(array $args = [])
|
242 |
* @method \Aws\OpsWorksCM\OpsWorksCMClient createOpsWorksCM(array $args = [])
|
243 |
* @method \Aws\MultiRegionClient createMultiRegionOpsWorksCM(array $args = [])
|
244 |
* @method \Aws\Organizations\OrganizationsClient createOrganizations(array $args = [])
|
245 |
* @method \Aws\MultiRegionClient createMultiRegionOrganizations(array $args = [])
|
|
|
|
|
246 |
* @method \Aws\PI\PIClient createPI(array $args = [])
|
247 |
* @method \Aws\MultiRegionClient createMultiRegionPI(array $args = [])
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
* @method \Aws\Pinpoint\PinpointClient createPinpoint(array $args = [])
|
249 |
* @method \Aws\MultiRegionClient createMultiRegionPinpoint(array $args = [])
|
250 |
* @method \Aws\PinpointEmail\PinpointEmailClient createPinpointEmail(array $args = [])
|
@@ -255,6 +327,10 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
255 |
* @method \Aws\MultiRegionClient createMultiRegionPolly(array $args = [])
|
256 |
* @method \Aws\Pricing\PricingClient createPricing(array $args = [])
|
257 |
* @method \Aws\MultiRegionClient createMultiRegionPricing(array $args = [])
|
|
|
|
|
|
|
|
|
258 |
* @method \Aws\QuickSight\QuickSightClient createQuickSight(array $args = [])
|
259 |
* @method \Aws\MultiRegionClient createMultiRegionQuickSight(array $args = [])
|
260 |
* @method \Aws\RAM\RAMClient createRAM(array $args = [])
|
@@ -283,10 +359,18 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
283 |
* @method \Aws\S3\S3MultiRegionClient createMultiRegionS3(array $args = [])
|
284 |
* @method \Aws\S3Control\S3ControlClient createS3Control(array $args = [])
|
285 |
* @method \Aws\MultiRegionClient createMultiRegionS3Control(array $args = [])
|
|
|
|
|
|
|
|
|
286 |
* @method \Aws\SageMaker\SageMakerClient createSageMaker(array $args = [])
|
287 |
* @method \Aws\MultiRegionClient createMultiRegionSageMaker(array $args = [])
|
288 |
* @method \Aws\SageMakerRuntime\SageMakerRuntimeClient createSageMakerRuntime(array $args = [])
|
289 |
* @method \Aws\MultiRegionClient createMultiRegionSageMakerRuntime(array $args = [])
|
|
|
|
|
|
|
|
|
290 |
* @method \Aws\SecretsManager\SecretsManagerClient createSecretsManager(array $args = [])
|
291 |
* @method \Aws\MultiRegionClient createMultiRegionSecretsManager(array $args = [])
|
292 |
* @method \Aws\SecurityHub\SecurityHubClient createSecurityHub(array $args = [])
|
@@ -297,8 +381,12 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
297 |
* @method \Aws\MultiRegionClient createMultiRegionServiceCatalog(array $args = [])
|
298 |
* @method \Aws\ServiceDiscovery\ServiceDiscoveryClient createServiceDiscovery(array $args = [])
|
299 |
* @method \Aws\MultiRegionClient createMultiRegionServiceDiscovery(array $args = [])
|
|
|
|
|
300 |
* @method \Aws\Ses\SesClient createSes(array $args = [])
|
301 |
* @method \Aws\MultiRegionClient createMultiRegionSes(array $args = [])
|
|
|
|
|
302 |
* @method \Aws\Sfn\SfnClient createSfn(array $args = [])
|
303 |
* @method \Aws\MultiRegionClient createMultiRegionSfn(array $args = [])
|
304 |
* @method \Aws\Shield\ShieldClient createShield(array $args = [])
|
@@ -321,30 +409,42 @@ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
|
321 |
* @method \Aws\MultiRegionClient createMultiRegionSupport(array $args = [])
|
322 |
* @method \Aws\Swf\SwfClient createSwf(array $args = [])
|
323 |
* @method \Aws\MultiRegionClient createMultiRegionSwf(array $args = [])
|
|
|
|
|
324 |
* @method \Aws\TranscribeService\TranscribeServiceClient createTranscribeService(array $args = [])
|
325 |
* @method \Aws\MultiRegionClient createMultiRegionTranscribeService(array $args = [])
|
326 |
* @method \Aws\Transfer\TransferClient createTransfer(array $args = [])
|
327 |
* @method \Aws\MultiRegionClient createMultiRegionTransfer(array $args = [])
|
328 |
* @method \Aws\Translate\TranslateClient createTranslate(array $args = [])
|
329 |
* @method \Aws\MultiRegionClient createMultiRegionTranslate(array $args = [])
|
|
|
|
|
330 |
* @method \Aws\Waf\WafClient createWaf(array $args = [])
|
331 |
* @method \Aws\MultiRegionClient createMultiRegionWaf(array $args = [])
|
332 |
* @method \Aws\WafRegional\WafRegionalClient createWafRegional(array $args = [])
|
333 |
* @method \Aws\MultiRegionClient createMultiRegionWafRegional(array $args = [])
|
334 |
* @method \Aws\WorkDocs\WorkDocsClient createWorkDocs(array $args = [])
|
335 |
* @method \Aws\MultiRegionClient createMultiRegionWorkDocs(array $args = [])
|
|
|
|
|
336 |
* @method \Aws\WorkMail\WorkMailClient createWorkMail(array $args = [])
|
337 |
* @method \Aws\MultiRegionClient createMultiRegionWorkMail(array $args = [])
|
|
|
|
|
338 |
* @method \Aws\WorkSpaces\WorkSpacesClient createWorkSpaces(array $args = [])
|
339 |
* @method \Aws\MultiRegionClient createMultiRegionWorkSpaces(array $args = [])
|
340 |
* @method \Aws\XRay\XRayClient createXRay(array $args = [])
|
341 |
* @method \Aws\MultiRegionClient createMultiRegionXRay(array $args = [])
|
|
|
|
|
|
|
|
|
342 |
* @method \Aws\signer\signerClient createsigner(array $args = [])
|
343 |
* @method \Aws\MultiRegionClient createMultiRegionsigner(array $args = [])
|
344 |
*/
|
345 |
class Sdk
|
346 |
{
|
347 |
-
const VERSION = '3.
|
348 |
/** @var array Arguments for creating clients */
|
349 |
private $args;
|
350 |
/**
|
@@ -403,6 +503,18 @@ class Sdk
|
|
403 |
$klass = class_exists($klass) ? $klass : 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\MultiRegionClient';
|
404 |
return new $klass($this->mergeArgs($namespace, $service, $args));
|
405 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
406 |
private function mergeArgs($namespace, array $manifest, array $args = [])
|
407 |
{
|
408 |
// Merge provided args with stored, service-specific args.
|
7 |
*
|
8 |
* @method \Aws\ACMPCA\ACMPCAClient createACMPCA(array $args = [])
|
9 |
* @method \Aws\MultiRegionClient createMultiRegionACMPCA(array $args = [])
|
10 |
+
* @method \Aws\AccessAnalyzer\AccessAnalyzerClient createAccessAnalyzer(array $args = [])
|
11 |
+
* @method \Aws\MultiRegionClient createMultiRegionAccessAnalyzer(array $args = [])
|
12 |
* @method \Aws\Acm\AcmClient createAcm(array $args = [])
|
13 |
* @method \Aws\MultiRegionClient createMultiRegionAcm(array $args = [])
|
14 |
* @method \Aws\AlexaForBusiness\AlexaForBusinessClient createAlexaForBusiness(array $args = [])
|
21 |
* @method \Aws\MultiRegionClient createMultiRegionApiGatewayManagementApi(array $args = [])
|
22 |
* @method \Aws\ApiGatewayV2\ApiGatewayV2Client createApiGatewayV2(array $args = [])
|
23 |
* @method \Aws\MultiRegionClient createMultiRegionApiGatewayV2(array $args = [])
|
24 |
+
* @method \Aws\AppConfig\AppConfigClient createAppConfig(array $args = [])
|
25 |
+
* @method \Aws\MultiRegionClient createMultiRegionAppConfig(array $args = [])
|
26 |
* @method \Aws\AppMesh\AppMeshClient createAppMesh(array $args = [])
|
27 |
* @method \Aws\MultiRegionClient createMultiRegionAppMesh(array $args = [])
|
28 |
* @method \Aws\AppSync\AppSyncClient createAppSync(array $args = [])
|
31 |
* @method \Aws\MultiRegionClient createMultiRegionApplicationAutoScaling(array $args = [])
|
32 |
* @method \Aws\ApplicationDiscoveryService\ApplicationDiscoveryServiceClient createApplicationDiscoveryService(array $args = [])
|
33 |
* @method \Aws\MultiRegionClient createMultiRegionApplicationDiscoveryService(array $args = [])
|
34 |
+
* @method \Aws\ApplicationInsights\ApplicationInsightsClient createApplicationInsights(array $args = [])
|
35 |
+
* @method \Aws\MultiRegionClient createMultiRegionApplicationInsights(array $args = [])
|
36 |
* @method \Aws\Appstream\AppstreamClient createAppstream(array $args = [])
|
37 |
* @method \Aws\MultiRegionClient createMultiRegionAppstream(array $args = [])
|
38 |
* @method \Aws\Athena\AthenaClient createAthena(array $args = [])
|
39 |
* @method \Aws\MultiRegionClient createMultiRegionAthena(array $args = [])
|
40 |
+
* @method \Aws\AugmentedAIRuntime\AugmentedAIRuntimeClient createAugmentedAIRuntime(array $args = [])
|
41 |
+
* @method \Aws\MultiRegionClient createMultiRegionAugmentedAIRuntime(array $args = [])
|
42 |
* @method \Aws\AutoScaling\AutoScalingClient createAutoScaling(array $args = [])
|
43 |
* @method \Aws\MultiRegionClient createMultiRegionAutoScaling(array $args = [])
|
44 |
* @method \Aws\AutoScalingPlans\AutoScalingPlansClient createAutoScalingPlans(array $args = [])
|
45 |
* @method \Aws\MultiRegionClient createMultiRegionAutoScalingPlans(array $args = [])
|
46 |
+
* @method \Aws\Backup\BackupClient createBackup(array $args = [])
|
47 |
+
* @method \Aws\MultiRegionClient createMultiRegionBackup(array $args = [])
|
48 |
* @method \Aws\Batch\BatchClient createBatch(array $args = [])
|
49 |
* @method \Aws\MultiRegionClient createMultiRegionBatch(array $args = [])
|
50 |
* @method \Aws\Budgets\BudgetsClient createBudgets(array $args = [])
|
81 |
* @method \Aws\MultiRegionClient createMultiRegionCodeCommit(array $args = [])
|
82 |
* @method \Aws\CodeDeploy\CodeDeployClient createCodeDeploy(array $args = [])
|
83 |
* @method \Aws\MultiRegionClient createMultiRegionCodeDeploy(array $args = [])
|
84 |
+
* @method \Aws\CodeGuruProfiler\CodeGuruProfilerClient createCodeGuruProfiler(array $args = [])
|
85 |
+
* @method \Aws\MultiRegionClient createMultiRegionCodeGuruProfiler(array $args = [])
|
86 |
+
* @method \Aws\CodeGuruReviewer\CodeGuruReviewerClient createCodeGuruReviewer(array $args = [])
|
87 |
+
* @method \Aws\MultiRegionClient createMultiRegionCodeGuruReviewer(array $args = [])
|
88 |
* @method \Aws\CodePipeline\CodePipelineClient createCodePipeline(array $args = [])
|
89 |
* @method \Aws\MultiRegionClient createMultiRegionCodePipeline(array $args = [])
|
90 |
* @method \Aws\CodeStar\CodeStarClient createCodeStar(array $args = [])
|
91 |
* @method \Aws\MultiRegionClient createMultiRegionCodeStar(array $args = [])
|
92 |
+
* @method \Aws\CodeStarNotifications\CodeStarNotificationsClient createCodeStarNotifications(array $args = [])
|
93 |
+
* @method \Aws\MultiRegionClient createMultiRegionCodeStarNotifications(array $args = [])
|
94 |
+
* @method \Aws\CodeStarconnections\CodeStarconnectionsClient createCodeStarconnections(array $args = [])
|
95 |
+
* @method \Aws\MultiRegionClient createMultiRegionCodeStarconnections(array $args = [])
|
96 |
* @method \Aws\CognitoIdentity\CognitoIdentityClient createCognitoIdentity(array $args = [])
|
97 |
* @method \Aws\MultiRegionClient createMultiRegionCognitoIdentity(array $args = [])
|
98 |
* @method \Aws\CognitoIdentityProvider\CognitoIdentityProviderClient createCognitoIdentityProvider(array $args = [])
|
103 |
* @method \Aws\MultiRegionClient createMultiRegionComprehend(array $args = [])
|
104 |
* @method \Aws\ComprehendMedical\ComprehendMedicalClient createComprehendMedical(array $args = [])
|
105 |
* @method \Aws\MultiRegionClient createMultiRegionComprehendMedical(array $args = [])
|
106 |
+
* @method \Aws\ComputeOptimizer\ComputeOptimizerClient createComputeOptimizer(array $args = [])
|
107 |
+
* @method \Aws\MultiRegionClient createMultiRegionComputeOptimizer(array $args = [])
|
108 |
* @method \Aws\ConfigService\ConfigServiceClient createConfigService(array $args = [])
|
109 |
* @method \Aws\MultiRegionClient createMultiRegionConfigService(array $args = [])
|
110 |
* @method \Aws\Connect\ConnectClient createConnect(array $args = [])
|
111 |
* @method \Aws\MultiRegionClient createMultiRegionConnect(array $args = [])
|
112 |
+
* @method \Aws\ConnectParticipant\ConnectParticipantClient createConnectParticipant(array $args = [])
|
113 |
+
* @method \Aws\MultiRegionClient createMultiRegionConnectParticipant(array $args = [])
|
114 |
* @method \Aws\CostExplorer\CostExplorerClient createCostExplorer(array $args = [])
|
115 |
* @method \Aws\MultiRegionClient createMultiRegionCostExplorer(array $args = [])
|
116 |
* @method \Aws\CostandUsageReportService\CostandUsageReportServiceClient createCostandUsageReportService(array $args = [])
|
119 |
* @method \Aws\MultiRegionClient createMultiRegionDAX(array $args = [])
|
120 |
* @method \Aws\DLM\DLMClient createDLM(array $args = [])
|
121 |
* @method \Aws\MultiRegionClient createMultiRegionDLM(array $args = [])
|
122 |
+
* @method \Aws\DataExchange\DataExchangeClient createDataExchange(array $args = [])
|
123 |
+
* @method \Aws\MultiRegionClient createMultiRegionDataExchange(array $args = [])
|
124 |
* @method \Aws\DataPipeline\DataPipelineClient createDataPipeline(array $args = [])
|
125 |
* @method \Aws\MultiRegionClient createMultiRegionDataPipeline(array $args = [])
|
126 |
* @method \Aws\DataSync\DataSyncClient createDataSync(array $args = [])
|
127 |
* @method \Aws\MultiRegionClient createMultiRegionDataSync(array $args = [])
|
128 |
* @method \Aws\DatabaseMigrationService\DatabaseMigrationServiceClient createDatabaseMigrationService(array $args = [])
|
129 |
* @method \Aws\MultiRegionClient createMultiRegionDatabaseMigrationService(array $args = [])
|
130 |
+
* @method \Aws\Detective\DetectiveClient createDetective(array $args = [])
|
131 |
+
* @method \Aws\MultiRegionClient createMultiRegionDetective(array $args = [])
|
132 |
* @method \Aws\DeviceFarm\DeviceFarmClient createDeviceFarm(array $args = [])
|
133 |
* @method \Aws\MultiRegionClient createMultiRegionDeviceFarm(array $args = [])
|
134 |
* @method \Aws\DirectConnect\DirectConnectClient createDirectConnect(array $args = [])
|
141 |
* @method \Aws\MultiRegionClient createMultiRegionDynamoDb(array $args = [])
|
142 |
* @method \Aws\DynamoDbStreams\DynamoDbStreamsClient createDynamoDbStreams(array $args = [])
|
143 |
* @method \Aws\MultiRegionClient createMultiRegionDynamoDbStreams(array $args = [])
|
144 |
+
* @method \Aws\EBS\EBSClient createEBS(array $args = [])
|
145 |
+
* @method \Aws\MultiRegionClient createMultiRegionEBS(array $args = [])
|
146 |
+
* @method \Aws\EC2InstanceConnect\EC2InstanceConnectClient createEC2InstanceConnect(array $args = [])
|
147 |
+
* @method \Aws\MultiRegionClient createMultiRegionEC2InstanceConnect(array $args = [])
|
148 |
* @method \Aws\EKS\EKSClient createEKS(array $args = [])
|
149 |
* @method \Aws\MultiRegionClient createMultiRegionEKS(array $args = [])
|
150 |
* @method \Aws\Ec2\Ec2Client createEc2(array $args = [])
|
159 |
* @method \Aws\MultiRegionClient createMultiRegionElastiCache(array $args = [])
|
160 |
* @method \Aws\ElasticBeanstalk\ElasticBeanstalkClient createElasticBeanstalk(array $args = [])
|
161 |
* @method \Aws\MultiRegionClient createMultiRegionElasticBeanstalk(array $args = [])
|
162 |
+
* @method \Aws\ElasticInference\ElasticInferenceClient createElasticInference(array $args = [])
|
163 |
+
* @method \Aws\MultiRegionClient createMultiRegionElasticInference(array $args = [])
|
164 |
* @method \Aws\ElasticLoadBalancing\ElasticLoadBalancingClient createElasticLoadBalancing(array $args = [])
|
165 |
* @method \Aws\MultiRegionClient createMultiRegionElasticLoadBalancing(array $args = [])
|
166 |
* @method \Aws\ElasticLoadBalancingV2\ElasticLoadBalancingV2Client createElasticLoadBalancingV2(array $args = [])
|
171 |
* @method \Aws\MultiRegionClient createMultiRegionElasticsearchService(array $args = [])
|
172 |
* @method \Aws\Emr\EmrClient createEmr(array $args = [])
|
173 |
* @method \Aws\MultiRegionClient createMultiRegionEmr(array $args = [])
|
174 |
+
* @method \Aws\EventBridge\EventBridgeClient createEventBridge(array $args = [])
|
175 |
+
* @method \Aws\MultiRegionClient createMultiRegionEventBridge(array $args = [])
|
176 |
* @method \Aws\FMS\FMSClient createFMS(array $args = [])
|
177 |
* @method \Aws\MultiRegionClient createMultiRegionFMS(array $args = [])
|
178 |
* @method \Aws\FSx\FSxClient createFSx(array $args = [])
|
179 |
* @method \Aws\MultiRegionClient createMultiRegionFSx(array $args = [])
|
180 |
* @method \Aws\Firehose\FirehoseClient createFirehose(array $args = [])
|
181 |
* @method \Aws\MultiRegionClient createMultiRegionFirehose(array $args = [])
|
182 |
+
* @method \Aws\ForecastQueryService\ForecastQueryServiceClient createForecastQueryService(array $args = [])
|
183 |
+
* @method \Aws\MultiRegionClient createMultiRegionForecastQueryService(array $args = [])
|
184 |
+
* @method \Aws\ForecastService\ForecastServiceClient createForecastService(array $args = [])
|
185 |
+
* @method \Aws\MultiRegionClient createMultiRegionForecastService(array $args = [])
|
186 |
+
* @method \Aws\FraudDetector\FraudDetectorClient createFraudDetector(array $args = [])
|
187 |
+
* @method \Aws\MultiRegionClient createMultiRegionFraudDetector(array $args = [])
|
188 |
* @method \Aws\GameLift\GameLiftClient createGameLift(array $args = [])
|
189 |
* @method \Aws\MultiRegionClient createMultiRegionGameLift(array $args = [])
|
190 |
* @method \Aws\Glacier\GlacierClient createGlacier(array $args = [])
|
195 |
* @method \Aws\MultiRegionClient createMultiRegionGlue(array $args = [])
|
196 |
* @method \Aws\Greengrass\GreengrassClient createGreengrass(array $args = [])
|
197 |
* @method \Aws\MultiRegionClient createMultiRegionGreengrass(array $args = [])
|
198 |
+
* @method \Aws\GroundStation\GroundStationClient createGroundStation(array $args = [])
|
199 |
+
* @method \Aws\MultiRegionClient createMultiRegionGroundStation(array $args = [])
|
200 |
* @method \Aws\GuardDuty\GuardDutyClient createGuardDuty(array $args = [])
|
201 |
* @method \Aws\MultiRegionClient createMultiRegionGuardDuty(array $args = [])
|
202 |
* @method \Aws\Health\HealthClient createHealth(array $args = [])
|
213 |
* @method \Aws\MultiRegionClient createMultiRegionIoT1ClickProjects(array $args = [])
|
214 |
* @method \Aws\IoTAnalytics\IoTAnalyticsClient createIoTAnalytics(array $args = [])
|
215 |
* @method \Aws\MultiRegionClient createMultiRegionIoTAnalytics(array $args = [])
|
216 |
+
* @method \Aws\IoTEvents\IoTEventsClient createIoTEvents(array $args = [])
|
217 |
+
* @method \Aws\MultiRegionClient createMultiRegionIoTEvents(array $args = [])
|
218 |
+
* @method \Aws\IoTEventsData\IoTEventsDataClient createIoTEventsData(array $args = [])
|
219 |
+
* @method \Aws\MultiRegionClient createMultiRegionIoTEventsData(array $args = [])
|
220 |
* @method \Aws\IoTJobsDataPlane\IoTJobsDataPlaneClient createIoTJobsDataPlane(array $args = [])
|
221 |
* @method \Aws\MultiRegionClient createMultiRegionIoTJobsDataPlane(array $args = [])
|
222 |
+
* @method \Aws\IoTSecureTunneling\IoTSecureTunnelingClient createIoTSecureTunneling(array $args = [])
|
223 |
+
* @method \Aws\MultiRegionClient createMultiRegionIoTSecureTunneling(array $args = [])
|
224 |
+
* @method \Aws\IoTThingsGraph\IoTThingsGraphClient createIoTThingsGraph(array $args = [])
|
225 |
+
* @method \Aws\MultiRegionClient createMultiRegionIoTThingsGraph(array $args = [])
|
226 |
* @method \Aws\Iot\IotClient createIot(array $args = [])
|
227 |
* @method \Aws\MultiRegionClient createMultiRegionIot(array $args = [])
|
228 |
* @method \Aws\IotDataPlane\IotDataPlaneClient createIotDataPlane(array $args = [])
|
241 |
* @method \Aws\MultiRegionClient createMultiRegionKinesisVideoArchivedMedia(array $args = [])
|
242 |
* @method \Aws\KinesisVideoMedia\KinesisVideoMediaClient createKinesisVideoMedia(array $args = [])
|
243 |
* @method \Aws\MultiRegionClient createMultiRegionKinesisVideoMedia(array $args = [])
|
244 |
+
* @method \Aws\KinesisVideoSignalingChannels\KinesisVideoSignalingChannelsClient createKinesisVideoSignalingChannels(array $args = [])
|
245 |
+
* @method \Aws\MultiRegionClient createMultiRegionKinesisVideoSignalingChannels(array $args = [])
|
246 |
* @method \Aws\Kms\KmsClient createKms(array $args = [])
|
247 |
* @method \Aws\MultiRegionClient createMultiRegionKms(array $args = [])
|
248 |
+
* @method \Aws\LakeFormation\LakeFormationClient createLakeFormation(array $args = [])
|
249 |
+
* @method \Aws\MultiRegionClient createMultiRegionLakeFormation(array $args = [])
|
250 |
* @method \Aws\Lambda\LambdaClient createLambda(array $args = [])
|
251 |
* @method \Aws\MultiRegionClient createMultiRegionLambda(array $args = [])
|
252 |
* @method \Aws\LexModelBuildingService\LexModelBuildingServiceClient createLexModelBuildingService(array $args = [])
|
265 |
* @method \Aws\MultiRegionClient createMultiRegionMachineLearning(array $args = [])
|
266 |
* @method \Aws\Macie\MacieClient createMacie(array $args = [])
|
267 |
* @method \Aws\MultiRegionClient createMultiRegionMacie(array $args = [])
|
268 |
+
* @method \Aws\ManagedBlockchain\ManagedBlockchainClient createManagedBlockchain(array $args = [])
|
269 |
+
* @method \Aws\MultiRegionClient createMultiRegionManagedBlockchain(array $args = [])
|
270 |
+
* @method \Aws\MarketplaceCatalog\MarketplaceCatalogClient createMarketplaceCatalog(array $args = [])
|
271 |
+
* @method \Aws\MultiRegionClient createMultiRegionMarketplaceCatalog(array $args = [])
|
272 |
* @method \Aws\MarketplaceCommerceAnalytics\MarketplaceCommerceAnalyticsClient createMarketplaceCommerceAnalytics(array $args = [])
|
273 |
* @method \Aws\MultiRegionClient createMultiRegionMarketplaceCommerceAnalytics(array $args = [])
|
274 |
* @method \Aws\MarketplaceEntitlementService\MarketplaceEntitlementServiceClient createMarketplaceEntitlementService(array $args = [])
|
283 |
* @method \Aws\MultiRegionClient createMultiRegionMediaLive(array $args = [])
|
284 |
* @method \Aws\MediaPackage\MediaPackageClient createMediaPackage(array $args = [])
|
285 |
* @method \Aws\MultiRegionClient createMultiRegionMediaPackage(array $args = [])
|
286 |
+
* @method \Aws\MediaPackageVod\MediaPackageVodClient createMediaPackageVod(array $args = [])
|
287 |
+
* @method \Aws\MultiRegionClient createMultiRegionMediaPackageVod(array $args = [])
|
288 |
* @method \Aws\MediaStore\MediaStoreClient createMediaStore(array $args = [])
|
289 |
* @method \Aws\MultiRegionClient createMultiRegionMediaStore(array $args = [])
|
290 |
* @method \Aws\MediaStoreData\MediaStoreDataClient createMediaStoreData(array $args = [])
|
293 |
* @method \Aws\MultiRegionClient createMultiRegionMediaTailor(array $args = [])
|
294 |
* @method \Aws\MigrationHub\MigrationHubClient createMigrationHub(array $args = [])
|
295 |
* @method \Aws\MultiRegionClient createMultiRegionMigrationHub(array $args = [])
|
296 |
+
* @method \Aws\MigrationHubConfig\MigrationHubConfigClient createMigrationHubConfig(array $args = [])
|
297 |
+
* @method \Aws\MultiRegionClient createMultiRegionMigrationHubConfig(array $args = [])
|
298 |
* @method \Aws\Mobile\MobileClient createMobile(array $args = [])
|
299 |
* @method \Aws\MultiRegionClient createMultiRegionMobile(array $args = [])
|
300 |
* @method \Aws\Neptune\NeptuneClient createNeptune(array $args = [])
|
301 |
* @method \Aws\MultiRegionClient createMultiRegionNeptune(array $args = [])
|
302 |
+
* @method \Aws\NetworkManager\NetworkManagerClient createNetworkManager(array $args = [])
|
303 |
+
* @method \Aws\MultiRegionClient createMultiRegionNetworkManager(array $args = [])
|
304 |
* @method \Aws\OpsWorks\OpsWorksClient createOpsWorks(array $args = [])
|
305 |
* @method \Aws\MultiRegionClient createMultiRegionOpsWorks(array $args = [])
|
306 |
* @method \Aws\OpsWorksCM\OpsWorksCMClient createOpsWorksCM(array $args = [])
|
307 |
* @method \Aws\MultiRegionClient createMultiRegionOpsWorksCM(array $args = [])
|
308 |
* @method \Aws\Organizations\OrganizationsClient createOrganizations(array $args = [])
|
309 |
* @method \Aws\MultiRegionClient createMultiRegionOrganizations(array $args = [])
|
310 |
+
* @method \Aws\Outposts\OutpostsClient createOutposts(array $args = [])
|
311 |
+
* @method \Aws\MultiRegionClient createMultiRegionOutposts(array $args = [])
|
312 |
* @method \Aws\PI\PIClient createPI(array $args = [])
|
313 |
* @method \Aws\MultiRegionClient createMultiRegionPI(array $args = [])
|
314 |
+
* @method \Aws\Personalize\PersonalizeClient createPersonalize(array $args = [])
|
315 |
+
* @method \Aws\MultiRegionClient createMultiRegionPersonalize(array $args = [])
|
316 |
+
* @method \Aws\PersonalizeEvents\PersonalizeEventsClient createPersonalizeEvents(array $args = [])
|
317 |
+
* @method \Aws\MultiRegionClient createMultiRegionPersonalizeEvents(array $args = [])
|
318 |
+
* @method \Aws\PersonalizeRuntime\PersonalizeRuntimeClient createPersonalizeRuntime(array $args = [])
|
319 |
+
* @method \Aws\MultiRegionClient createMultiRegionPersonalizeRuntime(array $args = [])
|
320 |
* @method \Aws\Pinpoint\PinpointClient createPinpoint(array $args = [])
|
321 |
* @method \Aws\MultiRegionClient createMultiRegionPinpoint(array $args = [])
|
322 |
* @method \Aws\PinpointEmail\PinpointEmailClient createPinpointEmail(array $args = [])
|
327 |
* @method \Aws\MultiRegionClient createMultiRegionPolly(array $args = [])
|
328 |
* @method \Aws\Pricing\PricingClient createPricing(array $args = [])
|
329 |
* @method \Aws\MultiRegionClient createMultiRegionPricing(array $args = [])
|
330 |
+
* @method \Aws\QLDB\QLDBClient createQLDB(array $args = [])
|
331 |
+
* @method \Aws\MultiRegionClient createMultiRegionQLDB(array $args = [])
|
332 |
+
* @method \Aws\QLDBSession\QLDBSessionClient createQLDBSession(array $args = [])
|
333 |
+
* @method \Aws\MultiRegionClient createMultiRegionQLDBSession(array $args = [])
|
334 |
* @method \Aws\QuickSight\QuickSightClient createQuickSight(array $args = [])
|
335 |
* @method \Aws\MultiRegionClient createMultiRegionQuickSight(array $args = [])
|
336 |
* @method \Aws\RAM\RAMClient createRAM(array $args = [])
|
359 |
* @method \Aws\S3\S3MultiRegionClient createMultiRegionS3(array $args = [])
|
360 |
* @method \Aws\S3Control\S3ControlClient createS3Control(array $args = [])
|
361 |
* @method \Aws\MultiRegionClient createMultiRegionS3Control(array $args = [])
|
362 |
+
* @method \Aws\SSO\SSOClient createSSO(array $args = [])
|
363 |
+
* @method \Aws\MultiRegionClient createMultiRegionSSO(array $args = [])
|
364 |
+
* @method \Aws\SSOOIDC\SSOOIDCClient createSSOOIDC(array $args = [])
|
365 |
+
* @method \Aws\MultiRegionClient createMultiRegionSSOOIDC(array $args = [])
|
366 |
* @method \Aws\SageMaker\SageMakerClient createSageMaker(array $args = [])
|
367 |
* @method \Aws\MultiRegionClient createMultiRegionSageMaker(array $args = [])
|
368 |
* @method \Aws\SageMakerRuntime\SageMakerRuntimeClient createSageMakerRuntime(array $args = [])
|
369 |
* @method \Aws\MultiRegionClient createMultiRegionSageMakerRuntime(array $args = [])
|
370 |
+
* @method \Aws\SavingsPlans\SavingsPlansClient createSavingsPlans(array $args = [])
|
371 |
+
* @method \Aws\MultiRegionClient createMultiRegionSavingsPlans(array $args = [])
|
372 |
+
* @method \Aws\Schemas\SchemasClient createSchemas(array $args = [])
|
373 |
+
* @method \Aws\MultiRegionClient createMultiRegionSchemas(array $args = [])
|
374 |
* @method \Aws\SecretsManager\SecretsManagerClient createSecretsManager(array $args = [])
|
375 |
* @method \Aws\MultiRegionClient createMultiRegionSecretsManager(array $args = [])
|
376 |
* @method \Aws\SecurityHub\SecurityHubClient createSecurityHub(array $args = [])
|
381 |
* @method \Aws\MultiRegionClient createMultiRegionServiceCatalog(array $args = [])
|
382 |
* @method \Aws\ServiceDiscovery\ServiceDiscoveryClient createServiceDiscovery(array $args = [])
|
383 |
* @method \Aws\MultiRegionClient createMultiRegionServiceDiscovery(array $args = [])
|
384 |
+
* @method \Aws\ServiceQuotas\ServiceQuotasClient createServiceQuotas(array $args = [])
|
385 |
+
* @method \Aws\MultiRegionClient createMultiRegionServiceQuotas(array $args = [])
|
386 |
* @method \Aws\Ses\SesClient createSes(array $args = [])
|
387 |
* @method \Aws\MultiRegionClient createMultiRegionSes(array $args = [])
|
388 |
+
* @method \Aws\SesV2\SesV2Client createSesV2(array $args = [])
|
389 |
+
* @method \Aws\MultiRegionClient createMultiRegionSesV2(array $args = [])
|
390 |
* @method \Aws\Sfn\SfnClient createSfn(array $args = [])
|
391 |
* @method \Aws\MultiRegionClient createMultiRegionSfn(array $args = [])
|
392 |
* @method \Aws\Shield\ShieldClient createShield(array $args = [])
|
409 |
* @method \Aws\MultiRegionClient createMultiRegionSupport(array $args = [])
|
410 |
* @method \Aws\Swf\SwfClient createSwf(array $args = [])
|
411 |
* @method \Aws\MultiRegionClient createMultiRegionSwf(array $args = [])
|
412 |
+
* @method \Aws\Textract\TextractClient createTextract(array $args = [])
|
413 |
+
* @method \Aws\MultiRegionClient createMultiRegionTextract(array $args = [])
|
414 |
* @method \Aws\TranscribeService\TranscribeServiceClient createTranscribeService(array $args = [])
|
415 |
* @method \Aws\MultiRegionClient createMultiRegionTranscribeService(array $args = [])
|
416 |
* @method \Aws\Transfer\TransferClient createTransfer(array $args = [])
|
417 |
* @method \Aws\MultiRegionClient createMultiRegionTransfer(array $args = [])
|
418 |
* @method \Aws\Translate\TranslateClient createTranslate(array $args = [])
|
419 |
* @method \Aws\MultiRegionClient createMultiRegionTranslate(array $args = [])
|
420 |
+
* @method \Aws\WAFV2\WAFV2Client createWAFV2(array $args = [])
|
421 |
+
* @method \Aws\MultiRegionClient createMultiRegionWAFV2(array $args = [])
|
422 |
* @method \Aws\Waf\WafClient createWaf(array $args = [])
|
423 |
* @method \Aws\MultiRegionClient createMultiRegionWaf(array $args = [])
|
424 |
* @method \Aws\WafRegional\WafRegionalClient createWafRegional(array $args = [])
|
425 |
* @method \Aws\MultiRegionClient createMultiRegionWafRegional(array $args = [])
|
426 |
* @method \Aws\WorkDocs\WorkDocsClient createWorkDocs(array $args = [])
|
427 |
* @method \Aws\MultiRegionClient createMultiRegionWorkDocs(array $args = [])
|
428 |
+
* @method \Aws\WorkLink\WorkLinkClient createWorkLink(array $args = [])
|
429 |
+
* @method \Aws\MultiRegionClient createMultiRegionWorkLink(array $args = [])
|
430 |
* @method \Aws\WorkMail\WorkMailClient createWorkMail(array $args = [])
|
431 |
* @method \Aws\MultiRegionClient createMultiRegionWorkMail(array $args = [])
|
432 |
+
* @method \Aws\WorkMailMessageFlow\WorkMailMessageFlowClient createWorkMailMessageFlow(array $args = [])
|
433 |
+
* @method \Aws\MultiRegionClient createMultiRegionWorkMailMessageFlow(array $args = [])
|
434 |
* @method \Aws\WorkSpaces\WorkSpacesClient createWorkSpaces(array $args = [])
|
435 |
* @method \Aws\MultiRegionClient createMultiRegionWorkSpaces(array $args = [])
|
436 |
* @method \Aws\XRay\XRayClient createXRay(array $args = [])
|
437 |
* @method \Aws\MultiRegionClient createMultiRegionXRay(array $args = [])
|
438 |
+
* @method \Aws\imagebuilder\imagebuilderClient createimagebuilder(array $args = [])
|
439 |
+
* @method \Aws\MultiRegionClient createMultiRegionimagebuilder(array $args = [])
|
440 |
+
* @method \Aws\kendra\kendraClient createkendra(array $args = [])
|
441 |
+
* @method \Aws\MultiRegionClient createMultiRegionkendra(array $args = [])
|
442 |
* @method \Aws\signer\signerClient createsigner(array $args = [])
|
443 |
* @method \Aws\MultiRegionClient createMultiRegionsigner(array $args = [])
|
444 |
*/
|
445 |
class Sdk
|
446 |
{
|
447 |
+
const VERSION = '3.133.40';
|
448 |
/** @var array Arguments for creating clients */
|
449 |
private $args;
|
450 |
/**
|
503 |
$klass = class_exists($klass) ? $klass : 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\MultiRegionClient';
|
504 |
return new $klass($this->mergeArgs($namespace, $service, $args));
|
505 |
}
|
506 |
+
/**
|
507 |
+
* Clone existing SDK instance with ability to pass an associative array
|
508 |
+
* of extra client settings.
|
509 |
+
*
|
510 |
+
* @param array $args
|
511 |
+
*
|
512 |
+
* @return self
|
513 |
+
*/
|
514 |
+
public function copy(array $args = [])
|
515 |
+
{
|
516 |
+
return new self($args + $this->args);
|
517 |
+
}
|
518 |
private function mergeArgs($namespace, array $manifest, array $args = [])
|
519 |
{
|
520 |
// Merge provided args with stored, service-specific args.
|
@@ -13,7 +13,7 @@ class AnonymousSignature implements \DeliciousBrains\WP_Offload_Media\Aws3\Aws\S
|
|
13 |
{
|
14 |
return $request;
|
15 |
}
|
16 |
-
public function presign(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface $credentials, $expires)
|
17 |
{
|
18 |
return $request;
|
19 |
}
|
13 |
{
|
14 |
return $request;
|
15 |
}
|
16 |
+
public function presign(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface $credentials, $expires, array $options = [])
|
17 |
{
|
18 |
return $request;
|
19 |
}
|
@@ -32,5 +32,5 @@ interface SignatureInterface
|
|
32 |
*
|
33 |
* @return RequestInterface
|
34 |
*/
|
35 |
-
public function presign(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface $credentials, $expires);
|
36 |
}
|
32 |
*
|
33 |
* @return RequestInterface
|
34 |
*/
|
35 |
+
public function presign(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Credentials\CredentialsInterface $credentials, $expires, array $options = []);
|
36 |
}
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws;
|
4 |
+
|
5 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
|
6 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\IncalculablePayloadException;
|
7 |
+
use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
|
8 |
+
/**
|
9 |
+
* @internal
|
10 |
+
*/
|
11 |
+
class StreamRequestPayloadMiddleware
|
12 |
+
{
|
13 |
+
private $nextHandler;
|
14 |
+
private $service;
|
15 |
+
/**
|
16 |
+
* Create a middleware wrapper function
|
17 |
+
*
|
18 |
+
* @param Service $service
|
19 |
+
* @return \Closure
|
20 |
+
*/
|
21 |
+
public static function wrap(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $service)
|
22 |
+
{
|
23 |
+
return function (callable $handler) use($service) {
|
24 |
+
return new self($handler, $service);
|
25 |
+
};
|
26 |
+
}
|
27 |
+
public function __construct(callable $nextHandler, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $service)
|
28 |
+
{
|
29 |
+
$this->nextHandler = $nextHandler;
|
30 |
+
$this->service = $service;
|
31 |
+
}
|
32 |
+
public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface $request)
|
33 |
+
{
|
34 |
+
$nextHandler = $this->nextHandler;
|
35 |
+
$operation = $this->service->getOperation($command->getName());
|
36 |
+
$contentLength = $request->getHeader('content-length');
|
37 |
+
$hasStreaming = false;
|
38 |
+
$requiresLength = false;
|
39 |
+
// Check if any present input member is a stream and requires the
|
40 |
+
// content length
|
41 |
+
foreach ($operation->getInput()->getMembers() as $name => $member) {
|
42 |
+
if (!empty($member['streaming']) && isset($command[$name])) {
|
43 |
+
$hasStreaming = true;
|
44 |
+
if (!empty($member['requiresLength'])) {
|
45 |
+
$requiresLength = true;
|
46 |
+
}
|
47 |
+
}
|
48 |
+
}
|
49 |
+
if ($hasStreaming) {
|
50 |
+
// Add 'transfer-encoding' header if payload size not required to
|
51 |
+
// to be calculated and not already known
|
52 |
+
if (empty($requiresLength) && empty($contentLength) && isset($operation['authtype']) && $operation['authtype'] == 'v4-unsigned-body') {
|
53 |
+
$request = $request->withHeader('transfer-encoding', 'chunked');
|
54 |
+
// Otherwise, make sure 'content-length' header is added
|
55 |
+
} else {
|
56 |
+
if (empty($contentLength)) {
|
57 |
+
$size = $request->getBody()->getSize();
|
58 |
+
if (is_null($size)) {
|
59 |
+
throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\IncalculablePayloadException('Payload' . ' content length is required and can not be' . ' calculated.');
|
60 |
+
}
|
61 |
+
$request = $request->withHeader('content-length', $size);
|
62 |
+
}
|
63 |
+
}
|
64 |
+
}
|
65 |
+
return $nextHandler($command, $request);
|
66 |
+
}
|
67 |
+
}
|
@@ -124,7 +124,7 @@ class WrappedHttpHandler
|
|
124 |
$parts = ['response' => null];
|
125 |
} else {
|
126 |
try {
|
127 |
-
$parts = call_user_func($this->errorParser, $err['response']);
|
128 |
$serviceError .= " {$parts['code']} ({$parts['type']}): " . "{$parts['message']} - " . $err['response']->getBody();
|
129 |
} catch (ParserException $e) {
|
130 |
$parts = [];
|
124 |
$parts = ['response' => null];
|
125 |
} else {
|
126 |
try {
|
127 |
+
$parts = call_user_func($this->errorParser, $err['response'], $command);
|
128 |
$serviceError .= " {$parts['code']} ({$parts['type']}): " . "{$parts['message']} - " . $err['response']->getBody();
|
129 |
} catch (ParserException $e) {
|
130 |
$parts = [];
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// This file was auto-generated from sdk-root/src/data/accessanalyzer/2019-11-01/api-2.json
|
4 |
+
return ['version' => '2.0', 'metadata' => ['apiVersion' => '2019-11-01', 'endpointPrefix' => 'access-analyzer', 'jsonVersion' => '1.1', 'protocol' => 'rest-json', 'serviceFullName' => 'Access Analyzer', 'serviceId' => 'AccessAnalyzer', 'signatureVersion' => 'v4', 'signingName' => 'access-analyzer', 'uid' => 'accessanalyzer-2019-11-01'], 'operations' => ['CreateAnalyzer' => ['name' => 'CreateAnalyzer', 'http' => ['method' => 'PUT', 'requestUri' => '/analyzer', 'responseCode' => 200], 'input' => ['shape' => 'CreateAnalyzerRequest'], 'output' => ['shape' => 'CreateAnalyzerResponse'], 'errors' => [['shape' => 'ConflictException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ServiceQuotaExceededException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'CreateArchiveRule' => ['name' => 'CreateArchiveRule', 'http' => ['method' => 'PUT', 'requestUri' => '/analyzer/{analyzerName}/archive-rule', 'responseCode' => 200], 'input' => ['shape' => 'CreateArchiveRuleRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ConflictException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ServiceQuotaExceededException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'DeleteAnalyzer' => ['name' => 'DeleteAnalyzer', 'http' => ['method' => 'DELETE', 'requestUri' => '/analyzer/{analyzerName}', 'responseCode' => 200], 'input' => ['shape' => 'DeleteAnalyzerRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'DeleteArchiveRule' => ['name' => 'DeleteArchiveRule', 'http' => ['method' => 'DELETE', 'requestUri' => '/analyzer/{analyzerName}/archive-rule/{ruleName}', 'responseCode' => 200], 'input' => ['shape' => 'DeleteArchiveRuleRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'GetAnalyzedResource' => ['name' => 'GetAnalyzedResource', 'http' => ['method' => 'GET', 'requestUri' => '/analyzed-resource', 'responseCode' => 200], 'input' => ['shape' => 'GetAnalyzedResourceRequest'], 'output' => ['shape' => 'GetAnalyzedResourceResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'GetAnalyzer' => ['name' => 'GetAnalyzer', 'http' => ['method' => 'GET', 'requestUri' => '/analyzer/{analyzerName}', 'responseCode' => 200], 'input' => ['shape' => 'GetAnalyzerRequest'], 'output' => ['shape' => 'GetAnalyzerResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'GetArchiveRule' => ['name' => 'GetArchiveRule', 'http' => ['method' => 'GET', 'requestUri' => '/analyzer/{analyzerName}/archive-rule/{ruleName}', 'responseCode' => 200], 'input' => ['shape' => 'GetArchiveRuleRequest'], 'output' => ['shape' => 'GetArchiveRuleResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'GetFinding' => ['name' => 'GetFinding', 'http' => ['method' => 'GET', 'requestUri' => '/finding/{id}', 'responseCode' => 200], 'input' => ['shape' => 'GetFindingRequest'], 'output' => ['shape' => 'GetFindingResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'ListAnalyzedResources' => ['name' => 'ListAnalyzedResources', 'http' => ['method' => 'POST', 'requestUri' => '/analyzed-resource', 'responseCode' => 200], 'input' => ['shape' => 'ListAnalyzedResourcesRequest'], 'output' => ['shape' => 'ListAnalyzedResourcesResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'ListAnalyzers' => ['name' => 'ListAnalyzers', 'http' => ['method' => 'GET', 'requestUri' => '/analyzer', 'responseCode' => 200], 'input' => ['shape' => 'ListAnalyzersRequest'], 'output' => ['shape' => 'ListAnalyzersResponse'], 'errors' => [['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'ListArchiveRules' => ['name' => 'ListArchiveRules', 'http' => ['method' => 'GET', 'requestUri' => '/analyzer/{analyzerName}/archive-rule', 'responseCode' => 200], 'input' => ['shape' => 'ListArchiveRulesRequest'], 'output' => ['shape' => 'ListArchiveRulesResponse'], 'errors' => [['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'ListFindings' => ['name' => 'ListFindings', 'http' => ['method' => 'POST', 'requestUri' => '/finding', 'responseCode' => 200], 'input' => ['shape' => 'ListFindingsRequest'], 'output' => ['shape' => 'ListFindingsResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'ListTagsForResource' => ['name' => 'ListTagsForResource', 'http' => ['method' => 'GET', 'requestUri' => '/tags/{resourceArn}', 'responseCode' => 200], 'input' => ['shape' => 'ListTagsForResourceRequest'], 'output' => ['shape' => 'ListTagsForResourceResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'StartResourceScan' => ['name' => 'StartResourceScan', 'http' => ['method' => 'POST', 'requestUri' => '/resource/scan', 'responseCode' => 200], 'input' => ['shape' => 'StartResourceScanRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']]], 'TagResource' => ['name' => 'TagResource', 'http' => ['method' => 'POST', 'requestUri' => '/tags/{resourceArn}', 'responseCode' => 200], 'input' => ['shape' => 'TagResourceRequest'], 'output' => ['shape' => 'TagResourceResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'UntagResource' => ['name' => 'UntagResource', 'http' => ['method' => 'DELETE', 'requestUri' => '/tags/{resourceArn}', 'responseCode' => 200], 'input' => ['shape' => 'UntagResourceRequest'], 'output' => ['shape' => 'UntagResourceResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'UpdateArchiveRule' => ['name' => 'UpdateArchiveRule', 'http' => ['method' => 'PUT', 'requestUri' => '/analyzer/{analyzerName}/archive-rule/{ruleName}', 'responseCode' => 200], 'input' => ['shape' => 'UpdateArchiveRuleRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true], 'UpdateFindings' => ['name' => 'UpdateFindings', 'http' => ['method' => 'PUT', 'requestUri' => '/finding', 'responseCode' => 200], 'input' => ['shape' => 'UpdateFindingsRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ValidationException'], ['shape' => 'InternalServerException'], ['shape' => 'ThrottlingException'], ['shape' => 'AccessDeniedException']], 'idempotent' => \true]], 'shapes' => ['AccessDeniedException' => ['type' => 'structure', 'required' => ['message'], 'members' => ['message' => ['shape' => 'String']], 'error' => ['httpStatusCode' => 403, 'senderFault' => \true], 'exception' => \true], 'ActionList' => ['type' => 'list', 'member' => ['shape' => 'String']], 'AnalyzedResource' => ['type' => 'structure', 'required' => ['analyzedAt', 'createdAt', 'isPublic', 'resourceArn', 'resourceType', 'updatedAt'], 'members' => ['actions' => ['shape' => 'ActionList'], 'analyzedAt' => ['shape' => 'Timestamp'], 'createdAt' => ['shape' => 'Timestamp'], 'error' => ['shape' => 'String'], 'isPublic' => ['shape' => 'Boolean'], 'resourceArn' => ['shape' => 'ResourceArn'], 'resourceType' => ['shape' => 'ResourceType'], 'sharedVia' => ['shape' => 'SharedViaList'], 'status' => ['shape' => 'FindingStatus'], 'updatedAt' => ['shape' => 'Timestamp']]], 'AnalyzedResourceSummary' => ['type' => 'structure', 'required' => ['resourceArn', 'resourceType'], 'members' => ['resourceArn' => ['shape' => 'ResourceArn'], 'resourceType' => ['shape' => 'ResourceType']]], 'AnalyzedResourcesList' => ['type' => 'list', 'member' => ['shape' => 'AnalyzedResourceSummary']], 'AnalyzerArn' => ['type' => 'string', 'pattern' => '^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:analyzer/.{1,255}$'], 'AnalyzerSummary' => ['type' => 'structure', 'required' => ['arn', 'createdAt', 'name', 'type'], 'members' => ['arn' => ['shape' => 'AnalyzerArn'], 'createdAt' => ['shape' => 'Timestamp'], 'lastResourceAnalyzed' => ['shape' => 'String'], 'lastResourceAnalyzedAt' => ['shape' => 'Timestamp'], 'name' => ['shape' => 'Name'], 'tags' => ['shape' => 'TagsMap'], 'type' => ['shape' => 'Type']]], 'AnalyzersList' => ['type' => 'list', 'member' => ['shape' => 'AnalyzerSummary']], 'ArchiveRuleSummary' => ['type' => 'structure', 'required' => ['createdAt', 'filter', 'ruleName', 'updatedAt'], 'members' => ['createdAt' => ['shape' => 'Timestamp'], 'filter' => ['shape' => 'FilterCriteriaMap'], 'ruleName' => ['shape' => 'Name'], 'updatedAt' => ['shape' => 'Timestamp']]], 'ArchiveRulesList' => ['type' => 'list', 'member' => ['shape' => 'ArchiveRuleSummary']], 'Boolean' => ['type' => 'boolean', 'box' => \true], 'ConditionKeyMap' => ['type' => 'map', 'key' => ['shape' => 'String'], 'value' => ['shape' => 'String']], 'ConflictException' => ['type' => 'structure', 'required' => ['message', 'resourceId', 'resourceType'], 'members' => ['message' => ['shape' => 'String'], 'resourceId' => ['shape' => 'String'], 'resourceType' => ['shape' => 'String']], 'error' => ['httpStatusCode' => 409, 'senderFault' => \true], 'exception' => \true], 'CreateAnalyzerRequest' => ['type' => 'structure', 'required' => ['analyzerName', 'type'], 'members' => ['analyzerName' => ['shape' => 'Name'], 'archiveRules' => ['shape' => 'InlineArchiveRulesList'], 'clientToken' => ['shape' => 'String', 'idempotencyToken' => \true], 'tags' => ['shape' => 'TagsMap'], 'type' => ['shape' => 'Type']]], 'CreateAnalyzerResponse' => ['type' => 'structure', 'members' => ['arn' => ['shape' => 'AnalyzerArn']]], 'CreateArchiveRuleRequest' => ['type' => 'structure', 'required' => ['analyzerName', 'filter', 'ruleName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName'], 'clientToken' => ['shape' => 'String', 'idempotencyToken' => \true], 'filter' => ['shape' => 'FilterCriteriaMap'], 'ruleName' => ['shape' => 'Name']]], 'Criterion' => ['type' => 'structure', 'members' => ['contains' => ['shape' => 'ValueList'], 'eq' => ['shape' => 'ValueList'], 'exists' => ['shape' => 'Boolean'], 'neq' => ['shape' => 'ValueList']]], 'DeleteAnalyzerRequest' => ['type' => 'structure', 'required' => ['analyzerName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName'], 'clientToken' => ['shape' => 'String', 'idempotencyToken' => \true, 'location' => 'querystring', 'locationName' => 'clientToken']]], 'DeleteArchiveRuleRequest' => ['type' => 'structure', 'required' => ['analyzerName', 'ruleName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName'], 'clientToken' => ['shape' => 'String', 'idempotencyToken' => \true, 'location' => 'querystring', 'locationName' => 'clientToken'], 'ruleName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'ruleName']]], 'FilterCriteriaMap' => ['type' => 'map', 'key' => ['shape' => 'String'], 'value' => ['shape' => 'Criterion']], 'Finding' => ['type' => 'structure', 'required' => ['analyzedAt', 'condition', 'createdAt', 'id', 'resourceType', 'status', 'updatedAt'], 'members' => ['action' => ['shape' => 'ActionList'], 'analyzedAt' => ['shape' => 'Timestamp'], 'condition' => ['shape' => 'ConditionKeyMap'], 'createdAt' => ['shape' => 'Timestamp'], 'error' => ['shape' => 'String'], 'id' => ['shape' => 'FindingId'], 'isPublic' => ['shape' => 'Boolean'], 'principal' => ['shape' => 'PrincipalMap'], 'resource' => ['shape' => 'String'], 'resourceType' => ['shape' => 'ResourceType'], 'status' => ['shape' => 'FindingStatus'], 'updatedAt' => ['shape' => 'Timestamp']]], 'FindingId' => ['type' => 'string'], 'FindingIdList' => ['type' => 'list', 'member' => ['shape' => 'FindingId']], 'FindingStatus' => ['type' => 'string', 'enum' => ['ACTIVE', 'ARCHIVED', 'RESOLVED']], 'FindingStatusUpdate' => ['type' => 'string', 'enum' => ['ACTIVE', 'ARCHIVED']], 'FindingSummary' => ['type' => 'structure', 'required' => ['analyzedAt', 'condition', 'createdAt', 'id', 'resourceType', 'status', 'updatedAt'], 'members' => ['action' => ['shape' => 'ActionList'], 'analyzedAt' => ['shape' => 'Timestamp'], 'condition' => ['shape' => 'ConditionKeyMap'], 'createdAt' => ['shape' => 'Timestamp'], 'error' => ['shape' => 'String'], 'id' => ['shape' => 'FindingId'], 'isPublic' => ['shape' => 'Boolean'], 'principal' => ['shape' => 'PrincipalMap'], 'resource' => ['shape' => 'String'], 'resourceType' => ['shape' => 'ResourceType'], 'status' => ['shape' => 'FindingStatus'], 'updatedAt' => ['shape' => 'Timestamp']]], 'FindingsList' => ['type' => 'list', 'member' => ['shape' => 'FindingSummary']], 'GetAnalyzedResourceRequest' => ['type' => 'structure', 'required' => ['analyzerArn', 'resourceArn'], 'members' => ['analyzerArn' => ['shape' => 'AnalyzerArn', 'location' => 'querystring', 'locationName' => 'analyzerArn'], 'resourceArn' => ['shape' => 'ResourceArn', 'location' => 'querystring', 'locationName' => 'resourceArn']]], 'GetAnalyzedResourceResponse' => ['type' => 'structure', 'members' => ['resource' => ['shape' => 'AnalyzedResource']]], 'GetAnalyzerRequest' => ['type' => 'structure', 'required' => ['analyzerName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName']]], 'GetAnalyzerResponse' => ['type' => 'structure', 'required' => ['analyzer'], 'members' => ['analyzer' => ['shape' => 'AnalyzerSummary']]], 'GetArchiveRuleRequest' => ['type' => 'structure', 'required' => ['analyzerName', 'ruleName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName'], 'ruleName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'ruleName']]], 'GetArchiveRuleResponse' => ['type' => 'structure', 'required' => ['archiveRule'], 'members' => ['archiveRule' => ['shape' => 'ArchiveRuleSummary']]], 'GetFindingRequest' => ['type' => 'structure', 'required' => ['analyzerArn', 'id'], 'members' => ['analyzerArn' => ['shape' => 'AnalyzerArn', 'location' => 'querystring', 'locationName' => 'analyzerArn'], 'id' => ['shape' => 'FindingId', 'location' => 'uri', 'locationName' => 'id']]], 'GetFindingResponse' => ['type' => 'structure', 'members' => ['finding' => ['shape' => 'Finding']]], 'InlineArchiveRule' => ['type' => 'structure', 'required' => ['filter', 'ruleName'], 'members' => ['filter' => ['shape' => 'FilterCriteriaMap'], 'ruleName' => ['shape' => 'Name']]], 'InlineArchiveRulesList' => ['type' => 'list', 'member' => ['shape' => 'InlineArchiveRule']], 'Integer' => ['type' => 'integer', 'box' => \true], 'InternalServerException' => ['type' => 'structure', 'required' => ['message'], 'members' => ['message' => ['shape' => 'String'], 'retryAfterSeconds' => ['shape' => 'Integer', 'location' => 'header', 'locationName' => 'Retry-After']], 'error' => ['httpStatusCode' => 500], 'exception' => \true, 'fault' => \true], 'ListAnalyzedResourcesRequest' => ['type' => 'structure', 'required' => ['analyzerArn'], 'members' => ['analyzerArn' => ['shape' => 'AnalyzerArn'], 'maxResults' => ['shape' => 'Integer'], 'nextToken' => ['shape' => 'Token'], 'resourceType' => ['shape' => 'ResourceType']]], 'ListAnalyzedResourcesResponse' => ['type' => 'structure', 'required' => ['analyzedResources'], 'members' => ['analyzedResources' => ['shape' => 'AnalyzedResourcesList'], 'nextToken' => ['shape' => 'Token']]], 'ListAnalyzersRequest' => ['type' => 'structure', 'members' => ['maxResults' => ['shape' => 'Integer', 'location' => 'querystring', 'locationName' => 'maxResults'], 'nextToken' => ['shape' => 'Token', 'location' => 'querystring', 'locationName' => 'nextToken'], 'type' => ['shape' => 'Type', 'location' => 'querystring', 'locationName' => 'type']]], 'ListAnalyzersResponse' => ['type' => 'structure', 'required' => ['analyzers'], 'members' => ['analyzers' => ['shape' => 'AnalyzersList'], 'nextToken' => ['shape' => 'Token']]], 'ListArchiveRulesRequest' => ['type' => 'structure', 'required' => ['analyzerName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName'], 'maxResults' => ['shape' => 'Integer', 'location' => 'querystring', 'locationName' => 'maxResults'], 'nextToken' => ['shape' => 'Token', 'location' => 'querystring', 'locationName' => 'nextToken']]], 'ListArchiveRulesResponse' => ['type' => 'structure', 'required' => ['archiveRules'], 'members' => ['archiveRules' => ['shape' => 'ArchiveRulesList'], 'nextToken' => ['shape' => 'Token']]], 'ListFindingsRequest' => ['type' => 'structure', 'required' => ['analyzerArn'], 'members' => ['analyzerArn' => ['shape' => 'AnalyzerArn'], 'filter' => ['shape' => 'FilterCriteriaMap'], 'maxResults' => ['shape' => 'Integer'], 'nextToken' => ['shape' => 'Token'], 'sort' => ['shape' => 'SortCriteria']]], 'ListFindingsResponse' => ['type' => 'structure', 'required' => ['findings'], 'members' => ['findings' => ['shape' => 'FindingsList'], 'nextToken' => ['shape' => 'Token']]], 'ListTagsForResourceRequest' => ['type' => 'structure', 'required' => ['resourceArn'], 'members' => ['resourceArn' => ['shape' => 'String', 'location' => 'uri', 'locationName' => 'resourceArn']]], 'ListTagsForResourceResponse' => ['type' => 'structure', 'members' => ['tags' => ['shape' => 'TagsMap']]], 'Name' => ['type' => 'string', 'max' => 255, 'min' => 1, 'pattern' => '^[A-Za-z][A-Za-z0-9_.-]*$'], 'OrderBy' => ['type' => 'string', 'enum' => ['ASC', 'DESC']], 'PrincipalMap' => ['type' => 'map', 'key' => ['shape' => 'String'], 'value' => ['shape' => 'String']], 'ResourceArn' => ['type' => 'string', 'pattern' => 'arn:[^:]*:[^:]*:[^:]*:[^:]*:.*$'], 'ResourceNotFoundException' => ['type' => 'structure', 'required' => ['message', 'resourceId', 'resourceType'], 'members' => ['message' => ['shape' => 'String'], 'resourceId' => ['shape' => 'String'], 'resourceType' => ['shape' => 'String']], 'error' => ['httpStatusCode' => 404, 'senderFault' => \true], 'exception' => \true], 'ResourceType' => ['type' => 'string', 'enum' => ['AWS::IAM::Role', 'AWS::KMS::Key', 'AWS::Lambda::Function', 'AWS::Lambda::LayerVersion', 'AWS::S3::Bucket', 'AWS::SQS::Queue']], 'ServiceQuotaExceededException' => ['type' => 'structure', 'required' => ['message', 'resourceId', 'resourceType'], 'members' => ['message' => ['shape' => 'String'], 'resourceId' => ['shape' => 'String'], 'resourceType' => ['shape' => 'String']], 'error' => ['httpStatusCode' => 402, 'senderFault' => \true], 'exception' => \true], 'SharedViaList' => ['type' => 'list', 'member' => ['shape' => 'String']], 'SortCriteria' => ['type' => 'structure', 'members' => ['attributeName' => ['shape' => 'String'], 'orderBy' => ['shape' => 'OrderBy']]], 'StartResourceScanRequest' => ['type' => 'structure', 'required' => ['analyzerArn', 'resourceArn'], 'members' => ['analyzerArn' => ['shape' => 'AnalyzerArn'], 'resourceArn' => ['shape' => 'ResourceArn']]], 'String' => ['type' => 'string'], 'TagKeys' => ['type' => 'list', 'member' => ['shape' => 'String']], 'TagResourceRequest' => ['type' => 'structure', 'required' => ['resourceArn', 'tags'], 'members' => ['resourceArn' => ['shape' => 'String', 'location' => 'uri', 'locationName' => 'resourceArn'], 'tags' => ['shape' => 'TagsMap']]], 'TagResourceResponse' => ['type' => 'structure', 'members' => []], 'TagsMap' => ['type' => 'map', 'key' => ['shape' => 'String'], 'value' => ['shape' => 'String']], 'ThrottlingException' => ['type' => 'structure', 'required' => ['message'], 'members' => ['message' => ['shape' => 'String'], 'retryAfterSeconds' => ['shape' => 'Integer', 'location' => 'header', 'locationName' => 'Retry-After']], 'error' => ['httpStatusCode' => 429, 'senderFault' => \true], 'exception' => \true], 'Timestamp' => ['type' => 'timestamp', 'timestampFormat' => 'iso8601'], 'Token' => ['type' => 'string'], 'Type' => ['type' => 'string', 'enum' => ['ACCOUNT']], 'UntagResourceRequest' => ['type' => 'structure', 'required' => ['resourceArn', 'tagKeys'], 'members' => ['resourceArn' => ['shape' => 'String', 'location' => 'uri', 'locationName' => 'resourceArn'], 'tagKeys' => ['shape' => 'TagKeys', 'location' => 'querystring', 'locationName' => 'tagKeys']]], 'UntagResourceResponse' => ['type' => 'structure', 'members' => []], 'UpdateArchiveRuleRequest' => ['type' => 'structure', 'required' => ['analyzerName', 'filter', 'ruleName'], 'members' => ['analyzerName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'analyzerName'], 'clientToken' => ['shape' => 'String', 'idempotencyToken' => \true], 'filter' => ['shape' => 'FilterCriteriaMap'], 'ruleName' => ['shape' => 'Name', 'location' => 'uri', 'locationName' => 'ruleName']]], 'UpdateFindingsRequest' => ['type' => 'structure', 'required' => ['analyzerArn', 'status'], 'members' => ['analyzerArn' => ['shape' => 'AnalyzerArn'], 'clientToken' => ['shape' => 'String', 'idempotencyToken' => \true], 'ids' => ['shape' => 'FindingIdList'], 'resourceArn' => ['shape' => 'ResourceArn'], 'status' => ['shape' => 'FindingStatusUpdate']]], 'ValidationException' => ['type' => 'structure', 'required' => ['message', 'reason'], 'members' => ['fieldList' => ['shape' => 'ValidationExceptionFieldList'], 'message' => ['shape' => 'String'], 'reason' => ['shape' => 'ValidationExceptionReason']], 'error' => ['httpStatusCode' => 400, 'senderFault' => \true], 'exception' => \true], 'ValidationExceptionField' => ['type' => 'structure', 'required' => ['message', 'name'], 'members' => ['message' => ['shape' => 'String'], 'name' => ['shape' => 'String']]], 'ValidationExceptionFieldList' => ['type' => 'list', 'member' => ['shape' => 'ValidationExceptionField']], 'ValidationExceptionReason' => ['type' => 'string', 'enum' => ['cannotParse', 'fieldValidationFailed', 'other', 'unknownOperation']], 'ValueList' => ['type' => 'list', 'member' => ['shape' => 'String'], 'max' => 20, 'min' => 1]]];
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// This file was auto-generated from sdk-root/src/data/accessanalyzer/2019-11-01/paginators-1.json
|
4 |
+
return ['pagination' => ['ListAnalyzedResources' => ['input_token' => 'nextToken', 'output_token' => 'nextToken', 'limit_key' => 'maxResults', 'result_key' => 'analyzedResources'], 'ListAnalyzers' => ['input_token' => 'nextToken', 'output_token' => 'nextToken', 'limit_key' => 'maxResults', 'result_key' => 'analyzers'], 'ListArchiveRules' => ['input_token' => 'nextToken', 'output_token' => 'nextToken', 'limit_key' => 'maxResults', 'result_key' => 'archiveRules'], 'ListFindings' => ['input_token' => 'nextToken', 'output_token' => 'nextToken', 'limit_key' => 'maxResults', 'result_key' => 'findings']]];
|
@@ -1,4 +1,4 @@
|
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/acm-pca/2017-08-22/api-2.json
|
4 |
-
return ['version' => '2.0', 'metadata' => ['apiVersion' => '2017-08-22', 'endpointPrefix' => 'acm-pca', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceAbbreviation' => 'ACM-PCA', 'serviceFullName' => 'AWS Certificate Manager Private Certificate Authority', 'serviceId' => 'ACM PCA', 'signatureVersion' => 'v4', 'targetPrefix' => 'ACMPrivateCA', 'uid' => 'acm-pca-2017-08-22'], 'operations' => ['CreateCertificateAuthority' => ['name' => 'CreateCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateCertificateAuthorityRequest'], 'output' => ['shape' => 'CreateCertificateAuthorityResponse'], 'errors' => [['shape' => 'InvalidArgsException'], ['shape' => 'InvalidPolicyException'], ['shape' => 'LimitExceededException']], 'idempotent' => \true], 'CreateCertificateAuthorityAuditReport' => ['name' => 'CreateCertificateAuthorityAuditReport', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateCertificateAuthorityAuditReportRequest'], 'output' => ['shape' => 'CreateCertificateAuthorityAuditReportResponse'], 'errors' => [['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidArgsException'], ['shape' => 'InvalidStateException']], 'idempotent' => \true], 'DeleteCertificateAuthority' => ['name' => 'DeleteCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteCertificateAuthorityRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'DescribeCertificateAuthority' => ['name' => 'DescribeCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DescribeCertificateAuthorityRequest'], 'output' => ['shape' => 'DescribeCertificateAuthorityResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'DescribeCertificateAuthorityAuditReport' => ['name' => 'DescribeCertificateAuthorityAuditReport', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DescribeCertificateAuthorityAuditReportRequest'], 'output' => ['shape' => 'DescribeCertificateAuthorityAuditReportResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidArgsException']]], 'GetCertificate' => ['name' => 'GetCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateRequest'], 'output' => ['shape' => 'GetCertificateResponse'], 'errors' => [['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'GetCertificateAuthorityCertificate' => ['name' => 'GetCertificateAuthorityCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateAuthorityCertificateRequest'], 'output' => ['shape' => 'GetCertificateAuthorityCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException']]], 'GetCertificateAuthorityCsr' => ['name' => 'GetCertificateAuthorityCsr', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateAuthorityCsrRequest'], 'output' => ['shape' => 'GetCertificateAuthorityCsrResponse'], 'errors' => [['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'ImportCertificateAuthorityCertificate' => ['name' => 'ImportCertificateAuthorityCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ImportCertificateAuthorityCertificateRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'MalformedCertificateException'], ['shape' => 'CertificateMismatchException']]], 'IssueCertificate' => ['name' => 'IssueCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'IssueCertificateRequest'], 'output' => ['shape' => 'IssueCertificateResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidArgsException'], ['shape' => 'MalformedCSRException']], 'idempotent' => \true], 'ListCertificateAuthorities' => ['name' => 'ListCertificateAuthorities', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListCertificateAuthoritiesRequest'], 'output' => ['shape' => 'ListCertificateAuthoritiesResponse'], 'errors' => [['shape' => 'InvalidNextTokenException']]], 'ListTags' => ['name' => 'ListTags', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListTagsRequest'], 'output' => ['shape' => 'ListTagsResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'RestoreCertificateAuthority' => ['name' => 'RestoreCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RestoreCertificateAuthorityRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException']]], 'RevokeCertificate' => ['name' => 'RevokeCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RevokeCertificateRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'RequestAlreadyProcessedException'], ['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException']]], 'TagCertificateAuthority' => ['name' => 'TagCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'TagCertificateAuthorityRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidTagException'], ['shape' => 'TooManyTagsException']]], 'UntagCertificateAuthority' => ['name' => 'UntagCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UntagCertificateAuthorityRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidTagException']]], 'UpdateCertificateAuthority' => ['name' => 'UpdateCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateCertificateAuthorityRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArgsException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidPolicyException']]]], 'shapes' => ['ASN1Subject' => ['type' => 'structure', 'members' => ['Country' => ['shape' => 'CountryCodeString'], 'Organization' => ['shape' => 'String64'], 'OrganizationalUnit' => ['shape' => 'String64'], 'DistinguishedNameQualifier' => ['shape' => 'DistinguishedNameQualifierString'], 'State' => ['shape' => 'String128'], 'CommonName' => ['shape' => 'String64'], 'SerialNumber' => ['shape' => 'String64'], 'Locality' => ['shape' => 'String128'], 'Title' => ['shape' => 'String64'], 'Surname' => ['shape' => 'String40'], 'GivenName' => ['shape' => 'String16'], 'Initials' => ['shape' => 'String5'], 'Pseudonym' => ['shape' => 'String128'], 'GenerationQualifier' => ['shape' => 'String3']]], 'Arn' => ['type' => 'string', 'max' => 200, 'min' => 5, 'pattern' => 'arn:[\\w+=/,.@-]+:[\\w+=/,.@-]+:[\\w+=/,.@-]*:[0-9]+:[\\w+=,.@-]+(/[\\w+=/,.@-]+)*'], 'AuditReportId' => ['type' => 'string', 'max' => 36, 'min' => 36, 'pattern' => '[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}'], 'AuditReportResponseFormat' => ['type' => 'string', 'enum' => ['JSON', 'CSV']], 'AuditReportStatus' => ['type' => 'string', 'enum' => ['CREATING', 'SUCCESS', 'FAILED']], 'Boolean' => ['type' => 'boolean'], 'CertificateAuthorities' => ['type' => 'list', 'member' => ['shape' => 'CertificateAuthority']], 'CertificateAuthority' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'CreatedAt' => ['shape' => 'TStamp'], 'LastStateChangeAt' => ['shape' => 'TStamp'], 'Type' => ['shape' => 'CertificateAuthorityType'], 'Serial' => ['shape' => 'String'], 'Status' => ['shape' => 'CertificateAuthorityStatus'], 'NotBefore' => ['shape' => 'TStamp'], 'NotAfter' => ['shape' => 'TStamp'], 'FailureReason' => ['shape' => 'FailureReason'], 'CertificateAuthorityConfiguration' => ['shape' => 'CertificateAuthorityConfiguration'], 'RevocationConfiguration' => ['shape' => 'RevocationConfiguration'], 'RestorableUntil' => ['shape' => 'TStamp']]], 'CertificateAuthorityConfiguration' => ['type' => 'structure', 'required' => ['KeyAlgorithm', 'SigningAlgorithm', 'Subject'], 'members' => ['KeyAlgorithm' => ['shape' => 'KeyAlgorithm'], 'SigningAlgorithm' => ['shape' => 'SigningAlgorithm'], 'Subject' => ['shape' => 'ASN1Subject']]], 'CertificateAuthorityStatus' => ['type' => 'string', 'enum' => ['CREATING', 'PENDING_CERTIFICATE', 'ACTIVE', 'DELETED', 'DISABLED', 'EXPIRED', 'FAILED']], 'CertificateAuthorityType' => ['type' => 'string', 'enum' => ['SUBORDINATE']], 'CertificateBody' => ['type' => 'string'], 'CertificateBodyBlob' => ['type' => 'blob', 'max' => 32768, 'min' => 1], 'CertificateChain' => ['type' => 'string'], 'CertificateChainBlob' => ['type' => 'blob', 'max' => 2097152, 'min' => 0], 'CertificateMismatchException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ConcurrentModificationException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'CountryCodeString' => ['type' => 'string', 'pattern' => '[A-Za-z]{2}'], 'CreateCertificateAuthorityAuditReportRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'S3BucketName', 'AuditReportResponseFormat'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'S3BucketName' => ['shape' => 'String'], 'AuditReportResponseFormat' => ['shape' => 'AuditReportResponseFormat']]], 'CreateCertificateAuthorityAuditReportResponse' => ['type' => 'structure', 'members' => ['AuditReportId' => ['shape' => 'AuditReportId'], 'S3Key' => ['shape' => 'String']]], 'CreateCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityConfiguration', 'CertificateAuthorityType'], 'members' => ['CertificateAuthorityConfiguration' => ['shape' => 'CertificateAuthorityConfiguration'], 'RevocationConfiguration' => ['shape' => 'RevocationConfiguration'], 'CertificateAuthorityType' => ['shape' => 'CertificateAuthorityType'], 'IdempotencyToken' => ['shape' => 'IdempotencyToken']]], 'CreateCertificateAuthorityResponse' => ['type' => 'structure', 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'CrlConfiguration' => ['type' => 'structure', 'required' => ['Enabled'], 'members' => ['Enabled' => ['shape' => 'Boolean', 'box' => \true], 'ExpirationInDays' => ['shape' => 'Integer1To5000', 'box' => \true], 'CustomCname' => ['shape' => 'String253'], 'S3BucketName' => ['shape' => 'String3To255']]], 'CsrBlob' => ['type' => 'blob', 'max' => 32768, 'min' => 1], 'CsrBody' => ['type' => 'string'], 'DeleteCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'PermanentDeletionTimeInDays' => ['shape' => 'PermanentDeletionTimeInDays']]], 'DescribeCertificateAuthorityAuditReportRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'AuditReportId'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'AuditReportId' => ['shape' => 'AuditReportId']]], 'DescribeCertificateAuthorityAuditReportResponse' => ['type' => 'structure', 'members' => ['AuditReportStatus' => ['shape' => 'AuditReportStatus'], 'S3BucketName' => ['shape' => 'String'], 'S3Key' => ['shape' => 'String'], 'CreatedAt' => ['shape' => 'TStamp']]], 'DescribeCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'DescribeCertificateAuthorityResponse' => ['type' => 'structure', 'members' => ['CertificateAuthority' => ['shape' => 'CertificateAuthority']]], 'DistinguishedNameQualifierString' => ['type' => 'string', 'max' => 64, 'min' => 0, 'pattern' => '[a-zA-Z0-9\'()+-.?:/= ]*'], 'FailureReason' => ['type' => 'string', 'enum' => ['REQUEST_TIMED_OUT', 'UNSUPPORTED_ALGORITHM', 'OTHER']], 'GetCertificateAuthorityCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'GetCertificateAuthorityCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain']]], 'GetCertificateAuthorityCsrRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'GetCertificateAuthorityCsrResponse' => ['type' => 'structure', 'members' => ['Csr' => ['shape' => 'CsrBody']]], 'GetCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'CertificateArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'CertificateArn' => ['shape' => 'Arn']]], 'GetCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain']]], 'IdempotencyToken' => ['type' => 'string', 'max' => 36, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u00FF]*'], 'ImportCertificateAuthorityCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Certificate', 'CertificateChain'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Certificate' => ['shape' => 'CertificateBodyBlob'], 'CertificateChain' => ['shape' => 'CertificateChainBlob']]], 'Integer1To5000' => ['type' => 'integer', 'max' => 5000, 'min' => 1], 'InvalidArgsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidArnException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidNextTokenException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidPolicyException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidStateException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidTagException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'IssueCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Csr', 'SigningAlgorithm', 'Validity'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Csr' => ['shape' => 'CsrBlob'], 'SigningAlgorithm' => ['shape' => 'SigningAlgorithm'], 'Validity' => ['shape' => 'Validity'], 'IdempotencyToken' => ['shape' => 'IdempotencyToken']]], 'IssueCertificateResponse' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'KeyAlgorithm' => ['type' => 'string', 'enum' => ['RSA_2048', 'RSA_4096', 'EC_prime256v1', 'EC_secp384r1']], 'LimitExceededException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ListCertificateAuthoritiesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListCertificateAuthoritiesResponse' => ['type' => 'structure', 'members' => ['CertificateAuthorities' => ['shape' => 'CertificateAuthorities'], 'NextToken' => ['shape' => 'NextToken']]], 'ListTagsRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListTagsResponse' => ['type' => 'structure', 'members' => ['Tags' => ['shape' => 'TagList'], 'NextToken' => ['shape' => 'NextToken']]], 'MalformedCSRException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'MalformedCertificateException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'MaxResults' => ['type' => 'integer', 'max' => 1000, 'min' => 1], 'NextToken' => ['type' => 'string', 'max' => 500, 'min' => 1], 'PermanentDeletionTimeInDays' => ['type' => 'integer', 'max' => 30, 'min' => 7], 'PositiveLong' => ['type' => 'long', 'min' => 1], 'RequestAlreadyProcessedException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'RequestFailedException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'RequestInProgressException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResourceNotFoundException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'RestoreCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'RevocationConfiguration' => ['type' => 'structure', 'members' => ['CrlConfiguration' => ['shape' => 'CrlConfiguration']]], 'RevocationReason' => ['type' => 'string', 'enum' => ['UNSPECIFIED', 'KEY_COMPROMISE', 'CERTIFICATE_AUTHORITY_COMPROMISE', 'AFFILIATION_CHANGED', 'SUPERSEDED', 'CESSATION_OF_OPERATION', 'PRIVILEGE_WITHDRAWN', 'A_A_COMPROMISE']], 'RevokeCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'CertificateSerial', 'RevocationReason'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'CertificateSerial' => ['shape' => 'String128'], 'RevocationReason' => ['shape' => 'RevocationReason']]], 'SigningAlgorithm' => ['type' => 'string', 'enum' => ['SHA256WITHECDSA', 'SHA384WITHECDSA', 'SHA512WITHECDSA', 'SHA256WITHRSA', 'SHA384WITHRSA', 'SHA512WITHRSA']], 'String' => ['type' => 'string'], 'String128' => ['type' => 'string', 'max' => 128, 'min' => 0], 'String16' => ['type' => 'string', 'max' => 16, 'min' => 0], 'String253' => ['type' => 'string', 'max' => 253, 'min' => 0], 'String3' => ['type' => 'string', 'max' => 3, 'min' => 0], 'String3To255' => ['type' => 'string', 'max' => 255, 'min' => 3], 'String40' => ['type' => 'string', 'max' => 40, 'min' => 0], 'String5' => ['type' => 'string', 'max' => 5, 'min' => 0], 'String64' => ['type' => 'string', 'max' => 64, 'min' => 0], 'TStamp' => ['type' => 'timestamp'], 'Tag' => ['type' => 'structure', 'required' => ['Key'], 'members' => ['Key' => ['shape' => 'TagKey'], 'Value' => ['shape' => 'TagValue']]], 'TagCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Tags'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '[\\p{L}\\p{Z}\\p{N}_.:\\/=+\\-@]*'], 'TagList' => ['type' => 'list', 'member' => ['shape' => 'Tag'], 'max' => 50, 'min' => 1], 'TagValue' => ['type' => 'string', 'max' => 256, 'min' => 0, 'pattern' => '[\\p{L}\\p{Z}\\p{N}_.:\\/=+\\-@]*'], 'TooManyTagsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'UntagCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Tags'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'UpdateCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'RevocationConfiguration' => ['shape' => 'RevocationConfiguration'], 'Status' => ['shape' => 'CertificateAuthorityStatus']]], 'Validity' => ['type' => 'structure', 'required' => ['Value', 'Type'], 'members' => ['Value' => ['shape' => 'PositiveLong', 'box' => \true], 'Type' => ['shape' => 'ValidityPeriodType']]], 'ValidityPeriodType' => ['type' => 'string', 'enum' => ['END_DATE', 'ABSOLUTE', 'DAYS', 'MONTHS', 'YEARS']]]];
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/acm-pca/2017-08-22/api-2.json
|
4 |
+
return ['version' => '2.0', 'metadata' => ['apiVersion' => '2017-08-22', 'endpointPrefix' => 'acm-pca', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceAbbreviation' => 'ACM-PCA', 'serviceFullName' => 'AWS Certificate Manager Private Certificate Authority', 'serviceId' => 'ACM PCA', 'signatureVersion' => 'v4', 'targetPrefix' => 'ACMPrivateCA', 'uid' => 'acm-pca-2017-08-22'], 'operations' => ['CreateCertificateAuthority' => ['name' => 'CreateCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateCertificateAuthorityRequest'], 'output' => ['shape' => 'CreateCertificateAuthorityResponse'], 'errors' => [['shape' => 'InvalidArgsException'], ['shape' => 'InvalidPolicyException'], ['shape' => 'InvalidTagException'], ['shape' => 'LimitExceededException']], 'idempotent' => \true], 'CreateCertificateAuthorityAuditReport' => ['name' => 'CreateCertificateAuthorityAuditReport', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateCertificateAuthorityAuditReportRequest'], 'output' => ['shape' => 'CreateCertificateAuthorityAuditReportResponse'], 'errors' => [['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidArgsException'], ['shape' => 'InvalidStateException']], 'idempotent' => \true], 'CreatePermission' => ['name' => 'CreatePermission', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreatePermissionRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'PermissionAlreadyExistsException'], ['shape' => 'LimitExceededException'], ['shape' => 'InvalidStateException'], ['shape' => 'RequestFailedException']]], 'DeleteCertificateAuthority' => ['name' => 'DeleteCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteCertificateAuthorityRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'DeletePermission' => ['name' => 'DeletePermission', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeletePermissionRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'RequestFailedException']]], 'DescribeCertificateAuthority' => ['name' => 'DescribeCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DescribeCertificateAuthorityRequest'], 'output' => ['shape' => 'DescribeCertificateAuthorityResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'DescribeCertificateAuthorityAuditReport' => ['name' => 'DescribeCertificateAuthorityAuditReport', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DescribeCertificateAuthorityAuditReportRequest'], 'output' => ['shape' => 'DescribeCertificateAuthorityAuditReportResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidArgsException']]], 'GetCertificate' => ['name' => 'GetCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateRequest'], 'output' => ['shape' => 'GetCertificateResponse'], 'errors' => [['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'GetCertificateAuthorityCertificate' => ['name' => 'GetCertificateAuthorityCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateAuthorityCertificateRequest'], 'output' => ['shape' => 'GetCertificateAuthorityCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException']]], 'GetCertificateAuthorityCsr' => ['name' => 'GetCertificateAuthorityCsr', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateAuthorityCsrRequest'], 'output' => ['shape' => 'GetCertificateAuthorityCsrResponse'], 'errors' => [['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'ImportCertificateAuthorityCertificate' => ['name' => 'ImportCertificateAuthorityCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ImportCertificateAuthorityCertificateRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidRequestException'], ['shape' => 'InvalidStateException'], ['shape' => 'MalformedCertificateException'], ['shape' => 'CertificateMismatchException']]], 'IssueCertificate' => ['name' => 'IssueCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'IssueCertificateRequest'], 'output' => ['shape' => 'IssueCertificateResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidArgsException'], ['shape' => 'MalformedCSRException']], 'idempotent' => \true], 'ListCertificateAuthorities' => ['name' => 'ListCertificateAuthorities', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListCertificateAuthoritiesRequest'], 'output' => ['shape' => 'ListCertificateAuthoritiesResponse'], 'errors' => [['shape' => 'InvalidNextTokenException']]], 'ListPermissions' => ['name' => 'ListPermissions', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListPermissionsRequest'], 'output' => ['shape' => 'ListPermissionsResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidNextTokenException'], ['shape' => 'InvalidStateException'], ['shape' => 'RequestFailedException']]], 'ListTags' => ['name' => 'ListTags', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListTagsRequest'], 'output' => ['shape' => 'ListTagsResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException']]], 'RestoreCertificateAuthority' => ['name' => 'RestoreCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RestoreCertificateAuthorityRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException']]], 'RevokeCertificate' => ['name' => 'RevokeCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RevokeCertificateRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidRequestException'], ['shape' => 'InvalidStateException'], ['shape' => 'LimitExceededException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'RequestAlreadyProcessedException'], ['shape' => 'RequestInProgressException'], ['shape' => 'RequestFailedException']]], 'TagCertificateAuthority' => ['name' => 'TagCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'TagCertificateAuthorityRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidTagException'], ['shape' => 'TooManyTagsException']]], 'UntagCertificateAuthority' => ['name' => 'UntagCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UntagCertificateAuthorityRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidTagException']]], 'UpdateCertificateAuthority' => ['name' => 'UpdateCertificateAuthority', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateCertificateAuthorityRequest'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArgsException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidPolicyException']]]], 'shapes' => ['ASN1Subject' => ['type' => 'structure', 'members' => ['Country' => ['shape' => 'CountryCodeString'], 'Organization' => ['shape' => 'String64'], 'OrganizationalUnit' => ['shape' => 'String64'], 'DistinguishedNameQualifier' => ['shape' => 'DistinguishedNameQualifierString'], 'State' => ['shape' => 'String128'], 'CommonName' => ['shape' => 'String64'], 'SerialNumber' => ['shape' => 'String64'], 'Locality' => ['shape' => 'String128'], 'Title' => ['shape' => 'String64'], 'Surname' => ['shape' => 'String40'], 'GivenName' => ['shape' => 'String16'], 'Initials' => ['shape' => 'String5'], 'Pseudonym' => ['shape' => 'String128'], 'GenerationQualifier' => ['shape' => 'String3']]], 'AccountId' => ['type' => 'string', 'max' => 12, 'min' => 12, 'pattern' => '[0-9]+'], 'ActionList' => ['type' => 'list', 'member' => ['shape' => 'ActionType'], 'max' => 3, 'min' => 1], 'ActionType' => ['type' => 'string', 'enum' => ['IssueCertificate', 'GetCertificate', 'ListPermissions']], 'Arn' => ['type' => 'string', 'max' => 200, 'min' => 5, 'pattern' => 'arn:[\\w+=/,.@-]+:[\\w+=/,.@-]+:[\\w+=/,.@-]*:[0-9]*:[\\w+=,.@-]+(/[\\w+=/,.@-]+)*'], 'AuditReportId' => ['type' => 'string', 'max' => 36, 'min' => 36, 'pattern' => '[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}'], 'AuditReportResponseFormat' => ['type' => 'string', 'enum' => ['JSON', 'CSV']], 'AuditReportStatus' => ['type' => 'string', 'enum' => ['CREATING', 'SUCCESS', 'FAILED']], 'Boolean' => ['type' => 'boolean'], 'CertificateAuthorities' => ['type' => 'list', 'member' => ['shape' => 'CertificateAuthority']], 'CertificateAuthority' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'CreatedAt' => ['shape' => 'TStamp'], 'LastStateChangeAt' => ['shape' => 'TStamp'], 'Type' => ['shape' => 'CertificateAuthorityType'], 'Serial' => ['shape' => 'String'], 'Status' => ['shape' => 'CertificateAuthorityStatus'], 'NotBefore' => ['shape' => 'TStamp'], 'NotAfter' => ['shape' => 'TStamp'], 'FailureReason' => ['shape' => 'FailureReason'], 'CertificateAuthorityConfiguration' => ['shape' => 'CertificateAuthorityConfiguration'], 'RevocationConfiguration' => ['shape' => 'RevocationConfiguration'], 'RestorableUntil' => ['shape' => 'TStamp']]], 'CertificateAuthorityConfiguration' => ['type' => 'structure', 'required' => ['KeyAlgorithm', 'SigningAlgorithm', 'Subject'], 'members' => ['KeyAlgorithm' => ['shape' => 'KeyAlgorithm'], 'SigningAlgorithm' => ['shape' => 'SigningAlgorithm'], 'Subject' => ['shape' => 'ASN1Subject']]], 'CertificateAuthorityStatus' => ['type' => 'string', 'enum' => ['CREATING', 'PENDING_CERTIFICATE', 'ACTIVE', 'DELETED', 'DISABLED', 'EXPIRED', 'FAILED']], 'CertificateAuthorityType' => ['type' => 'string', 'enum' => ['ROOT', 'SUBORDINATE']], 'CertificateBody' => ['type' => 'string'], 'CertificateBodyBlob' => ['type' => 'blob', 'max' => 32768, 'min' => 1], 'CertificateChain' => ['type' => 'string'], 'CertificateChainBlob' => ['type' => 'blob', 'max' => 2097152, 'min' => 0], 'CertificateMismatchException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ConcurrentModificationException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'CountryCodeString' => ['type' => 'string', 'pattern' => '[A-Za-z]{2}'], 'CreateCertificateAuthorityAuditReportRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'S3BucketName', 'AuditReportResponseFormat'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'S3BucketName' => ['shape' => 'String'], 'AuditReportResponseFormat' => ['shape' => 'AuditReportResponseFormat']]], 'CreateCertificateAuthorityAuditReportResponse' => ['type' => 'structure', 'members' => ['AuditReportId' => ['shape' => 'AuditReportId'], 'S3Key' => ['shape' => 'String']]], 'CreateCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityConfiguration', 'CertificateAuthorityType'], 'members' => ['CertificateAuthorityConfiguration' => ['shape' => 'CertificateAuthorityConfiguration'], 'RevocationConfiguration' => ['shape' => 'RevocationConfiguration'], 'CertificateAuthorityType' => ['shape' => 'CertificateAuthorityType'], 'IdempotencyToken' => ['shape' => 'IdempotencyToken'], 'Tags' => ['shape' => 'TagList']]], 'CreateCertificateAuthorityResponse' => ['type' => 'structure', 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'CreatePermissionRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Principal', 'Actions'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Principal' => ['shape' => 'Principal'], 'SourceAccount' => ['shape' => 'AccountId'], 'Actions' => ['shape' => 'ActionList']]], 'CrlConfiguration' => ['type' => 'structure', 'required' => ['Enabled'], 'members' => ['Enabled' => ['shape' => 'Boolean', 'box' => \true], 'ExpirationInDays' => ['shape' => 'Integer1To5000', 'box' => \true], 'CustomCname' => ['shape' => 'String253'], 'S3BucketName' => ['shape' => 'String3To255']]], 'CsrBlob' => ['type' => 'blob', 'max' => 32768, 'min' => 1], 'CsrBody' => ['type' => 'string'], 'DeleteCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'PermanentDeletionTimeInDays' => ['shape' => 'PermanentDeletionTimeInDays']]], 'DeletePermissionRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Principal'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Principal' => ['shape' => 'Principal'], 'SourceAccount' => ['shape' => 'AccountId']]], 'DescribeCertificateAuthorityAuditReportRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'AuditReportId'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'AuditReportId' => ['shape' => 'AuditReportId']]], 'DescribeCertificateAuthorityAuditReportResponse' => ['type' => 'structure', 'members' => ['AuditReportStatus' => ['shape' => 'AuditReportStatus'], 'S3BucketName' => ['shape' => 'String'], 'S3Key' => ['shape' => 'String'], 'CreatedAt' => ['shape' => 'TStamp']]], 'DescribeCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'DescribeCertificateAuthorityResponse' => ['type' => 'structure', 'members' => ['CertificateAuthority' => ['shape' => 'CertificateAuthority']]], 'DistinguishedNameQualifierString' => ['type' => 'string', 'max' => 64, 'min' => 0, 'pattern' => '[a-zA-Z0-9\'()+-.?:/= ]*'], 'FailureReason' => ['type' => 'string', 'enum' => ['REQUEST_TIMED_OUT', 'UNSUPPORTED_ALGORITHM', 'OTHER']], 'GetCertificateAuthorityCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'GetCertificateAuthorityCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain']]], 'GetCertificateAuthorityCsrRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'GetCertificateAuthorityCsrResponse' => ['type' => 'structure', 'members' => ['Csr' => ['shape' => 'CsrBody']]], 'GetCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'CertificateArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'CertificateArn' => ['shape' => 'Arn']]], 'GetCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain']]], 'IdempotencyToken' => ['type' => 'string', 'max' => 36, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u00FF]*'], 'ImportCertificateAuthorityCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Certificate'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Certificate' => ['shape' => 'CertificateBodyBlob'], 'CertificateChain' => ['shape' => 'CertificateChainBlob']]], 'Integer1To5000' => ['type' => 'integer', 'max' => 5000, 'min' => 1], 'InvalidArgsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidArnException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidNextTokenException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidPolicyException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidRequestException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidStateException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidTagException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'IssueCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Csr', 'SigningAlgorithm', 'Validity'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Csr' => ['shape' => 'CsrBlob'], 'SigningAlgorithm' => ['shape' => 'SigningAlgorithm'], 'TemplateArn' => ['shape' => 'Arn'], 'Validity' => ['shape' => 'Validity'], 'IdempotencyToken' => ['shape' => 'IdempotencyToken']]], 'IssueCertificateResponse' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'KeyAlgorithm' => ['type' => 'string', 'enum' => ['RSA_2048', 'RSA_4096', 'EC_prime256v1', 'EC_secp384r1']], 'LimitExceededException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ListCertificateAuthoritiesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListCertificateAuthoritiesResponse' => ['type' => 'structure', 'members' => ['CertificateAuthorities' => ['shape' => 'CertificateAuthorities'], 'NextToken' => ['shape' => 'NextToken']]], 'ListPermissionsRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListPermissionsResponse' => ['type' => 'structure', 'members' => ['Permissions' => ['shape' => 'PermissionList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListTagsRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListTagsResponse' => ['type' => 'structure', 'members' => ['Tags' => ['shape' => 'TagList'], 'NextToken' => ['shape' => 'NextToken']]], 'MalformedCSRException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'MalformedCertificateException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'MaxResults' => ['type' => 'integer', 'max' => 1000, 'min' => 1], 'NextToken' => ['type' => 'string', 'max' => 500, 'min' => 1], 'PermanentDeletionTimeInDays' => ['type' => 'integer', 'max' => 30, 'min' => 7], 'Permission' => ['type' => 'structure', 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'CreatedAt' => ['shape' => 'TStamp'], 'Principal' => ['shape' => 'String'], 'SourceAccount' => ['shape' => 'String'], 'Actions' => ['shape' => 'ActionList'], 'Policy' => ['shape' => 'String']]], 'PermissionAlreadyExistsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'PermissionList' => ['type' => 'list', 'member' => ['shape' => 'Permission'], 'min' => 0], 'PositiveLong' => ['type' => 'long', 'min' => 1], 'Principal' => ['type' => 'string', 'max' => 128, 'min' => 0, 'pattern' => '^[^*]+$'], 'RequestAlreadyProcessedException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'RequestFailedException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'RequestInProgressException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResourceNotFoundException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'RestoreCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn']]], 'RevocationConfiguration' => ['type' => 'structure', 'members' => ['CrlConfiguration' => ['shape' => 'CrlConfiguration']]], 'RevocationReason' => ['type' => 'string', 'enum' => ['UNSPECIFIED', 'KEY_COMPROMISE', 'CERTIFICATE_AUTHORITY_COMPROMISE', 'AFFILIATION_CHANGED', 'SUPERSEDED', 'CESSATION_OF_OPERATION', 'PRIVILEGE_WITHDRAWN', 'A_A_COMPROMISE']], 'RevokeCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'CertificateSerial', 'RevocationReason'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'CertificateSerial' => ['shape' => 'String128'], 'RevocationReason' => ['shape' => 'RevocationReason']]], 'SigningAlgorithm' => ['type' => 'string', 'enum' => ['SHA256WITHECDSA', 'SHA384WITHECDSA', 'SHA512WITHECDSA', 'SHA256WITHRSA', 'SHA384WITHRSA', 'SHA512WITHRSA']], 'String' => ['type' => 'string'], 'String128' => ['type' => 'string', 'max' => 128, 'min' => 0], 'String16' => ['type' => 'string', 'max' => 16, 'min' => 0], 'String253' => ['type' => 'string', 'max' => 253, 'min' => 0], 'String3' => ['type' => 'string', 'max' => 3, 'min' => 0], 'String3To255' => ['type' => 'string', 'max' => 255, 'min' => 3], 'String40' => ['type' => 'string', 'max' => 40, 'min' => 0], 'String5' => ['type' => 'string', 'max' => 5, 'min' => 0], 'String64' => ['type' => 'string', 'max' => 64, 'min' => 0], 'TStamp' => ['type' => 'timestamp'], 'Tag' => ['type' => 'structure', 'required' => ['Key'], 'members' => ['Key' => ['shape' => 'TagKey'], 'Value' => ['shape' => 'TagValue']]], 'TagCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Tags'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$'], 'TagList' => ['type' => 'list', 'member' => ['shape' => 'Tag'], 'max' => 50, 'min' => 1], 'TagValue' => ['type' => 'string', 'max' => 256, 'min' => 0, 'pattern' => '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$'], 'TooManyTagsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'UntagCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn', 'Tags'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'UpdateCertificateAuthorityRequest' => ['type' => 'structure', 'required' => ['CertificateAuthorityArn'], 'members' => ['CertificateAuthorityArn' => ['shape' => 'Arn'], 'RevocationConfiguration' => ['shape' => 'RevocationConfiguration'], 'Status' => ['shape' => 'CertificateAuthorityStatus']]], 'Validity' => ['type' => 'structure', 'required' => ['Value', 'Type'], 'members' => ['Value' => ['shape' => 'PositiveLong', 'box' => \true], 'Type' => ['shape' => 'ValidityPeriodType']]], 'ValidityPeriodType' => ['type' => 'string', 'enum' => ['END_DATE', 'ABSOLUTE', 'DAYS', 'MONTHS', 'YEARS']]]];
|
@@ -1,4 +1,4 @@
|
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/acm-pca/2017-08-22/paginators-1.json
|
4 |
-
return ['pagination' => ['ListCertificateAuthorities' => ['input_token' => 'NextToken', 'limit_key' => 'MaxResults', 'output_token' => 'NextToken', 'result_key' => 'CertificateAuthorities']]];
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/acm-pca/2017-08-22/paginators-1.json
|
4 |
+
return ['pagination' => ['ListCertificateAuthorities' => ['input_token' => 'NextToken', 'limit_key' => 'MaxResults', 'output_token' => 'NextToken', 'result_key' => 'CertificateAuthorities'], 'ListPermissions' => ['input_token' => 'NextToken', 'limit_key' => 'MaxResults', 'output_token' => 'NextToken', 'result_key' => 'Permissions'], 'ListTags' => ['input_token' => 'NextToken', 'limit_key' => 'MaxResults', 'output_token' => 'NextToken', 'result_key' => 'Tags']]];
|
@@ -1,4 +1,4 @@
|
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/acm-pca/2017-08-22/waiters-2.json
|
4 |
-
return ['version' => 2, 'waiters' => ['CertificateAuthorityCSRCreated' => ['description' => 'Wait until a Certificate Authority CSR is created', 'operation' => 'GetCertificateAuthorityCsr', 'delay' => 3, 'maxAttempts' => 60, 'acceptors' => [['state' => 'success', 'matcher' => 'status', 'expected' => 200], ['state' => 'retry', 'matcher' => 'error', 'expected' => 'RequestInProgressException']]], 'CertificateIssued' => ['description' => 'Wait until a certificate is issued', 'operation' => 'GetCertificate', 'delay' => 3, 'maxAttempts' => 60, 'acceptors' => [['state' => 'success', 'matcher' => 'status', 'expected' => 200], ['state' => 'retry', 'matcher' => 'error', 'expected' => 'RequestInProgressException']]], 'AuditReportCreated' => ['description' => 'Wait until a Audit Report is created', 'operation' => 'DescribeCertificateAuthorityAuditReport', 'delay' => 3, 'maxAttempts' => 60, 'acceptors' => [['state' => 'success', 'matcher' => 'path', 'argument' => 'AuditReportStatus', 'expected' => 'SUCCESS']]]]];
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/acm-pca/2017-08-22/waiters-2.json
|
4 |
+
return ['version' => 2, 'waiters' => ['CertificateAuthorityCSRCreated' => ['description' => 'Wait until a Certificate Authority CSR is created', 'operation' => 'GetCertificateAuthorityCsr', 'delay' => 3, 'maxAttempts' => 60, 'acceptors' => [['state' => 'success', 'matcher' => 'status', 'expected' => 200], ['state' => 'retry', 'matcher' => 'error', 'expected' => 'RequestInProgressException']]], 'CertificateIssued' => ['description' => 'Wait until a certificate is issued', 'operation' => 'GetCertificate', 'delay' => 3, 'maxAttempts' => 60, 'acceptors' => [['state' => 'success', 'matcher' => 'status', 'expected' => 200], ['state' => 'retry', 'matcher' => 'error', 'expected' => 'RequestInProgressException']]], 'AuditReportCreated' => ['description' => 'Wait until a Audit Report is created', 'operation' => 'DescribeCertificateAuthorityAuditReport', 'delay' => 3, 'maxAttempts' => 60, 'acceptors' => [['state' => 'success', 'matcher' => 'path', 'argument' => 'AuditReportStatus', 'expected' => 'SUCCESS'], ['state' => 'failure', 'matcher' => 'path', 'argument' => 'AuditReportStatus', 'expected' => 'FAILED']]]]];
|
@@ -1,4 +1,4 @@
|
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/acm/2015-12-08/api-2.json
|
4 |
-
return ['version' => '2.0', 'metadata' => ['apiVersion' => '2015-12-08', 'endpointPrefix' => 'acm', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceAbbreviation' => 'ACM', 'serviceFullName' => 'AWS Certificate Manager', 'serviceId' => 'ACM', 'signatureVersion' => 'v4', 'targetPrefix' => 'CertificateManager', 'uid' => 'acm-2015-12-08'], 'operations' => ['AddTagsToCertificate' => ['name' => 'AddTagsToCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AddTagsToCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidTagException'], ['shape' => 'TooManyTagsException']]], 'DeleteCertificate' => ['name' => 'DeleteCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ResourceInUseException'], ['shape' => 'InvalidArnException']]], 'DescribeCertificate' => ['name' => 'DescribeCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DescribeCertificateRequest'], 'output' => ['shape' => 'DescribeCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'ExportCertificate' => ['name' => 'ExportCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ExportCertificateRequest'], 'output' => ['shape' => 'ExportCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'RequestInProgressException'], ['shape' => 'InvalidArnException']]], 'GetCertificate' => ['name' => 'GetCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateRequest'], 'output' => ['shape' => 'GetCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'RequestInProgressException'], ['shape' => 'InvalidArnException']]], 'ImportCertificate' => ['name' => 'ImportCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ImportCertificateRequest'], 'output' => ['shape' => 'ImportCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'LimitExceededException']]], 'ListCertificates' => ['name' => 'ListCertificates', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListCertificatesRequest'], 'output' => ['shape' => 'ListCertificatesResponse']], 'ListTagsForCertificate' => ['name' => 'ListTagsForCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListTagsForCertificateRequest'], 'output' => ['shape' => 'ListTagsForCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'RemoveTagsFromCertificate' => ['name' => 'RemoveTagsFromCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RemoveTagsFromCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidTagException']]], 'RequestCertificate' => ['name' => 'RequestCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RequestCertificateRequest'], 'output' => ['shape' => 'RequestCertificateResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'InvalidDomainValidationOptionsException'], ['shape' => 'InvalidArnException']]], 'ResendValidationEmail' => ['name' => 'ResendValidationEmail', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ResendValidationEmailRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidDomainValidationOptionsException']]], 'UpdateCertificateOptions' => ['name' => 'UpdateCertificateOptions', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateCertificateOptionsRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'LimitExceededException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException']]]], 'shapes' => ['AddTagsToCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Tags'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'Arn' => ['type' => 'string', 'max' => 2048, 'min' => 20, 'pattern' => 'arn:[\\w+=/,.@-]+:[\\w+=/,.@-]+:[\\w+=/,.@-]*:[0-9]+:[\\w+=,.@-]+(/[\\w+=,.@-]+)*'], 'CertificateBody' => ['type' => 'string', 'max' => 32768, 'min' => 1, 'pattern' => '-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}(\\u000D?\\u000A)?'], 'CertificateBodyBlob' => ['type' => 'blob', 'max' => 32768, 'min' => 1], 'CertificateChain' => ['type' => 'string', 'max' => 2097152, 'min' => 1, 'pattern' => '(-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}\\u000D?\\u000A)*-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}(\\u000D?\\u000A)?'], 'CertificateChainBlob' => ['type' => 'blob', 'max' => 2097152, 'min' => 1], 'CertificateDetail' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'DomainName' => ['shape' => 'DomainNameString'], 'SubjectAlternativeNames' => ['shape' => 'DomainList'], 'DomainValidationOptions' => ['shape' => 'DomainValidationList'], 'Serial' => ['shape' => 'String'], 'Subject' => ['shape' => 'String'], 'Issuer' => ['shape' => 'String'], 'CreatedAt' => ['shape' => 'TStamp'], 'IssuedAt' => ['shape' => 'TStamp'], 'ImportedAt' => ['shape' => 'TStamp'], 'Status' => ['shape' => 'CertificateStatus'], 'RevokedAt' => ['shape' => 'TStamp'], 'RevocationReason' => ['shape' => 'RevocationReason'], 'NotBefore' => ['shape' => 'TStamp'], 'NotAfter' => ['shape' => 'TStamp'], 'KeyAlgorithm' => ['shape' => 'KeyAlgorithm'], 'SignatureAlgorithm' => ['shape' => 'String'], 'InUseBy' => ['shape' => 'InUseList'], 'FailureReason' => ['shape' => 'FailureReason'], 'Type' => ['shape' => 'CertificateType'], 'RenewalSummary' => ['shape' => 'RenewalSummary'], 'KeyUsages' => ['shape' => 'KeyUsageList'], 'ExtendedKeyUsages' => ['shape' => 'ExtendedKeyUsageList'], 'CertificateAuthorityArn' => ['shape' => 'Arn'], 'RenewalEligibility' => ['shape' => 'RenewalEligibility'], 'Options' => ['shape' => 'CertificateOptions']]], 'CertificateOptions' => ['type' => 'structure', 'members' => ['CertificateTransparencyLoggingPreference' => ['shape' => 'CertificateTransparencyLoggingPreference']]], 'CertificateStatus' => ['type' => 'string', 'enum' => ['PENDING_VALIDATION', 'ISSUED', 'INACTIVE', 'EXPIRED', 'VALIDATION_TIMED_OUT', 'REVOKED', 'FAILED']], 'CertificateStatuses' => ['type' => 'list', 'member' => ['shape' => 'CertificateStatus']], 'CertificateSummary' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'DomainName' => ['shape' => 'DomainNameString']]], 'CertificateSummaryList' => ['type' => 'list', 'member' => ['shape' => 'CertificateSummary']], 'CertificateTransparencyLoggingPreference' => ['type' => 'string', 'enum' => ['ENABLED', 'DISABLED']], 'CertificateType' => ['type' => 'string', 'enum' => ['IMPORTED', 'AMAZON_ISSUED', 'PRIVATE']], 'DeleteCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'DescribeCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'DescribeCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateDetail']]], 'DomainList' => ['type' => 'list', 'member' => ['shape' => 'DomainNameString'], 'max' => 100, 'min' => 1], 'DomainNameString' => ['type' => 'string', 'max' => 253, 'min' => 1, 'pattern' => '^(\\*\\.)?(((?!-)[A-Za-z0-9-]{0,62}[A-Za-z0-9])\\.)+((?!-)[A-Za-z0-9-]{1,62}[A-Za-z0-9])$'], 'DomainStatus' => ['type' => 'string', 'enum' => ['PENDING_VALIDATION', 'SUCCESS', 'FAILED']], 'DomainValidation' => ['type' => 'structure', 'required' => ['DomainName'], 'members' => ['DomainName' => ['shape' => 'DomainNameString'], 'ValidationEmails' => ['shape' => 'ValidationEmailList'], 'ValidationDomain' => ['shape' => 'DomainNameString'], 'ValidationStatus' => ['shape' => 'DomainStatus'], 'ResourceRecord' => ['shape' => 'ResourceRecord'], 'ValidationMethod' => ['shape' => 'ValidationMethod']]], 'DomainValidationList' => ['type' => 'list', 'member' => ['shape' => 'DomainValidation'], 'max' => 1000, 'min' => 1], 'DomainValidationOption' => ['type' => 'structure', 'required' => ['DomainName', 'ValidationDomain'], 'members' => ['DomainName' => ['shape' => 'DomainNameString'], 'ValidationDomain' => ['shape' => 'DomainNameString']]], 'DomainValidationOptionList' => ['type' => 'list', 'member' => ['shape' => 'DomainValidationOption'], 'max' => 100, 'min' => 1], 'ExportCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Passphrase'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Passphrase' => ['shape' => 'PassphraseBlob']]], 'ExportCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain'], 'PrivateKey' => ['shape' => 'PrivateKey']]], 'ExtendedKeyUsage' => ['type' => 'structure', 'members' => ['Name' => ['shape' => 'ExtendedKeyUsageName'], 'OID' => ['shape' => 'String']]], 'ExtendedKeyUsageFilterList' => ['type' => 'list', 'member' => ['shape' => 'ExtendedKeyUsageName']], 'ExtendedKeyUsageList' => ['type' => 'list', 'member' => ['shape' => 'ExtendedKeyUsage']], 'ExtendedKeyUsageName' => ['type' => 'string', 'enum' => ['TLS_WEB_SERVER_AUTHENTICATION', 'TLS_WEB_CLIENT_AUTHENTICATION', 'CODE_SIGNING', 'EMAIL_PROTECTION', 'TIME_STAMPING', 'OCSP_SIGNING', 'IPSEC_END_SYSTEM', 'IPSEC_TUNNEL', 'IPSEC_USER', 'ANY', 'NONE', 'CUSTOM']], 'FailureReason' => ['type' => 'string', 'enum' => ['NO_AVAILABLE_CONTACTS', 'ADDITIONAL_VERIFICATION_REQUIRED', 'DOMAIN_NOT_ALLOWED', 'INVALID_PUBLIC_DOMAIN', 'CAA_ERROR', 'PCA_LIMIT_EXCEEDED', 'PCA_INVALID_ARN', 'PCA_INVALID_STATE', 'PCA_REQUEST_FAILED', 'PCA_RESOURCE_NOT_FOUND', 'PCA_INVALID_ARGS', 'OTHER']], 'Filters' => ['type' => 'structure', 'members' => ['extendedKeyUsage' => ['shape' => 'ExtendedKeyUsageFilterList'], 'keyUsage' => ['shape' => 'KeyUsageFilterList'], 'keyTypes' => ['shape' => 'KeyAlgorithmList']]], 'GetCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'GetCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain']]], 'IdempotencyToken' => ['type' => 'string', 'max' => 32, 'min' => 1, 'pattern' => '\\w+'], 'ImportCertificateRequest' => ['type' => 'structure', 'required' => ['Certificate', 'PrivateKey'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Certificate' => ['shape' => 'CertificateBodyBlob'], 'PrivateKey' => ['shape' => 'PrivateKeyBlob'], 'CertificateChain' => ['shape' => 'CertificateChainBlob']]], 'ImportCertificateResponse' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'InUseList' => ['type' => 'list', 'member' => ['shape' => 'String']], 'InvalidArnException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidDomainValidationOptionsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidStateException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidTagException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'KeyAlgorithm' => ['type' => 'string', 'enum' => ['RSA_2048', 'RSA_1024', 'RSA_4096', 'EC_prime256v1', 'EC_secp384r1', 'EC_secp521r1']], 'KeyAlgorithmList' => ['type' => 'list', 'member' => ['shape' => 'KeyAlgorithm']], 'KeyUsage' => ['type' => 'structure', 'members' => ['Name' => ['shape' => 'KeyUsageName']]], 'KeyUsageFilterList' => ['type' => 'list', 'member' => ['shape' => 'KeyUsageName']], 'KeyUsageList' => ['type' => 'list', 'member' => ['shape' => 'KeyUsage']], 'KeyUsageName' => ['type' => 'string', 'enum' => ['DIGITAL_SIGNATURE', 'NON_REPUDIATION', 'KEY_ENCIPHERMENT', 'DATA_ENCIPHERMENT', 'KEY_AGREEMENT', 'CERTIFICATE_SIGNING', 'CRL_SIGNING', 'ENCIPHER_ONLY', 'DECIPHER_ONLY', 'ANY', 'CUSTOM']], 'LimitExceededException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ListCertificatesRequest' => ['type' => 'structure', 'members' => ['CertificateStatuses' => ['shape' => 'CertificateStatuses'], 'Includes' => ['shape' => 'Filters'], 'NextToken' => ['shape' => 'NextToken'], 'MaxItems' => ['shape' => 'MaxItems']]], 'ListCertificatesResponse' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'CertificateSummaryList' => ['shape' => 'CertificateSummaryList']]], 'ListTagsForCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'ListTagsForCertificateResponse' => ['type' => 'structure', 'members' => ['Tags' => ['shape' => 'TagList']]], 'MaxItems' => ['type' => 'integer', 'max' => 1000, 'min' => 1], 'NextToken' => ['type' => 'string', 'max' => 320, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u00FF]*'], 'PassphraseBlob' => ['type' => 'blob', 'max' => 128, 'min' => 4, 'sensitive' => \true], 'PrivateKey' => ['type' => 'string', 'max' => 524288, 'min' => 1, 'pattern' => '-{5}BEGIN PRIVATE KEY-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END PRIVATE KEY-{5}(\\u000D?\\u000A)?', 'sensitive' => \true], 'PrivateKeyBlob' => ['type' => 'blob', 'max' => 524288, 'min' => 1, 'sensitive' => \true], 'RecordType' => ['type' => 'string', 'enum' => ['CNAME']], 'RemoveTagsFromCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Tags'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'RenewalEligibility' => ['type' => 'string', 'enum' => ['ELIGIBLE', 'INELIGIBLE']], 'RenewalStatus' => ['type' => 'string', 'enum' => ['PENDING_AUTO_RENEWAL', 'PENDING_VALIDATION', 'SUCCESS', 'FAILED']], 'RenewalSummary' => ['type' => 'structure', 'required' => ['RenewalStatus', 'DomainValidationOptions'], 'members' => ['RenewalStatus' => ['shape' => 'RenewalStatus'], 'DomainValidationOptions' => ['shape' => 'DomainValidationList']]], 'RequestCertificateRequest' => ['type' => 'structure', 'required' => ['DomainName'], 'members' => ['DomainName' => ['shape' => 'DomainNameString'], 'ValidationMethod' => ['shape' => 'ValidationMethod'], 'SubjectAlternativeNames' => ['shape' => 'DomainList'], 'IdempotencyToken' => ['shape' => 'IdempotencyToken'], 'DomainValidationOptions' => ['shape' => 'DomainValidationOptionList'], 'Options' => ['shape' => 'CertificateOptions'], 'CertificateAuthorityArn' => ['shape' => 'Arn']]], 'RequestCertificateResponse' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'RequestInProgressException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResendValidationEmailRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Domain', 'ValidationDomain'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Domain' => ['shape' => 'DomainNameString'], 'ValidationDomain' => ['shape' => 'DomainNameString']]], 'ResourceInUseException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResourceNotFoundException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResourceRecord' => ['type' => 'structure', 'required' => ['Name', 'Type', 'Value'], 'members' => ['Name' => ['shape' => 'String'], 'Type' => ['shape' => 'RecordType'], 'Value' => ['shape' => 'String']]], 'RevocationReason' => ['type' => 'string', 'enum' => ['UNSPECIFIED', 'KEY_COMPROMISE', 'CA_COMPROMISE', 'AFFILIATION_CHANGED', 'SUPERCEDED', 'CESSATION_OF_OPERATION', 'CERTIFICATE_HOLD', 'REMOVE_FROM_CRL', 'PRIVILEGE_WITHDRAWN', 'A_A_COMPROMISE']], 'String' => ['type' => 'string'], 'TStamp' => ['type' => 'timestamp'], 'Tag' => ['type' => 'structure', 'required' => ['Key'], 'members' => ['Key' => ['shape' => 'TagKey'], 'Value' => ['shape' => 'TagValue']]], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '[\\p{L}\\p{Z}\\p{N}_.:\\/=+\\-@]*'], 'TagList' => ['type' => 'list', 'member' => ['shape' => 'Tag'], 'max' => 50, 'min' => 1], 'TagValue' => ['type' => 'string', 'max' => 256, 'min' => 0, 'pattern' => '[\\p{L}\\p{Z}\\p{N}_.:\\/=+\\-@]*'], 'TooManyTagsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'UpdateCertificateOptionsRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Options'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Options' => ['shape' => 'CertificateOptions']]], 'ValidationEmailList' => ['type' => 'list', 'member' => ['shape' => 'String']], 'ValidationMethod' => ['type' => 'string', 'enum' => ['EMAIL', 'DNS']]]];
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/acm/2015-12-08/api-2.json
|
4 |
+
return ['version' => '2.0', 'metadata' => ['apiVersion' => '2015-12-08', 'endpointPrefix' => 'acm', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceAbbreviation' => 'ACM', 'serviceFullName' => 'AWS Certificate Manager', 'serviceId' => 'ACM', 'signatureVersion' => 'v4', 'targetPrefix' => 'CertificateManager', 'uid' => 'acm-2015-12-08'], 'operations' => ['AddTagsToCertificate' => ['name' => 'AddTagsToCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AddTagsToCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidTagException'], ['shape' => 'TooManyTagsException'], ['shape' => 'TagPolicyException'], ['shape' => 'InvalidParameterException']]], 'DeleteCertificate' => ['name' => 'DeleteCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'ResourceInUseException'], ['shape' => 'InvalidArnException']]], 'DescribeCertificate' => ['name' => 'DescribeCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DescribeCertificateRequest'], 'output' => ['shape' => 'DescribeCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'ExportCertificate' => ['name' => 'ExportCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ExportCertificateRequest'], 'output' => ['shape' => 'ExportCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'RequestInProgressException'], ['shape' => 'InvalidArnException']]], 'GetCertificate' => ['name' => 'GetCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetCertificateRequest'], 'output' => ['shape' => 'GetCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'RequestInProgressException'], ['shape' => 'InvalidArnException']]], 'ImportCertificate' => ['name' => 'ImportCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ImportCertificateRequest'], 'output' => ['shape' => 'ImportCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'LimitExceededException'], ['shape' => 'InvalidTagException'], ['shape' => 'TooManyTagsException'], ['shape' => 'TagPolicyException'], ['shape' => 'InvalidParameterException']]], 'ListCertificates' => ['name' => 'ListCertificates', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListCertificatesRequest'], 'output' => ['shape' => 'ListCertificatesResponse'], 'errors' => [['shape' => 'InvalidArgsException']]], 'ListTagsForCertificate' => ['name' => 'ListTagsForCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListTagsForCertificateRequest'], 'output' => ['shape' => 'ListTagsForCertificateResponse'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'RemoveTagsFromCertificate' => ['name' => 'RemoveTagsFromCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RemoveTagsFromCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidTagException'], ['shape' => 'TagPolicyException'], ['shape' => 'InvalidParameterException']]], 'RenewCertificate' => ['name' => 'RenewCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RenewCertificateRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidArnException']]], 'RequestCertificate' => ['name' => 'RequestCertificate', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RequestCertificateRequest'], 'output' => ['shape' => 'RequestCertificateResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'InvalidDomainValidationOptionsException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidTagException'], ['shape' => 'TooManyTagsException'], ['shape' => 'TagPolicyException'], ['shape' => 'InvalidParameterException']]], 'ResendValidationEmail' => ['name' => 'ResendValidationEmail', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ResendValidationEmailRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException'], ['shape' => 'InvalidDomainValidationOptionsException']]], 'UpdateCertificateOptions' => ['name' => 'UpdateCertificateOptions', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateCertificateOptionsRequest'], 'errors' => [['shape' => 'ResourceNotFoundException'], ['shape' => 'LimitExceededException'], ['shape' => 'InvalidStateException'], ['shape' => 'InvalidArnException']]]], 'shapes' => ['AddTagsToCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Tags'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'Arn' => ['type' => 'string', 'max' => 2048, 'min' => 20, 'pattern' => 'arn:[\\w+=/,.@-]+:[\\w+=/,.@-]+:[\\w+=/,.@-]*:[0-9]+:[\\w+=,.@-]+(/[\\w+=,.@-]+)*'], 'CertificateBody' => ['type' => 'string', 'max' => 32768, 'min' => 1, 'pattern' => '-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}(\\u000D?\\u000A)?'], 'CertificateBodyBlob' => ['type' => 'blob', 'max' => 32768, 'min' => 1], 'CertificateChain' => ['type' => 'string', 'max' => 2097152, 'min' => 1, 'pattern' => '(-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}\\u000D?\\u000A)*-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}(\\u000D?\\u000A)?'], 'CertificateChainBlob' => ['type' => 'blob', 'max' => 2097152, 'min' => 1], 'CertificateDetail' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'DomainName' => ['shape' => 'DomainNameString'], 'SubjectAlternativeNames' => ['shape' => 'DomainList'], 'DomainValidationOptions' => ['shape' => 'DomainValidationList'], 'Serial' => ['shape' => 'String'], 'Subject' => ['shape' => 'String'], 'Issuer' => ['shape' => 'String'], 'CreatedAt' => ['shape' => 'TStamp'], 'IssuedAt' => ['shape' => 'TStamp'], 'ImportedAt' => ['shape' => 'TStamp'], 'Status' => ['shape' => 'CertificateStatus'], 'RevokedAt' => ['shape' => 'TStamp'], 'RevocationReason' => ['shape' => 'RevocationReason'], 'NotBefore' => ['shape' => 'TStamp'], 'NotAfter' => ['shape' => 'TStamp'], 'KeyAlgorithm' => ['shape' => 'KeyAlgorithm'], 'SignatureAlgorithm' => ['shape' => 'String'], 'InUseBy' => ['shape' => 'InUseList'], 'FailureReason' => ['shape' => 'FailureReason'], 'Type' => ['shape' => 'CertificateType'], 'RenewalSummary' => ['shape' => 'RenewalSummary'], 'KeyUsages' => ['shape' => 'KeyUsageList'], 'ExtendedKeyUsages' => ['shape' => 'ExtendedKeyUsageList'], 'CertificateAuthorityArn' => ['shape' => 'Arn'], 'RenewalEligibility' => ['shape' => 'RenewalEligibility'], 'Options' => ['shape' => 'CertificateOptions']]], 'CertificateOptions' => ['type' => 'structure', 'members' => ['CertificateTransparencyLoggingPreference' => ['shape' => 'CertificateTransparencyLoggingPreference']]], 'CertificateStatus' => ['type' => 'string', 'enum' => ['PENDING_VALIDATION', 'ISSUED', 'INACTIVE', 'EXPIRED', 'VALIDATION_TIMED_OUT', 'REVOKED', 'FAILED']], 'CertificateStatuses' => ['type' => 'list', 'member' => ['shape' => 'CertificateStatus']], 'CertificateSummary' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'DomainName' => ['shape' => 'DomainNameString']]], 'CertificateSummaryList' => ['type' => 'list', 'member' => ['shape' => 'CertificateSummary']], 'CertificateTransparencyLoggingPreference' => ['type' => 'string', 'enum' => ['ENABLED', 'DISABLED']], 'CertificateType' => ['type' => 'string', 'enum' => ['IMPORTED', 'AMAZON_ISSUED', 'PRIVATE']], 'DeleteCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'DescribeCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'DescribeCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateDetail']]], 'DomainList' => ['type' => 'list', 'member' => ['shape' => 'DomainNameString'], 'max' => 100, 'min' => 1], 'DomainNameString' => ['type' => 'string', 'max' => 253, 'min' => 1, 'pattern' => '^(\\*\\.)?(((?!-)[A-Za-z0-9-]{0,62}[A-Za-z0-9])\\.)+((?!-)[A-Za-z0-9-]{1,62}[A-Za-z0-9])$'], 'DomainStatus' => ['type' => 'string', 'enum' => ['PENDING_VALIDATION', 'SUCCESS', 'FAILED']], 'DomainValidation' => ['type' => 'structure', 'required' => ['DomainName'], 'members' => ['DomainName' => ['shape' => 'DomainNameString'], 'ValidationEmails' => ['shape' => 'ValidationEmailList'], 'ValidationDomain' => ['shape' => 'DomainNameString'], 'ValidationStatus' => ['shape' => 'DomainStatus'], 'ResourceRecord' => ['shape' => 'ResourceRecord'], 'ValidationMethod' => ['shape' => 'ValidationMethod']]], 'DomainValidationList' => ['type' => 'list', 'member' => ['shape' => 'DomainValidation'], 'max' => 1000, 'min' => 1], 'DomainValidationOption' => ['type' => 'structure', 'required' => ['DomainName', 'ValidationDomain'], 'members' => ['DomainName' => ['shape' => 'DomainNameString'], 'ValidationDomain' => ['shape' => 'DomainNameString']]], 'DomainValidationOptionList' => ['type' => 'list', 'member' => ['shape' => 'DomainValidationOption'], 'max' => 100, 'min' => 1], 'ExportCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Passphrase'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Passphrase' => ['shape' => 'PassphraseBlob']]], 'ExportCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain'], 'PrivateKey' => ['shape' => 'PrivateKey']]], 'ExtendedKeyUsage' => ['type' => 'structure', 'members' => ['Name' => ['shape' => 'ExtendedKeyUsageName'], 'OID' => ['shape' => 'String']]], 'ExtendedKeyUsageFilterList' => ['type' => 'list', 'member' => ['shape' => 'ExtendedKeyUsageName']], 'ExtendedKeyUsageList' => ['type' => 'list', 'member' => ['shape' => 'ExtendedKeyUsage']], 'ExtendedKeyUsageName' => ['type' => 'string', 'enum' => ['TLS_WEB_SERVER_AUTHENTICATION', 'TLS_WEB_CLIENT_AUTHENTICATION', 'CODE_SIGNING', 'EMAIL_PROTECTION', 'TIME_STAMPING', 'OCSP_SIGNING', 'IPSEC_END_SYSTEM', 'IPSEC_TUNNEL', 'IPSEC_USER', 'ANY', 'NONE', 'CUSTOM']], 'FailureReason' => ['type' => 'string', 'enum' => ['NO_AVAILABLE_CONTACTS', 'ADDITIONAL_VERIFICATION_REQUIRED', 'DOMAIN_NOT_ALLOWED', 'INVALID_PUBLIC_DOMAIN', 'DOMAIN_VALIDATION_DENIED', 'CAA_ERROR', 'PCA_LIMIT_EXCEEDED', 'PCA_INVALID_ARN', 'PCA_INVALID_STATE', 'PCA_REQUEST_FAILED', 'PCA_NAME_CONSTRAINTS_VALIDATION', 'PCA_RESOURCE_NOT_FOUND', 'PCA_INVALID_ARGS', 'PCA_INVALID_DURATION', 'PCA_ACCESS_DENIED', 'OTHER']], 'Filters' => ['type' => 'structure', 'members' => ['extendedKeyUsage' => ['shape' => 'ExtendedKeyUsageFilterList'], 'keyUsage' => ['shape' => 'KeyUsageFilterList'], 'keyTypes' => ['shape' => 'KeyAlgorithmList']]], 'GetCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'GetCertificateResponse' => ['type' => 'structure', 'members' => ['Certificate' => ['shape' => 'CertificateBody'], 'CertificateChain' => ['shape' => 'CertificateChain']]], 'IdempotencyToken' => ['type' => 'string', 'max' => 32, 'min' => 1, 'pattern' => '\\w+'], 'ImportCertificateRequest' => ['type' => 'structure', 'required' => ['Certificate', 'PrivateKey'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Certificate' => ['shape' => 'CertificateBodyBlob'], 'PrivateKey' => ['shape' => 'PrivateKeyBlob'], 'CertificateChain' => ['shape' => 'CertificateChainBlob'], 'Tags' => ['shape' => 'TagList']]], 'ImportCertificateResponse' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'InUseList' => ['type' => 'list', 'member' => ['shape' => 'String']], 'InvalidArgsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidArnException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidDomainValidationOptionsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidParameterException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidStateException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'InvalidTagException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'KeyAlgorithm' => ['type' => 'string', 'enum' => ['RSA_2048', 'RSA_1024', 'RSA_4096', 'EC_prime256v1', 'EC_secp384r1', 'EC_secp521r1']], 'KeyAlgorithmList' => ['type' => 'list', 'member' => ['shape' => 'KeyAlgorithm']], 'KeyUsage' => ['type' => 'structure', 'members' => ['Name' => ['shape' => 'KeyUsageName']]], 'KeyUsageFilterList' => ['type' => 'list', 'member' => ['shape' => 'KeyUsageName']], 'KeyUsageList' => ['type' => 'list', 'member' => ['shape' => 'KeyUsage']], 'KeyUsageName' => ['type' => 'string', 'enum' => ['DIGITAL_SIGNATURE', 'NON_REPUDIATION', 'KEY_ENCIPHERMENT', 'DATA_ENCIPHERMENT', 'KEY_AGREEMENT', 'CERTIFICATE_SIGNING', 'CRL_SIGNING', 'ENCIPHER_ONLY', 'DECIPHER_ONLY', 'ANY', 'CUSTOM']], 'LimitExceededException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ListCertificatesRequest' => ['type' => 'structure', 'members' => ['CertificateStatuses' => ['shape' => 'CertificateStatuses'], 'Includes' => ['shape' => 'Filters'], 'NextToken' => ['shape' => 'NextToken'], 'MaxItems' => ['shape' => 'MaxItems']]], 'ListCertificatesResponse' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'CertificateSummaryList' => ['shape' => 'CertificateSummaryList']]], 'ListTagsForCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'ListTagsForCertificateResponse' => ['type' => 'structure', 'members' => ['Tags' => ['shape' => 'TagList']]], 'MaxItems' => ['type' => 'integer', 'max' => 1000, 'min' => 1], 'NextToken' => ['type' => 'string', 'max' => 10000, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u00FF]*'], 'PassphraseBlob' => ['type' => 'blob', 'max' => 128, 'min' => 4, 'sensitive' => \true], 'PrivateKey' => ['type' => 'string', 'max' => 524288, 'min' => 1, 'pattern' => '-{5}BEGIN PRIVATE KEY-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END PRIVATE KEY-{5}(\\u000D?\\u000A)?', 'sensitive' => \true], 'PrivateKeyBlob' => ['type' => 'blob', 'max' => 5120, 'min' => 1, 'sensitive' => \true], 'RecordType' => ['type' => 'string', 'enum' => ['CNAME']], 'RemoveTagsFromCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Tags'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'RenewCertificateRequest' => ['type' => 'structure', 'required' => ['CertificateArn'], 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'RenewalEligibility' => ['type' => 'string', 'enum' => ['ELIGIBLE', 'INELIGIBLE']], 'RenewalStatus' => ['type' => 'string', 'enum' => ['PENDING_AUTO_RENEWAL', 'PENDING_VALIDATION', 'SUCCESS', 'FAILED']], 'RenewalSummary' => ['type' => 'structure', 'required' => ['RenewalStatus', 'DomainValidationOptions', 'UpdatedAt'], 'members' => ['RenewalStatus' => ['shape' => 'RenewalStatus'], 'DomainValidationOptions' => ['shape' => 'DomainValidationList'], 'RenewalStatusReason' => ['shape' => 'FailureReason'], 'UpdatedAt' => ['shape' => 'TStamp']]], 'RequestCertificateRequest' => ['type' => 'structure', 'required' => ['DomainName'], 'members' => ['DomainName' => ['shape' => 'DomainNameString'], 'ValidationMethod' => ['shape' => 'ValidationMethod'], 'SubjectAlternativeNames' => ['shape' => 'DomainList'], 'IdempotencyToken' => ['shape' => 'IdempotencyToken'], 'DomainValidationOptions' => ['shape' => 'DomainValidationOptionList'], 'Options' => ['shape' => 'CertificateOptions'], 'CertificateAuthorityArn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'RequestCertificateResponse' => ['type' => 'structure', 'members' => ['CertificateArn' => ['shape' => 'Arn']]], 'RequestInProgressException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResendValidationEmailRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Domain', 'ValidationDomain'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Domain' => ['shape' => 'DomainNameString'], 'ValidationDomain' => ['shape' => 'DomainNameString']]], 'ResourceInUseException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResourceNotFoundException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'ResourceRecord' => ['type' => 'structure', 'required' => ['Name', 'Type', 'Value'], 'members' => ['Name' => ['shape' => 'String'], 'Type' => ['shape' => 'RecordType'], 'Value' => ['shape' => 'String']]], 'RevocationReason' => ['type' => 'string', 'enum' => ['UNSPECIFIED', 'KEY_COMPROMISE', 'CA_COMPROMISE', 'AFFILIATION_CHANGED', 'SUPERCEDED', 'CESSATION_OF_OPERATION', 'CERTIFICATE_HOLD', 'REMOVE_FROM_CRL', 'PRIVILEGE_WITHDRAWN', 'A_A_COMPROMISE']], 'String' => ['type' => 'string'], 'TStamp' => ['type' => 'timestamp'], 'Tag' => ['type' => 'structure', 'required' => ['Key'], 'members' => ['Key' => ['shape' => 'TagKey'], 'Value' => ['shape' => 'TagValue']]], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '[\\p{L}\\p{Z}\\p{N}_.:\\/=+\\-@]*'], 'TagList' => ['type' => 'list', 'member' => ['shape' => 'Tag'], 'max' => 50, 'min' => 1], 'TagPolicyException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'TagValue' => ['type' => 'string', 'max' => 256, 'min' => 0, 'pattern' => '[\\p{L}\\p{Z}\\p{N}_.:\\/=+\\-@]*'], 'TooManyTagsException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'String']], 'exception' => \true], 'UpdateCertificateOptionsRequest' => ['type' => 'structure', 'required' => ['CertificateArn', 'Options'], 'members' => ['CertificateArn' => ['shape' => 'Arn'], 'Options' => ['shape' => 'CertificateOptions']]], 'ValidationEmailList' => ['type' => 'list', 'member' => ['shape' => 'String']], 'ValidationMethod' => ['type' => 'string', 'enum' => ['EMAIL', 'DNS']]]];
|
@@ -1,4 +1,4 @@
|
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/alexaforbusiness/2017-11-09/api-2.json
|
4 |
-
return ['version' => '2.0', 'metadata' => ['apiVersion' => '2017-11-09', 'endpointPrefix' => 'a4b', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceFullName' => 'Alexa For Business', 'serviceId' => 'Alexa For Business', 'signatureVersion' => 'v4', 'targetPrefix' => 'AlexaForBusiness', 'uid' => 'alexaforbusiness-2017-11-09'], 'operations' => ['ApproveSkill' => ['name' => 'ApproveSkill', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ApproveSkillRequest'], 'output' => ['shape' => 'ApproveSkillResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'AssociateContactWithAddressBook' => ['name' => 'AssociateContactWithAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateContactWithAddressBookRequest'], 'output' => ['shape' => 'AssociateContactWithAddressBookResponse'], 'errors' => [['shape' => 'LimitExceededException']]], 'AssociateDeviceWithRoom' => ['name' => 'AssociateDeviceWithRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateDeviceWithRoomRequest'], 'output' => ['shape' => 'AssociateDeviceWithRoomResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'AssociateSkillGroupWithRoom' => ['name' => 'AssociateSkillGroupWithRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateSkillGroupWithRoomRequest'], 'output' => ['shape' => 'AssociateSkillGroupWithRoomResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'AssociateSkillWithSkillGroup' => ['name' => 'AssociateSkillWithSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateSkillWithSkillGroupRequest'], 'output' => ['shape' => 'AssociateSkillWithSkillGroupResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException'], ['shape' => 'SkillNotLinkedException']]], 'AssociateSkillWithUsers' => ['name' => 'AssociateSkillWithUsers', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateSkillWithUsersRequest'], 'output' => ['shape' => 'AssociateSkillWithUsersResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'CreateAddressBook' => ['name' => 'CreateAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateAddressBookRequest'], 'output' => ['shape' => 'CreateAddressBookResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateBusinessReportSchedule' => ['name' => 'CreateBusinessReportSchedule', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateBusinessReportScheduleRequest'], 'output' => ['shape' => 'CreateBusinessReportScheduleResponse'], 'errors' => [['shape' => 'AlreadyExistsException']]], 'CreateConferenceProvider' => ['name' => 'CreateConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateConferenceProviderRequest'], 'output' => ['shape' => 'CreateConferenceProviderResponse'], 'errors' => [['shape' => 'AlreadyExistsException']]], 'CreateContact' => ['name' => 'CreateContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateContactRequest'], 'output' => ['shape' => 'CreateContactResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateProfile' => ['name' => 'CreateProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateProfileRequest'], 'output' => ['shape' => 'CreateProfileResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'AlreadyExistsException'], ['shape' => 'ConcurrentModificationException']]], 'CreateRoom' => ['name' => 'CreateRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateRoomRequest'], 'output' => ['shape' => 'CreateRoomResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateSkillGroup' => ['name' => 'CreateSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateSkillGroupRequest'], 'output' => ['shape' => 'CreateSkillGroupResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException']]], 'CreateUser' => ['name' => 'CreateUser', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateUserRequest'], 'output' => ['shape' => 'CreateUserResponse'], 'errors' => [['shape' => 'ResourceInUseException'], ['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteAddressBook' => ['name' => 'DeleteAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteAddressBookRequest'], 'output' => ['shape' => 'DeleteAddressBookResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteBusinessReportSchedule' => ['name' => 'DeleteBusinessReportSchedule', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteBusinessReportScheduleRequest'], 'output' => ['shape' => 'DeleteBusinessReportScheduleResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteConferenceProvider' => ['name' => 'DeleteConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteConferenceProviderRequest'], 'output' => ['shape' => 'DeleteConferenceProviderResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'DeleteContact' => ['name' => 'DeleteContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteContactRequest'], 'output' => ['shape' => 'DeleteContactResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteDevice' => ['name' => 'DeleteDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteDeviceRequest'], 'output' => ['shape' => 'DeleteDeviceResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidCertificateAuthorityException']]], 'DeleteProfile' => ['name' => 'DeleteProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteProfileRequest'], 'output' => ['shape' => 'DeleteProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteRoom' => ['name' => 'DeleteRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteRoomRequest'], 'output' => ['shape' => 'DeleteRoomResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteRoomSkillParameter' => ['name' => 'DeleteRoomSkillParameter', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteRoomSkillParameterRequest'], 'output' => ['shape' => 'DeleteRoomSkillParameterResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'DeleteSkillAuthorization' => ['name' => 'DeleteSkillAuthorization', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteSkillAuthorizationRequest'], 'output' => ['shape' => 'DeleteSkillAuthorizationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteSkillGroup' => ['name' => 'DeleteSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteSkillGroupRequest'], 'output' => ['shape' => 'DeleteSkillGroupResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteUser' => ['name' => 'DeleteUser', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteUserRequest'], 'output' => ['shape' => 'DeleteUserResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DisassociateContactFromAddressBook' => ['name' => 'DisassociateContactFromAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateContactFromAddressBookRequest'], 'output' => ['shape' => 'DisassociateContactFromAddressBookResponse']], 'DisassociateDeviceFromRoom' => ['name' => 'DisassociateDeviceFromRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateDeviceFromRoomRequest'], 'output' => ['shape' => 'DisassociateDeviceFromRoomResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'DisassociateSkillFromSkillGroup' => ['name' => 'DisassociateSkillFromSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateSkillFromSkillGroupRequest'], 'output' => ['shape' => 'DisassociateSkillFromSkillGroupResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'DisassociateSkillFromUsers' => ['name' => 'DisassociateSkillFromUsers', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateSkillFromUsersRequest'], 'output' => ['shape' => 'DisassociateSkillFromUsersResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'DisassociateSkillGroupFromRoom' => ['name' => 'DisassociateSkillGroupFromRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateSkillGroupFromRoomRequest'], 'output' => ['shape' => 'DisassociateSkillGroupFromRoomResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'ForgetSmartHomeAppliances' => ['name' => 'ForgetSmartHomeAppliances', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ForgetSmartHomeAppliancesRequest'], 'output' => ['shape' => 'ForgetSmartHomeAppliancesResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetAddressBook' => ['name' => 'GetAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetAddressBookRequest'], 'output' => ['shape' => 'GetAddressBookResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetConferencePreference' => ['name' => 'GetConferencePreference', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetConferencePreferenceRequest'], 'output' => ['shape' => 'GetConferencePreferenceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetConferenceProvider' => ['name' => 'GetConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetConferenceProviderRequest'], 'output' => ['shape' => 'GetConferenceProviderResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetContact' => ['name' => 'GetContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetContactRequest'], 'output' => ['shape' => 'GetContactResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetDevice' => ['name' => 'GetDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetDeviceRequest'], 'output' => ['shape' => 'GetDeviceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetProfile' => ['name' => 'GetProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetProfileRequest'], 'output' => ['shape' => 'GetProfileResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetRoom' => ['name' => 'GetRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetRoomRequest'], 'output' => ['shape' => 'GetRoomResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetRoomSkillParameter' => ['name' => 'GetRoomSkillParameter', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetRoomSkillParameterRequest'], 'output' => ['shape' => 'GetRoomSkillParameterResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetSkillGroup' => ['name' => 'GetSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetSkillGroupRequest'], 'output' => ['shape' => 'GetSkillGroupResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'ListBusinessReportSchedules' => ['name' => 'ListBusinessReportSchedules', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListBusinessReportSchedulesRequest'], 'output' => ['shape' => 'ListBusinessReportSchedulesResponse']], 'ListConferenceProviders' => ['name' => 'ListConferenceProviders', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListConferenceProvidersRequest'], 'output' => ['shape' => 'ListConferenceProvidersResponse']], 'ListDeviceEvents' => ['name' => 'ListDeviceEvents', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListDeviceEventsRequest'], 'output' => ['shape' => 'ListDeviceEventsResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'ListSkills' => ['name' => 'ListSkills', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSkillsRequest'], 'output' => ['shape' => 'ListSkillsResponse']], 'ListSkillsStoreCategories' => ['name' => 'ListSkillsStoreCategories', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSkillsStoreCategoriesRequest'], 'output' => ['shape' => 'ListSkillsStoreCategoriesResponse']], 'ListSkillsStoreSkillsByCategory' => ['name' => 'ListSkillsStoreSkillsByCategory', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSkillsStoreSkillsByCategoryRequest'], 'output' => ['shape' => 'ListSkillsStoreSkillsByCategoryResponse']], 'ListSmartHomeAppliances' => ['name' => 'ListSmartHomeAppliances', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSmartHomeAppliancesRequest'], 'output' => ['shape' => 'ListSmartHomeAppliancesResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'ListTags' => ['name' => 'ListTags', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListTagsRequest'], 'output' => ['shape' => 'ListTagsResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'PutConferencePreference' => ['name' => 'PutConferencePreference', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutConferencePreferenceRequest'], 'output' => ['shape' => 'PutConferencePreferenceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'PutRoomSkillParameter' => ['name' => 'PutRoomSkillParameter', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutRoomSkillParameterRequest'], 'output' => ['shape' => 'PutRoomSkillParameterResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'PutSkillAuthorization' => ['name' => 'PutSkillAuthorization', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutSkillAuthorizationRequest'], 'output' => ['shape' => 'PutSkillAuthorizationResponse'], 'errors' => [['shape' => 'UnauthorizedException'], ['shape' => 'ConcurrentModificationException']]], 'RegisterAVSDevice' => ['name' => 'RegisterAVSDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RegisterAVSDeviceRequest'], 'output' => ['shape' => 'RegisterAVSDeviceResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidDeviceException']]], 'RejectSkill' => ['name' => 'RejectSkill', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RejectSkillRequest'], 'output' => ['shape' => 'RejectSkillResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'ResolveRoom' => ['name' => 'ResolveRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ResolveRoomRequest'], 'output' => ['shape' => 'ResolveRoomResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'RevokeInvitation' => ['name' => 'RevokeInvitation', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RevokeInvitationRequest'], 'output' => ['shape' => 'RevokeInvitationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'SearchAddressBooks' => ['name' => 'SearchAddressBooks', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchAddressBooksRequest'], 'output' => ['shape' => 'SearchAddressBooksResponse']], 'SearchContacts' => ['name' => 'SearchContacts', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchContactsRequest'], 'output' => ['shape' => 'SearchContactsResponse']], 'SearchDevices' => ['name' => 'SearchDevices', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchDevicesRequest'], 'output' => ['shape' => 'SearchDevicesResponse']], 'SearchProfiles' => ['name' => 'SearchProfiles', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchProfilesRequest'], 'output' => ['shape' => 'SearchProfilesResponse']], 'SearchRooms' => ['name' => 'SearchRooms', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchRoomsRequest'], 'output' => ['shape' => 'SearchRoomsResponse']], 'SearchSkillGroups' => ['name' => 'SearchSkillGroups', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchSkillGroupsRequest'], 'output' => ['shape' => 'SearchSkillGroupsResponse']], 'SearchUsers' => ['name' => 'SearchUsers', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchUsersRequest'], 'output' => ['shape' => 'SearchUsersResponse']], 'SendInvitation' => ['name' => 'SendInvitation', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SendInvitationRequest'], 'output' => ['shape' => 'SendInvitationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'InvalidUserStatusException'], ['shape' => 'ConcurrentModificationException']]], 'StartDeviceSync' => ['name' => 'StartDeviceSync', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'StartDeviceSyncRequest'], 'output' => ['shape' => 'StartDeviceSyncResponse'], 'errors' => [['shape' => 'DeviceNotRegisteredException']]], 'StartSmartHomeApplianceDiscovery' => ['name' => 'StartSmartHomeApplianceDiscovery', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'StartSmartHomeApplianceDiscoveryRequest'], 'output' => ['shape' => 'StartSmartHomeApplianceDiscoveryResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'TagResource' => ['name' => 'TagResource', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'TagResourceRequest'], 'output' => ['shape' => 'TagResourceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'UntagResource' => ['name' => 'UntagResource', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UntagResourceRequest'], 'output' => ['shape' => 'UntagResourceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'UpdateAddressBook' => ['name' => 'UpdateAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateAddressBookRequest'], 'output' => ['shape' => 'UpdateAddressBookResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateBusinessReportSchedule' => ['name' => 'UpdateBusinessReportSchedule', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateBusinessReportScheduleRequest'], 'output' => ['shape' => 'UpdateBusinessReportScheduleResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateConferenceProvider' => ['name' => 'UpdateConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateConferenceProviderRequest'], 'output' => ['shape' => 'UpdateConferenceProviderResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'UpdateContact' => ['name' => 'UpdateContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateContactRequest'], 'output' => ['shape' => 'UpdateContactResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateDevice' => ['name' => 'UpdateDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateDeviceRequest'], 'output' => ['shape' => 'UpdateDeviceResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'UpdateProfile' => ['name' => 'UpdateProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateProfileRequest'], 'output' => ['shape' => 'UpdateProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateRoom' => ['name' => 'UpdateRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateRoomRequest'], 'output' => ['shape' => 'UpdateRoomResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException']]], 'UpdateSkillGroup' => ['name' => 'UpdateSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateSkillGroupRequest'], 'output' => ['shape' => 'UpdateSkillGroupResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException']]]], 'shapes' => ['Address' => ['type' => 'string', 'max' => 500, 'min' => 1], 'AddressBook' => ['type' => 'structure', 'members' => ['AddressBookArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription']]], 'AddressBookData' => ['type' => 'structure', 'members' => ['AddressBookArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription']]], 'AddressBookDataList' => ['type' => 'list', 'member' => ['shape' => 'AddressBookData']], 'AddressBookDescription' => ['type' => 'string', 'max' => 200, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'AddressBookName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'AlreadyExistsException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'AmazonId' => ['type' => 'string', 'pattern' => '[a-zA-Z0-9]{1,18}'], 'ApplianceDescription' => ['type' => 'string'], 'ApplianceFriendlyName' => ['type' => 'string'], 'ApplianceManufacturerName' => ['type' => 'string'], 'ApproveSkillRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId']]], 'ApproveSkillResponse' => ['type' => 'structure', 'members' => []], 'Arn' => ['type' => 'string', 'pattern' => 'arn:[a-z0-9-\\.]{1,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[^/].{0,1023}'], 'AssociateContactWithAddressBookRequest' => ['type' => 'structure', 'required' => ['ContactArn', 'AddressBookArn'], 'members' => ['ContactArn' => ['shape' => 'Arn'], 'AddressBookArn' => ['shape' => 'Arn']]], 'AssociateContactWithAddressBookResponse' => ['type' => 'structure', 'members' => []], 'AssociateDeviceWithRoomRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'RoomArn' => ['shape' => 'Arn']]], 'AssociateDeviceWithRoomResponse' => ['type' => 'structure', 'members' => []], 'AssociateSkillGroupWithRoomRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'RoomArn' => ['shape' => 'Arn']]], 'AssociateSkillGroupWithRoomResponse' => ['type' => 'structure', 'members' => []], 'AssociateSkillWithSkillGroupRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId']]], 'AssociateSkillWithSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'AssociateSkillWithUsersRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['OrganizationArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId']]], 'AssociateSkillWithUsersResponse' => ['type' => 'structure', 'members' => []], 'AuthorizationResult' => ['type' => 'map', 'key' => ['shape' => 'Key'], 'value' => ['shape' => 'Value'], 'sensitive' => \true], 'Boolean' => ['type' => 'boolean'], 'BulletPoint' => ['type' => 'string'], 'BulletPoints' => ['type' => 'list', 'member' => ['shape' => 'BulletPoint']], 'BusinessReport' => ['type' => 'structure', 'members' => ['Status' => ['shape' => 'BusinessReportStatus'], 'FailureCode' => ['shape' => 'BusinessReportFailureCode'], 'S3Location' => ['shape' => 'BusinessReportS3Location'], 'DeliveryTime' => ['shape' => 'Timestamp'], 'DownloadUrl' => ['shape' => 'BusinessReportDownloadUrl']]], 'BusinessReportContentRange' => ['type' => 'structure', 'members' => ['Interval' => ['shape' => 'BusinessReportInterval']]], 'BusinessReportDownloadUrl' => ['type' => 'string'], 'BusinessReportFailureCode' => ['type' => 'string', 'enum' => ['ACCESS_DENIED', 'NO_SUCH_BUCKET', 'INTERNAL_FAILURE']], 'BusinessReportFormat' => ['type' => 'string', 'enum' => ['CSV', 'CSV_ZIP']], 'BusinessReportInterval' => ['type' => 'string', 'enum' => ['ONE_DAY', 'ONE_WEEK']], 'BusinessReportRecurrence' => ['type' => 'structure', 'members' => ['StartDate' => ['shape' => 'Date']]], 'BusinessReportS3Location' => ['type' => 'structure', 'members' => ['Path' => ['shape' => 'BusinessReportS3Path'], 'BucketName' => ['shape' => 'CustomerS3BucketName']]], 'BusinessReportS3Path' => ['type' => 'string'], 'BusinessReportSchedule' => ['type' => 'structure', 'members' => ['ScheduleArn' => ['shape' => 'Arn'], 'ScheduleName' => ['shape' => 'BusinessReportScheduleName'], 'S3BucketName' => ['shape' => 'CustomerS3BucketName'], 'S3KeyPrefix' => ['shape' => 'S3KeyPrefix'], 'Format' => ['shape' => 'BusinessReportFormat'], 'ContentRange' => ['shape' => 'BusinessReportContentRange'], 'Recurrence' => ['shape' => 'BusinessReportRecurrence'], 'LastBusinessReport' => ['shape' => 'BusinessReport']]], 'BusinessReportScheduleList' => ['type' => 'list', 'member' => ['shape' => 'BusinessReportSchedule']], 'BusinessReportScheduleName' => ['type' => 'string', 'max' => 64, 'min' => 0, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'BusinessReportStatus' => ['type' => 'string', 'enum' => ['RUNNING', 'SUCCEEDED', 'FAILED']], 'Category' => ['type' => 'structure', 'members' => ['CategoryId' => ['shape' => 'CategoryId'], 'CategoryName' => ['shape' => 'CategoryName']]], 'CategoryId' => ['type' => 'long', 'min' => 1], 'CategoryList' => ['type' => 'list', 'member' => ['shape' => 'Category']], 'CategoryName' => ['type' => 'string'], 'ClientId' => ['type' => 'string', 'pattern' => '^\\S+{1,256}$'], 'ClientRequestToken' => ['type' => 'string', 'max' => 150, 'min' => 10, 'pattern' => '[a-zA-Z0-9][a-zA-Z0-9_-]*'], 'CommsProtocol' => ['type' => 'string', 'enum' => ['SIP', 'SIPS', 'H323']], 'ConcurrentModificationException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'ConferencePreference' => ['type' => 'structure', 'members' => ['DefaultConferenceProviderArn' => ['shape' => 'Arn']]], 'ConferenceProvider' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'ConferenceProviderName'], 'Type' => ['shape' => 'ConferenceProviderType'], 'IPDialIn' => ['shape' => 'IPDialIn'], 'PSTNDialIn' => ['shape' => 'PSTNDialIn'], 'MeetingSetting' => ['shape' => 'MeetingSetting']]], 'ConferenceProviderName' => ['type' => 'string', 'max' => 50, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'ConferenceProviderType' => ['type' => 'string', 'enum' => ['CHIME', 'BLUEJEANS', 'FUZE', 'GOOGLE_HANGOUTS', 'POLYCOM', 'RINGCENTRAL', 'SKYPE_FOR_BUSINESS', 'WEBEX', 'ZOOM', 'CUSTOM']], 'ConferenceProvidersList' => ['type' => 'list', 'member' => ['shape' => 'ConferenceProvider']], 'ConnectionStatus' => ['type' => 'string', 'enum' => ['ONLINE', 'OFFLINE']], 'Contact' => ['type' => 'structure', 'members' => ['ContactArn' => ['shape' => 'Arn'], 'DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'E164PhoneNumber']]], 'ContactData' => ['type' => 'structure', 'members' => ['ContactArn' => ['shape' => 'Arn'], 'DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'E164PhoneNumber']]], 'ContactDataList' => ['type' => 'list', 'member' => ['shape' => 'ContactData']], 'ContactName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'CountryCode' => ['type' => 'string', 'pattern' => '\\d{1,3}'], 'CreateAddressBookRequest' => ['type' => 'structure', 'required' => ['Name'], 'members' => ['Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateAddressBookResponse' => ['type' => 'structure', 'members' => ['AddressBookArn' => ['shape' => 'Arn']]], 'CreateBusinessReportScheduleRequest' => ['type' => 'structure', 'required' => ['Format', 'ContentRange'], 'members' => ['ScheduleName' => ['shape' => 'BusinessReportScheduleName'], 'S3BucketName' => ['shape' => 'CustomerS3BucketName'], 'S3KeyPrefix' => ['shape' => 'S3KeyPrefix'], 'Format' => ['shape' => 'BusinessReportFormat'], 'ContentRange' => ['shape' => 'BusinessReportContentRange'], 'Recurrence' => ['shape' => 'BusinessReportRecurrence'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateBusinessReportScheduleResponse' => ['type' => 'structure', 'members' => ['ScheduleArn' => ['shape' => 'Arn']]], 'CreateConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderName', 'ConferenceProviderType', 'MeetingSetting'], 'members' => ['ConferenceProviderName' => ['shape' => 'ConferenceProviderName'], 'ConferenceProviderType' => ['shape' => 'ConferenceProviderType'], 'IPDialIn' => ['shape' => 'IPDialIn'], 'PSTNDialIn' => ['shape' => 'PSTNDialIn'], 'MeetingSetting' => ['shape' => 'MeetingSetting'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateConferenceProviderResponse' => ['type' => 'structure', 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn']]], 'CreateContactRequest' => ['type' => 'structure', 'required' => ['FirstName'], 'members' => ['DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'E164PhoneNumber'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateContactResponse' => ['type' => 'structure', 'members' => ['ContactArn' => ['shape' => 'Arn']]], 'CreateProfileRequest' => ['type' => 'structure', 'required' => ['ProfileName', 'Timezone', 'Address', 'DistanceUnit', 'TemperatureUnit', 'WakeWord'], 'members' => ['ProfileName' => ['shape' => 'ProfileName'], 'Timezone' => ['shape' => 'Timezone'], 'Address' => ['shape' => 'Address'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true], 'SetupModeDisabled' => ['shape' => 'Boolean'], 'MaxVolumeLimit' => ['shape' => 'MaxVolumeLimit'], 'PSTNEnabled' => ['shape' => 'Boolean']]], 'CreateProfileResponse' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn']]], 'CreateRoomRequest' => ['type' => 'structure', 'required' => ['RoomName'], 'members' => ['RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProfileArn' => ['shape' => 'Arn'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true], 'Tags' => ['shape' => 'TagList']]], 'CreateRoomResponse' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'CreateSkillGroupRequest' => ['type' => 'structure', 'required' => ['SkillGroupName'], 'members' => ['SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateSkillGroupResponse' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn']]], 'CreateUserRequest' => ['type' => 'structure', 'required' => ['UserId'], 'members' => ['UserId' => ['shape' => 'user_UserId'], 'FirstName' => ['shape' => 'user_FirstName'], 'LastName' => ['shape' => 'user_LastName'], 'Email' => ['shape' => 'Email'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true], 'Tags' => ['shape' => 'TagList']]], 'CreateUserResponse' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn']]], 'CustomerS3BucketName' => ['type' => 'string', 'pattern' => '[a-z0-9-\\.]{3,63}'], 'Date' => ['type' => 'string', 'pattern' => '^\\d{4}\\-(0?[1-9]|1[012])\\-(0?[1-9]|[12][0-9]|3[01])$'], 'DeleteAddressBookRequest' => ['type' => 'structure', 'required' => ['AddressBookArn'], 'members' => ['AddressBookArn' => ['shape' => 'Arn']]], 'DeleteAddressBookResponse' => ['type' => 'structure', 'members' => []], 'DeleteBusinessReportScheduleRequest' => ['type' => 'structure', 'required' => ['ScheduleArn'], 'members' => ['ScheduleArn' => ['shape' => 'Arn']]], 'DeleteBusinessReportScheduleResponse' => ['type' => 'structure', 'members' => []], 'DeleteConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderArn'], 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn']]], 'DeleteConferenceProviderResponse' => ['type' => 'structure', 'members' => []], 'DeleteContactRequest' => ['type' => 'structure', 'required' => ['ContactArn'], 'members' => ['ContactArn' => ['shape' => 'Arn']]], 'DeleteContactResponse' => ['type' => 'structure', 'members' => []], 'DeleteDeviceRequest' => ['type' => 'structure', 'required' => ['DeviceArn'], 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'DeleteDeviceResponse' => ['type' => 'structure', 'members' => []], 'DeleteProfileRequest' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn']]], 'DeleteProfileResponse' => ['type' => 'structure', 'members' => []], 'DeleteRoomRequest' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'DeleteRoomResponse' => ['type' => 'structure', 'members' => []], 'DeleteRoomSkillParameterRequest' => ['type' => 'structure', 'required' => ['SkillId', 'ParameterKey'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId'], 'ParameterKey' => ['shape' => 'RoomSkillParameterKey']]], 'DeleteRoomSkillParameterResponse' => ['type' => 'structure', 'members' => []], 'DeleteSkillAuthorizationRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId'], 'RoomArn' => ['shape' => 'Arn']]], 'DeleteSkillAuthorizationResponse' => ['type' => 'structure', 'members' => []], 'DeleteSkillGroupRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn']]], 'DeleteSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'DeleteUserRequest' => ['type' => 'structure', 'required' => ['EnrollmentId'], 'members' => ['UserArn' => ['shape' => 'Arn'], 'EnrollmentId' => ['shape' => 'EnrollmentId']]], 'DeleteUserResponse' => ['type' => 'structure', 'members' => []], 'DeveloperInfo' => ['type' => 'structure', 'members' => ['DeveloperName' => ['shape' => 'DeveloperName'], 'PrivacyPolicy' => ['shape' => 'PrivacyPolicy'], 'Email' => ['shape' => 'Email'], 'Url' => ['shape' => 'Url']]], 'DeveloperName' => ['type' => 'string'], 'Device' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceSerialNumber' => ['shape' => 'DeviceSerialNumber'], 'DeviceType' => ['shape' => 'DeviceType'], 'DeviceName' => ['shape' => 'DeviceName'], 'SoftwareVersion' => ['shape' => 'SoftwareVersion'], 'MacAddress' => ['shape' => 'MacAddress'], 'RoomArn' => ['shape' => 'Arn'], 'DeviceStatus' => ['shape' => 'DeviceStatus'], 'DeviceStatusInfo' => ['shape' => 'DeviceStatusInfo']]], 'DeviceData' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceSerialNumber' => ['shape' => 'DeviceSerialNumber'], 'DeviceType' => ['shape' => 'DeviceType'], 'DeviceName' => ['shape' => 'DeviceName'], 'SoftwareVersion' => ['shape' => 'SoftwareVersion'], 'MacAddress' => ['shape' => 'MacAddress'], 'DeviceStatus' => ['shape' => 'DeviceStatus'], 'RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'DeviceStatusInfo' => ['shape' => 'DeviceStatusInfo']]], 'DeviceDataList' => ['type' => 'list', 'member' => ['shape' => 'DeviceData']], 'DeviceEvent' => ['type' => 'structure', 'members' => ['Type' => ['shape' => 'DeviceEventType'], 'Value' => ['shape' => 'DeviceEventValue'], 'Timestamp' => ['shape' => 'Timestamp']]], 'DeviceEventList' => ['type' => 'list', 'member' => ['shape' => 'DeviceEvent']], 'DeviceEventType' => ['type' => 'string', 'enum' => ['CONNECTION_STATUS', 'DEVICE_STATUS']], 'DeviceEventValue' => ['type' => 'string'], 'DeviceName' => ['type' => 'string', 'max' => 100, 'min' => 2, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'DeviceNotRegisteredException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'DeviceSerialNumber' => ['type' => 'string', 'pattern' => '[a-zA-Z0-9]{1,200}'], 'DeviceSerialNumberForAVS' => ['type' => 'string', 'pattern' => '^[a-zA-Z0-9]{1,50}$'], 'DeviceStatus' => ['type' => 'string', 'enum' => ['READY', 'PENDING', 'WAS_OFFLINE', 'DEREGISTERED']], 'DeviceStatusDetail' => ['type' => 'structure', 'members' => ['Code' => ['shape' => 'DeviceStatusDetailCode']]], 'DeviceStatusDetailCode' => ['type' => 'string', 'enum' => ['DEVICE_SOFTWARE_UPDATE_NEEDED', 'DEVICE_WAS_OFFLINE']], 'DeviceStatusDetails' => ['type' => 'list', 'member' => ['shape' => 'DeviceStatusDetail']], 'DeviceStatusInfo' => ['type' => 'structure', 'members' => ['DeviceStatusDetails' => ['shape' => 'DeviceStatusDetails'], 'ConnectionStatus' => ['shape' => 'ConnectionStatus']]], 'DeviceType' => ['type' => 'string', 'pattern' => '[a-zA-Z0-9]{1,200}'], 'DisassociateContactFromAddressBookRequest' => ['type' => 'structure', 'required' => ['ContactArn', 'AddressBookArn'], 'members' => ['ContactArn' => ['shape' => 'Arn'], 'AddressBookArn' => ['shape' => 'Arn']]], 'DisassociateContactFromAddressBookResponse' => ['type' => 'structure', 'members' => []], 'DisassociateDeviceFromRoomRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'DisassociateDeviceFromRoomResponse' => ['type' => 'structure', 'members' => []], 'DisassociateSkillFromSkillGroupRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId']]], 'DisassociateSkillFromSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'DisassociateSkillFromUsersRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['OrganizationArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId']]], 'DisassociateSkillFromUsersResponse' => ['type' => 'structure', 'members' => []], 'DisassociateSkillGroupFromRoomRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'RoomArn' => ['shape' => 'Arn']]], 'DisassociateSkillGroupFromRoomResponse' => ['type' => 'structure', 'members' => []], 'DistanceUnit' => ['type' => 'string', 'enum' => ['METRIC', 'IMPERIAL']], 'E164PhoneNumber' => ['type' => 'string', 'pattern' => '^\\+\\d{8,}$', 'sensitive' => \true], 'Email' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '([0-9a-zA-Z]([+-.\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\\.)+[a-zA-Z]{2,9})'], 'EnablementType' => ['type' => 'string', 'enum' => ['ENABLED', 'PENDING']], 'EnablementTypeFilter' => ['type' => 'string', 'enum' => ['ENABLED', 'PENDING']], 'EndUserLicenseAgreement' => ['type' => 'string'], 'Endpoint' => ['type' => 'string', 'max' => 256, 'min' => 1], 'EnrollmentId' => ['type' => 'string', 'max' => 128, 'min' => 0], 'EnrollmentStatus' => ['type' => 'string', 'enum' => ['INITIALIZED', 'PENDING', 'REGISTERED', 'DISASSOCIATING', 'DEREGISTERING']], 'ErrorMessage' => ['type' => 'string'], 'Feature' => ['type' => 'string', 'enum' => ['BLUETOOTH', 'VOLUME', 'NOTIFICATIONS', 'LISTS', 'SKILLS', 'ALL']], 'Features' => ['type' => 'list', 'member' => ['shape' => 'Feature']], 'Filter' => ['type' => 'structure', 'required' => ['Key', 'Values'], 'members' => ['Key' => ['shape' => 'FilterKey'], 'Values' => ['shape' => 'FilterValueList']]], 'FilterKey' => ['type' => 'string', 'max' => 500, 'min' => 1], 'FilterList' => ['type' => 'list', 'member' => ['shape' => 'Filter'], 'max' => 25], 'FilterValue' => ['type' => 'string', 'max' => 500, 'min' => 1], 'FilterValueList' => ['type' => 'list', 'member' => ['shape' => 'FilterValue'], 'max' => 5], 'ForgetSmartHomeAppliancesRequest' => ['type' => 'structure', 'required' => ['RoomArn'], 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'ForgetSmartHomeAppliancesResponse' => ['type' => 'structure', 'members' => []], 'GenericKeyword' => ['type' => 'string'], 'GenericKeywords' => ['type' => 'list', 'member' => ['shape' => 'GenericKeyword']], 'GetAddressBookRequest' => ['type' => 'structure', 'required' => ['AddressBookArn'], 'members' => ['AddressBookArn' => ['shape' => 'Arn']]], 'GetAddressBookResponse' => ['type' => 'structure', 'members' => ['AddressBook' => ['shape' => 'AddressBook']]], 'GetConferencePreferenceRequest' => ['type' => 'structure', 'members' => []], 'GetConferencePreferenceResponse' => ['type' => 'structure', 'members' => ['Preference' => ['shape' => 'ConferencePreference']]], 'GetConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderArn'], 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn']]], 'GetConferenceProviderResponse' => ['type' => 'structure', 'members' => ['ConferenceProvider' => ['shape' => 'ConferenceProvider']]], 'GetContactRequest' => ['type' => 'structure', 'required' => ['ContactArn'], 'members' => ['ContactArn' => ['shape' => 'Arn']]], 'GetContactResponse' => ['type' => 'structure', 'members' => ['Contact' => ['shape' => 'Contact']]], 'GetDeviceRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'GetDeviceResponse' => ['type' => 'structure', 'members' => ['Device' => ['shape' => 'Device']]], 'GetProfileRequest' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn']]], 'GetProfileResponse' => ['type' => 'structure', 'members' => ['Profile' => ['shape' => 'Profile']]], 'GetRoomRequest' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'GetRoomResponse' => ['type' => 'structure', 'members' => ['Room' => ['shape' => 'Room']]], 'GetRoomSkillParameterRequest' => ['type' => 'structure', 'required' => ['SkillId', 'ParameterKey'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId'], 'ParameterKey' => ['shape' => 'RoomSkillParameterKey']]], 'GetRoomSkillParameterResponse' => ['type' => 'structure', 'members' => ['RoomSkillParameter' => ['shape' => 'RoomSkillParameter']]], 'GetSkillGroupRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn']]], 'GetSkillGroupResponse' => ['type' => 'structure', 'members' => ['SkillGroup' => ['shape' => 'SkillGroup']]], 'IPDialIn' => ['type' => 'structure', 'required' => ['Endpoint', 'CommsProtocol'], 'members' => ['Endpoint' => ['shape' => 'Endpoint'], 'CommsProtocol' => ['shape' => 'CommsProtocol']]], 'IconUrl' => ['type' => 'string'], 'InvalidCertificateAuthorityException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvalidDeviceException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvalidUserStatusException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvocationPhrase' => ['type' => 'string'], 'Key' => ['type' => 'string', 'min' => 1], 'LimitExceededException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'ListBusinessReportSchedulesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListBusinessReportSchedulesResponse' => ['type' => 'structure', 'members' => ['BusinessReportSchedules' => ['shape' => 'BusinessReportScheduleList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListConferenceProvidersRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListConferenceProvidersResponse' => ['type' => 'structure', 'members' => ['ConferenceProviders' => ['shape' => 'ConferenceProvidersList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListDeviceEventsRequest' => ['type' => 'structure', 'required' => ['DeviceArn'], 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'EventType' => ['shape' => 'DeviceEventType'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListDeviceEventsResponse' => ['type' => 'structure', 'members' => ['DeviceEvents' => ['shape' => 'DeviceEventList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSkillsRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'EnablementType' => ['shape' => 'EnablementTypeFilter'], 'SkillType' => ['shape' => 'SkillTypeFilter'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'SkillListMaxResults']]], 'ListSkillsResponse' => ['type' => 'structure', 'members' => ['SkillSummaries' => ['shape' => 'SkillSummaryList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSkillsStoreCategoriesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListSkillsStoreCategoriesResponse' => ['type' => 'structure', 'members' => ['CategoryList' => ['shape' => 'CategoryList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSkillsStoreSkillsByCategoryRequest' => ['type' => 'structure', 'required' => ['CategoryId'], 'members' => ['CategoryId' => ['shape' => 'CategoryId'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'SkillListMaxResults']]], 'ListSkillsStoreSkillsByCategoryResponse' => ['type' => 'structure', 'members' => ['SkillsStoreSkills' => ['shape' => 'SkillsStoreSkillList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSmartHomeAppliancesRequest' => ['type' => 'structure', 'required' => ['RoomArn'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'MaxResults' => ['shape' => 'MaxResults'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSmartHomeAppliancesResponse' => ['type' => 'structure', 'members' => ['SmartHomeAppliances' => ['shape' => 'SmartHomeApplianceList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListTagsRequest' => ['type' => 'structure', 'required' => ['Arn'], 'members' => ['Arn' => ['shape' => 'Arn'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListTagsResponse' => ['type' => 'structure', 'members' => ['Tags' => ['shape' => 'TagList'], 'NextToken' => ['shape' => 'NextToken']]], 'MacAddress' => ['type' => 'string'], 'MaxResults' => ['type' => 'integer', 'max' => 50, 'min' => 1], 'MaxVolumeLimit' => ['type' => 'integer'], 'MeetingSetting' => ['type' => 'structure', 'required' => ['RequirePin'], 'members' => ['RequirePin' => ['shape' => 'RequirePin']]], 'NameInUseException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'NewInThisVersionBulletPoints' => ['type' => 'list', 'member' => ['shape' => 'BulletPoint']], 'NextToken' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'NotFoundException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'OneClickIdDelay' => ['type' => 'string', 'max' => 2, 'min' => 1], 'OneClickPinDelay' => ['type' => 'string', 'max' => 2, 'min' => 1], 'OutboundPhoneNumber' => ['type' => 'string', 'pattern' => '\\d{10}'], 'PSTNDialIn' => ['type' => 'structure', 'required' => ['CountryCode', 'PhoneNumber', 'OneClickIdDelay', 'OneClickPinDelay'], 'members' => ['CountryCode' => ['shape' => 'CountryCode'], 'PhoneNumber' => ['shape' => 'OutboundPhoneNumber'], 'OneClickIdDelay' => ['shape' => 'OneClickIdDelay'], 'OneClickPinDelay' => ['shape' => 'OneClickPinDelay']]], 'PrivacyPolicy' => ['type' => 'string'], 'ProductDescription' => ['type' => 'string'], 'ProductId' => ['type' => 'string', 'pattern' => '^[a-zA-Z0-9_]{1,256}$'], 'Profile' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName'], 'IsDefault' => ['shape' => 'Boolean'], 'Address' => ['shape' => 'Address'], 'Timezone' => ['shape' => 'Timezone'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'SetupModeDisabled' => ['shape' => 'Boolean'], 'MaxVolumeLimit' => ['shape' => 'MaxVolumeLimit'], 'PSTNEnabled' => ['shape' => 'Boolean'], 'AddressBookArn' => ['shape' => 'Arn']]], 'ProfileData' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName'], 'IsDefault' => ['shape' => 'Boolean'], 'Address' => ['shape' => 'Address'], 'Timezone' => ['shape' => 'Timezone'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord']]], 'ProfileDataList' => ['type' => 'list', 'member' => ['shape' => 'ProfileData']], 'ProfileName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'ProviderCalendarId' => ['type' => 'string', 'max' => 100, 'min' => 0], 'PutConferencePreferenceRequest' => ['type' => 'structure', 'required' => ['ConferencePreference'], 'members' => ['ConferencePreference' => ['shape' => 'ConferencePreference']]], 'PutConferencePreferenceResponse' => ['type' => 'structure', 'members' => []], 'PutRoomSkillParameterRequest' => ['type' => 'structure', 'required' => ['SkillId', 'RoomSkillParameter'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId'], 'RoomSkillParameter' => ['shape' => 'RoomSkillParameter']]], 'PutRoomSkillParameterResponse' => ['type' => 'structure', 'members' => []], 'PutSkillAuthorizationRequest' => ['type' => 'structure', 'required' => ['AuthorizationResult', 'SkillId'], 'members' => ['AuthorizationResult' => ['shape' => 'AuthorizationResult'], 'SkillId' => ['shape' => 'SkillId'], 'RoomArn' => ['shape' => 'Arn']]], 'PutSkillAuthorizationResponse' => ['type' => 'structure', 'members' => []], 'RegisterAVSDeviceRequest' => ['type' => 'structure', 'required' => ['ClientId', 'UserCode', 'ProductId', 'DeviceSerialNumber', 'AmazonId'], 'members' => ['ClientId' => ['shape' => 'ClientId'], 'UserCode' => ['shape' => 'UserCode'], 'ProductId' => ['shape' => 'ProductId'], 'DeviceSerialNumber' => ['shape' => 'DeviceSerialNumberForAVS'], 'AmazonId' => ['shape' => 'AmazonId']]], 'RegisterAVSDeviceResponse' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'RejectSkillRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId']]], 'RejectSkillResponse' => ['type' => 'structure', 'members' => []], 'ReleaseDate' => ['type' => 'string'], 'RequirePin' => ['type' => 'string', 'enum' => ['YES', 'NO', 'OPTIONAL']], 'ResolveRoomRequest' => ['type' => 'structure', 'required' => ['UserId', 'SkillId'], 'members' => ['UserId' => ['shape' => 'UserId'], 'SkillId' => ['shape' => 'SkillId']]], 'ResolveRoomResponse' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'RoomSkillParameters' => ['shape' => 'RoomSkillParameters']]], 'ResourceInUseException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken']], 'exception' => \true], 'ReviewKey' => ['type' => 'string'], 'ReviewValue' => ['type' => 'string'], 'Reviews' => ['type' => 'map', 'key' => ['shape' => 'ReviewKey'], 'value' => ['shape' => 'ReviewValue']], 'RevokeInvitationRequest' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn'], 'EnrollmentId' => ['shape' => 'EnrollmentId']]], 'RevokeInvitationResponse' => ['type' => 'structure', 'members' => []], 'Room' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ProfileArn' => ['shape' => 'Arn']]], 'RoomData' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName']]], 'RoomDataList' => ['type' => 'list', 'member' => ['shape' => 'RoomData']], 'RoomDescription' => ['type' => 'string', 'max' => 200, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'RoomName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'RoomSkillParameter' => ['type' => 'structure', 'required' => ['ParameterKey', 'ParameterValue'], 'members' => ['ParameterKey' => ['shape' => 'RoomSkillParameterKey'], 'ParameterValue' => ['shape' => 'RoomSkillParameterValue']]], 'RoomSkillParameterKey' => ['type' => 'string', 'max' => 256, 'min' => 1], 'RoomSkillParameterValue' => ['type' => 'string', 'max' => 512, 'min' => 1], 'RoomSkillParameters' => ['type' => 'list', 'member' => ['shape' => 'RoomSkillParameter']], 'S3KeyPrefix' => ['type' => 'string', 'max' => 100, 'min' => 0, 'pattern' => '[A-Za-z0-9!_\\-\\.\\*\'()/]*'], 'SampleUtterances' => ['type' => 'list', 'member' => ['shape' => 'Utterance']], 'SearchAddressBooksRequest' => ['type' => 'structure', 'members' => ['Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'SearchAddressBooksResponse' => ['type' => 'structure', 'members' => ['AddressBooks' => ['shape' => 'AddressBookDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchContactsRequest' => ['type' => 'structure', 'members' => ['Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'SearchContactsResponse' => ['type' => 'structure', 'members' => ['Contacts' => ['shape' => 'ContactDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchDevicesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchDevicesResponse' => ['type' => 'structure', 'members' => ['Devices' => ['shape' => 'DeviceDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchProfilesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchProfilesResponse' => ['type' => 'structure', 'members' => ['Profiles' => ['shape' => 'ProfileDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchRoomsRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchRoomsResponse' => ['type' => 'structure', 'members' => ['Rooms' => ['shape' => 'RoomDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchSkillGroupsRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchSkillGroupsResponse' => ['type' => 'structure', 'members' => ['SkillGroups' => ['shape' => 'SkillGroupDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchUsersRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchUsersResponse' => ['type' => 'structure', 'members' => ['Users' => ['shape' => 'UserDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SendInvitationRequest' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn']]], 'SendInvitationResponse' => ['type' => 'structure', 'members' => []], 'ShortDescription' => ['type' => 'string'], 'SkillDetails' => ['type' => 'structure', 'members' => ['ProductDescription' => ['shape' => 'ProductDescription'], 'InvocationPhrase' => ['shape' => 'InvocationPhrase'], 'ReleaseDate' => ['shape' => 'ReleaseDate'], 'EndUserLicenseAgreement' => ['shape' => 'EndUserLicenseAgreement'], 'GenericKeywords' => ['shape' => 'GenericKeywords'], 'BulletPoints' => ['shape' => 'BulletPoints'], 'NewInThisVersionBulletPoints' => ['shape' => 'NewInThisVersionBulletPoints'], 'SkillTypes' => ['shape' => 'SkillTypes'], 'Reviews' => ['shape' => 'Reviews'], 'DeveloperInfo' => ['shape' => 'DeveloperInfo']]], 'SkillGroup' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription']]], 'SkillGroupData' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription']]], 'SkillGroupDataList' => ['type' => 'list', 'member' => ['shape' => 'SkillGroupData']], 'SkillGroupDescription' => ['type' => 'string', 'max' => 200, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'SkillGroupName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'SkillId' => ['type' => 'string', 'pattern' => '(^amzn1\\.ask\\.skill\\.[0-9a-f\\-]{1,200})|(^amzn1\\.echo-sdk-ams\\.app\\.[0-9a-f\\-]{1,200})'], 'SkillListMaxResults' => ['type' => 'integer', 'max' => 10, 'min' => 1], 'SkillName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'SkillNotLinkedException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'SkillStoreType' => ['type' => 'string'], 'SkillSummary' => ['type' => 'structure', 'members' => ['SkillId' => ['shape' => 'SkillId'], 'SkillName' => ['shape' => 'SkillName'], 'SupportsLinking' => ['shape' => 'boolean'], 'EnablementType' => ['shape' => 'EnablementType'], 'SkillType' => ['shape' => 'SkillType']]], 'SkillSummaryList' => ['type' => 'list', 'member' => ['shape' => 'SkillSummary']], 'SkillType' => ['type' => 'string', 'enum' => ['PUBLIC', 'PRIVATE'], 'max' => 100, 'min' => 1, 'pattern' => '[a-zA-Z0-9][a-zA-Z0-9_-]*'], 'SkillTypeFilter' => ['type' => 'string', 'enum' => ['PUBLIC', 'PRIVATE', 'ALL']], 'SkillTypes' => ['type' => 'list', 'member' => ['shape' => 'SkillStoreType']], 'SkillsStoreSkill' => ['type' => 'structure', 'members' => ['SkillId' => ['shape' => 'SkillId'], 'SkillName' => ['shape' => 'SkillName'], 'ShortDescription' => ['shape' => 'ShortDescription'], 'IconUrl' => ['shape' => 'IconUrl'], 'SampleUtterances' => ['shape' => 'SampleUtterances'], 'SkillDetails' => ['shape' => 'SkillDetails'], 'SupportsLinking' => ['shape' => 'boolean']]], 'SkillsStoreSkillList' => ['type' => 'list', 'member' => ['shape' => 'SkillsStoreSkill']], 'SmartHomeAppliance' => ['type' => 'structure', 'members' => ['FriendlyName' => ['shape' => 'ApplianceFriendlyName'], 'Description' => ['shape' => 'ApplianceDescription'], 'ManufacturerName' => ['shape' => 'ApplianceManufacturerName']]], 'SmartHomeApplianceList' => ['type' => 'list', 'member' => ['shape' => 'SmartHomeAppliance']], 'SoftwareVersion' => ['type' => 'string'], 'Sort' => ['type' => 'structure', 'required' => ['Key', 'Value'], 'members' => ['Key' => ['shape' => 'SortKey'], 'Value' => ['shape' => 'SortValue']]], 'SortKey' => ['type' => 'string', 'max' => 500, 'min' => 1], 'SortList' => ['type' => 'list', 'member' => ['shape' => 'Sort'], 'max' => 25], 'SortValue' => ['type' => 'string', 'enum' => ['ASC', 'DESC']], 'StartDeviceSyncRequest' => ['type' => 'structure', 'required' => ['Features'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'DeviceArn' => ['shape' => 'Arn'], 'Features' => ['shape' => 'Features']]], 'StartDeviceSyncResponse' => ['type' => 'structure', 'members' => []], 'StartSmartHomeApplianceDiscoveryRequest' => ['type' => 'structure', 'required' => ['RoomArn'], 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'StartSmartHomeApplianceDiscoveryResponse' => ['type' => 'structure', 'members' => []], 'Tag' => ['type' => 'structure', 'required' => ['Key', 'Value'], 'members' => ['Key' => ['shape' => 'TagKey'], 'Value' => ['shape' => 'TagValue']]], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$'], 'TagKeyList' => ['type' => 'list', 'member' => ['shape' => 'TagKey']], 'TagList' => ['type' => 'list', 'member' => ['shape' => 'Tag']], 'TagResourceRequest' => ['type' => 'structure', 'required' => ['Arn', 'Tags'], 'members' => ['Arn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'TagResourceResponse' => ['type' => 'structure', 'members' => []], 'TagValue' => ['type' => 'string', 'max' => 256, 'min' => 0, 'pattern' => '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$'], 'TemperatureUnit' => ['type' => 'string', 'enum' => ['FAHRENHEIT', 'CELSIUS']], 'Timestamp' => ['type' => 'timestamp'], 'Timezone' => ['type' => 'string', 'max' => 100, 'min' => 1], 'TotalCount' => ['type' => 'integer'], 'UnauthorizedException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'UntagResourceRequest' => ['type' => 'structure', 'required' => ['Arn', 'TagKeys'], 'members' => ['Arn' => ['shape' => 'Arn'], 'TagKeys' => ['shape' => 'TagKeyList']]], 'UntagResourceResponse' => ['type' => 'structure', 'members' => []], 'UpdateAddressBookRequest' => ['type' => 'structure', 'required' => ['AddressBookArn'], 'members' => ['AddressBookArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription']]], 'UpdateAddressBookResponse' => ['type' => 'structure', 'members' => []], 'UpdateBusinessReportScheduleRequest' => ['type' => 'structure', 'required' => ['ScheduleArn'], 'members' => ['ScheduleArn' => ['shape' => 'Arn'], 'S3BucketName' => ['shape' => 'CustomerS3BucketName'], 'S3KeyPrefix' => ['shape' => 'S3KeyPrefix'], 'Format' => ['shape' => 'BusinessReportFormat'], 'ScheduleName' => ['shape' => 'BusinessReportScheduleName'], 'Recurrence' => ['shape' => 'BusinessReportRecurrence']]], 'UpdateBusinessReportScheduleResponse' => ['type' => 'structure', 'members' => []], 'UpdateConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderArn', 'ConferenceProviderType', 'MeetingSetting'], 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn'], 'ConferenceProviderType' => ['shape' => 'ConferenceProviderType'], 'IPDialIn' => ['shape' => 'IPDialIn'], 'PSTNDialIn' => ['shape' => 'PSTNDialIn'], 'MeetingSetting' => ['shape' => 'MeetingSetting']]], 'UpdateConferenceProviderResponse' => ['type' => 'structure', 'members' => []], 'UpdateContactRequest' => ['type' => 'structure', 'required' => ['ContactArn'], 'members' => ['ContactArn' => ['shape' => 'Arn'], 'DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'E164PhoneNumber']]], 'UpdateContactResponse' => ['type' => 'structure', 'members' => []], 'UpdateDeviceRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceName' => ['shape' => 'DeviceName']]], 'UpdateDeviceResponse' => ['type' => 'structure', 'members' => []], 'UpdateProfileRequest' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName'], 'IsDefault' => ['shape' => 'Boolean'], 'Timezone' => ['shape' => 'Timezone'], 'Address' => ['shape' => 'Address'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'SetupModeDisabled' => ['shape' => 'Boolean'], 'MaxVolumeLimit' => ['shape' => 'MaxVolumeLimit'], 'PSTNEnabled' => ['shape' => 'Boolean']]], 'UpdateProfileResponse' => ['type' => 'structure', 'members' => []], 'UpdateRoomRequest' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ProfileArn' => ['shape' => 'Arn']]], 'UpdateRoomResponse' => ['type' => 'structure', 'members' => []], 'UpdateSkillGroupRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription']]], 'UpdateSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'Url' => ['type' => 'string'], 'UserCode' => ['type' => 'string', 'max' => 128, 'min' => 1], 'UserData' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn'], 'FirstName' => ['shape' => 'user_FirstName'], 'LastName' => ['shape' => 'user_LastName'], 'Email' => ['shape' => 'Email'], 'EnrollmentStatus' => ['shape' => 'EnrollmentStatus'], 'EnrollmentId' => ['shape' => 'EnrollmentId']]], 'UserDataList' => ['type' => 'list', 'member' => ['shape' => 'UserData']], 'UserId' => ['type' => 'string', 'pattern' => 'amzn1\\.[A-Za-z0-9+-\\/=.]{1,300}'], 'Utterance' => ['type' => 'string'], 'Value' => ['type' => 'string', 'min' => 1], 'WakeWord' => ['type' => 'string', 'enum' => ['ALEXA', 'AMAZON', 'ECHO', 'COMPUTER']], 'boolean' => ['type' => 'boolean'], 'user_FirstName' => ['type' => 'string', 'max' => 30, 'min' => 0, 'pattern' => '([A-Za-z\\-\' 0-9._]|\\p{IsLetter})*'], 'user_LastName' => ['type' => 'string', 'max' => 30, 'min' => 0, 'pattern' => '([A-Za-z\\-\' 0-9._]|\\p{IsLetter})*'], 'user_UserId' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '[a-zA-Z0-9@_+.-]*']]];
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/alexaforbusiness/2017-11-09/api-2.json
|
4 |
+
return ['version' => '2.0', 'metadata' => ['apiVersion' => '2017-11-09', 'endpointPrefix' => 'a4b', 'jsonVersion' => '1.1', 'protocol' => 'json', 'serviceFullName' => 'Alexa For Business', 'serviceId' => 'Alexa For Business', 'signatureVersion' => 'v4', 'targetPrefix' => 'AlexaForBusiness', 'uid' => 'alexaforbusiness-2017-11-09'], 'operations' => ['ApproveSkill' => ['name' => 'ApproveSkill', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ApproveSkillRequest'], 'output' => ['shape' => 'ApproveSkillResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'AssociateContactWithAddressBook' => ['name' => 'AssociateContactWithAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateContactWithAddressBookRequest'], 'output' => ['shape' => 'AssociateContactWithAddressBookResponse'], 'errors' => [['shape' => 'LimitExceededException']]], 'AssociateDeviceWithNetworkProfile' => ['name' => 'AssociateDeviceWithNetworkProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateDeviceWithNetworkProfileRequest'], 'output' => ['shape' => 'AssociateDeviceWithNetworkProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'AssociateDeviceWithRoom' => ['name' => 'AssociateDeviceWithRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateDeviceWithRoomRequest'], 'output' => ['shape' => 'AssociateDeviceWithRoomResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'AssociateSkillGroupWithRoom' => ['name' => 'AssociateSkillGroupWithRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateSkillGroupWithRoomRequest'], 'output' => ['shape' => 'AssociateSkillGroupWithRoomResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'AssociateSkillWithSkillGroup' => ['name' => 'AssociateSkillWithSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateSkillWithSkillGroupRequest'], 'output' => ['shape' => 'AssociateSkillWithSkillGroupResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException'], ['shape' => 'SkillNotLinkedException']]], 'AssociateSkillWithUsers' => ['name' => 'AssociateSkillWithUsers', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'AssociateSkillWithUsersRequest'], 'output' => ['shape' => 'AssociateSkillWithUsersResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'CreateAddressBook' => ['name' => 'CreateAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateAddressBookRequest'], 'output' => ['shape' => 'CreateAddressBookResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateBusinessReportSchedule' => ['name' => 'CreateBusinessReportSchedule', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateBusinessReportScheduleRequest'], 'output' => ['shape' => 'CreateBusinessReportScheduleResponse'], 'errors' => [['shape' => 'AlreadyExistsException']]], 'CreateConferenceProvider' => ['name' => 'CreateConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateConferenceProviderRequest'], 'output' => ['shape' => 'CreateConferenceProviderResponse'], 'errors' => [['shape' => 'AlreadyExistsException']]], 'CreateContact' => ['name' => 'CreateContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateContactRequest'], 'output' => ['shape' => 'CreateContactResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateGatewayGroup' => ['name' => 'CreateGatewayGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateGatewayGroupRequest'], 'output' => ['shape' => 'CreateGatewayGroupResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateNetworkProfile' => ['name' => 'CreateNetworkProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateNetworkProfileRequest'], 'output' => ['shape' => 'CreateNetworkProfileResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidCertificateAuthorityException'], ['shape' => 'InvalidServiceLinkedRoleStateException']]], 'CreateProfile' => ['name' => 'CreateProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateProfileRequest'], 'output' => ['shape' => 'CreateProfileResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'AlreadyExistsException'], ['shape' => 'ConcurrentModificationException']]], 'CreateRoom' => ['name' => 'CreateRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateRoomRequest'], 'output' => ['shape' => 'CreateRoomResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException']]], 'CreateSkillGroup' => ['name' => 'CreateSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateSkillGroupRequest'], 'output' => ['shape' => 'CreateSkillGroupResponse'], 'errors' => [['shape' => 'AlreadyExistsException'], ['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException']]], 'CreateUser' => ['name' => 'CreateUser', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'CreateUserRequest'], 'output' => ['shape' => 'CreateUserResponse'], 'errors' => [['shape' => 'ResourceInUseException'], ['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteAddressBook' => ['name' => 'DeleteAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteAddressBookRequest'], 'output' => ['shape' => 'DeleteAddressBookResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteBusinessReportSchedule' => ['name' => 'DeleteBusinessReportSchedule', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteBusinessReportScheduleRequest'], 'output' => ['shape' => 'DeleteBusinessReportScheduleResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteConferenceProvider' => ['name' => 'DeleteConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteConferenceProviderRequest'], 'output' => ['shape' => 'DeleteConferenceProviderResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'DeleteContact' => ['name' => 'DeleteContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteContactRequest'], 'output' => ['shape' => 'DeleteContactResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteDevice' => ['name' => 'DeleteDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteDeviceRequest'], 'output' => ['shape' => 'DeleteDeviceResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidCertificateAuthorityException']]], 'DeleteDeviceUsageData' => ['name' => 'DeleteDeviceUsageData', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteDeviceUsageDataRequest'], 'output' => ['shape' => 'DeleteDeviceUsageDataResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'DeviceNotRegisteredException'], ['shape' => 'LimitExceededException']]], 'DeleteGatewayGroup' => ['name' => 'DeleteGatewayGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteGatewayGroupRequest'], 'output' => ['shape' => 'DeleteGatewayGroupResponse'], 'errors' => [['shape' => 'ResourceAssociatedException']]], 'DeleteNetworkProfile' => ['name' => 'DeleteNetworkProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteNetworkProfileRequest'], 'output' => ['shape' => 'DeleteNetworkProfileResponse'], 'errors' => [['shape' => 'ResourceInUseException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'DeleteProfile' => ['name' => 'DeleteProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteProfileRequest'], 'output' => ['shape' => 'DeleteProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteRoom' => ['name' => 'DeleteRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteRoomRequest'], 'output' => ['shape' => 'DeleteRoomResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteRoomSkillParameter' => ['name' => 'DeleteRoomSkillParameter', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteRoomSkillParameterRequest'], 'output' => ['shape' => 'DeleteRoomSkillParameterResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'DeleteSkillAuthorization' => ['name' => 'DeleteSkillAuthorization', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteSkillAuthorizationRequest'], 'output' => ['shape' => 'DeleteSkillAuthorizationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteSkillGroup' => ['name' => 'DeleteSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteSkillGroupRequest'], 'output' => ['shape' => 'DeleteSkillGroupResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DeleteUser' => ['name' => 'DeleteUser', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DeleteUserRequest'], 'output' => ['shape' => 'DeleteUserResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'DisassociateContactFromAddressBook' => ['name' => 'DisassociateContactFromAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateContactFromAddressBookRequest'], 'output' => ['shape' => 'DisassociateContactFromAddressBookResponse']], 'DisassociateDeviceFromRoom' => ['name' => 'DisassociateDeviceFromRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateDeviceFromRoomRequest'], 'output' => ['shape' => 'DisassociateDeviceFromRoomResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'DisassociateSkillFromSkillGroup' => ['name' => 'DisassociateSkillFromSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateSkillFromSkillGroupRequest'], 'output' => ['shape' => 'DisassociateSkillFromSkillGroupResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'DisassociateSkillFromUsers' => ['name' => 'DisassociateSkillFromUsers', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateSkillFromUsersRequest'], 'output' => ['shape' => 'DisassociateSkillFromUsersResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'DisassociateSkillGroupFromRoom' => ['name' => 'DisassociateSkillGroupFromRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'DisassociateSkillGroupFromRoomRequest'], 'output' => ['shape' => 'DisassociateSkillGroupFromRoomResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'ForgetSmartHomeAppliances' => ['name' => 'ForgetSmartHomeAppliances', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ForgetSmartHomeAppliancesRequest'], 'output' => ['shape' => 'ForgetSmartHomeAppliancesResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetAddressBook' => ['name' => 'GetAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetAddressBookRequest'], 'output' => ['shape' => 'GetAddressBookResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetConferencePreference' => ['name' => 'GetConferencePreference', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetConferencePreferenceRequest'], 'output' => ['shape' => 'GetConferencePreferenceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetConferenceProvider' => ['name' => 'GetConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetConferenceProviderRequest'], 'output' => ['shape' => 'GetConferenceProviderResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetContact' => ['name' => 'GetContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetContactRequest'], 'output' => ['shape' => 'GetContactResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetDevice' => ['name' => 'GetDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetDeviceRequest'], 'output' => ['shape' => 'GetDeviceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetGateway' => ['name' => 'GetGateway', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetGatewayRequest'], 'output' => ['shape' => 'GetGatewayResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetGatewayGroup' => ['name' => 'GetGatewayGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetGatewayGroupRequest'], 'output' => ['shape' => 'GetGatewayGroupResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetInvitationConfiguration' => ['name' => 'GetInvitationConfiguration', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetInvitationConfigurationRequest'], 'output' => ['shape' => 'GetInvitationConfigurationResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetNetworkProfile' => ['name' => 'GetNetworkProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetNetworkProfileRequest'], 'output' => ['shape' => 'GetNetworkProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'InvalidSecretsManagerResourceException']]], 'GetProfile' => ['name' => 'GetProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetProfileRequest'], 'output' => ['shape' => 'GetProfileResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetRoom' => ['name' => 'GetRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetRoomRequest'], 'output' => ['shape' => 'GetRoomResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetRoomSkillParameter' => ['name' => 'GetRoomSkillParameter', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetRoomSkillParameterRequest'], 'output' => ['shape' => 'GetRoomSkillParameterResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'GetSkillGroup' => ['name' => 'GetSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'GetSkillGroupRequest'], 'output' => ['shape' => 'GetSkillGroupResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'ListBusinessReportSchedules' => ['name' => 'ListBusinessReportSchedules', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListBusinessReportSchedulesRequest'], 'output' => ['shape' => 'ListBusinessReportSchedulesResponse']], 'ListConferenceProviders' => ['name' => 'ListConferenceProviders', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListConferenceProvidersRequest'], 'output' => ['shape' => 'ListConferenceProvidersResponse']], 'ListDeviceEvents' => ['name' => 'ListDeviceEvents', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListDeviceEventsRequest'], 'output' => ['shape' => 'ListDeviceEventsResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'ListGatewayGroups' => ['name' => 'ListGatewayGroups', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListGatewayGroupsRequest'], 'output' => ['shape' => 'ListGatewayGroupsResponse']], 'ListGateways' => ['name' => 'ListGateways', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListGatewaysRequest'], 'output' => ['shape' => 'ListGatewaysResponse']], 'ListSkills' => ['name' => 'ListSkills', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSkillsRequest'], 'output' => ['shape' => 'ListSkillsResponse']], 'ListSkillsStoreCategories' => ['name' => 'ListSkillsStoreCategories', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSkillsStoreCategoriesRequest'], 'output' => ['shape' => 'ListSkillsStoreCategoriesResponse']], 'ListSkillsStoreSkillsByCategory' => ['name' => 'ListSkillsStoreSkillsByCategory', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSkillsStoreSkillsByCategoryRequest'], 'output' => ['shape' => 'ListSkillsStoreSkillsByCategoryResponse']], 'ListSmartHomeAppliances' => ['name' => 'ListSmartHomeAppliances', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListSmartHomeAppliancesRequest'], 'output' => ['shape' => 'ListSmartHomeAppliancesResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'ListTags' => ['name' => 'ListTags', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ListTagsRequest'], 'output' => ['shape' => 'ListTagsResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'PutConferencePreference' => ['name' => 'PutConferencePreference', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutConferencePreferenceRequest'], 'output' => ['shape' => 'PutConferencePreferenceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'PutInvitationConfiguration' => ['name' => 'PutInvitationConfiguration', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutInvitationConfigurationRequest'], 'output' => ['shape' => 'PutInvitationConfigurationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'PutRoomSkillParameter' => ['name' => 'PutRoomSkillParameter', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutRoomSkillParameterRequest'], 'output' => ['shape' => 'PutRoomSkillParameterResponse'], 'errors' => [['shape' => 'ConcurrentModificationException']]], 'PutSkillAuthorization' => ['name' => 'PutSkillAuthorization', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'PutSkillAuthorizationRequest'], 'output' => ['shape' => 'PutSkillAuthorizationResponse'], 'errors' => [['shape' => 'UnauthorizedException'], ['shape' => 'ConcurrentModificationException']]], 'RegisterAVSDevice' => ['name' => 'RegisterAVSDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RegisterAVSDeviceRequest'], 'output' => ['shape' => 'RegisterAVSDeviceResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidDeviceException']]], 'RejectSkill' => ['name' => 'RejectSkill', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RejectSkillRequest'], 'output' => ['shape' => 'RejectSkillResponse'], 'errors' => [['shape' => 'ConcurrentModificationException'], ['shape' => 'NotFoundException']]], 'ResolveRoom' => ['name' => 'ResolveRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'ResolveRoomRequest'], 'output' => ['shape' => 'ResolveRoomResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'RevokeInvitation' => ['name' => 'RevokeInvitation', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'RevokeInvitationRequest'], 'output' => ['shape' => 'RevokeInvitationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'SearchAddressBooks' => ['name' => 'SearchAddressBooks', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchAddressBooksRequest'], 'output' => ['shape' => 'SearchAddressBooksResponse']], 'SearchContacts' => ['name' => 'SearchContacts', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchContactsRequest'], 'output' => ['shape' => 'SearchContactsResponse']], 'SearchDevices' => ['name' => 'SearchDevices', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchDevicesRequest'], 'output' => ['shape' => 'SearchDevicesResponse']], 'SearchNetworkProfiles' => ['name' => 'SearchNetworkProfiles', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchNetworkProfilesRequest'], 'output' => ['shape' => 'SearchNetworkProfilesResponse']], 'SearchProfiles' => ['name' => 'SearchProfiles', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchProfilesRequest'], 'output' => ['shape' => 'SearchProfilesResponse']], 'SearchRooms' => ['name' => 'SearchRooms', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchRoomsRequest'], 'output' => ['shape' => 'SearchRoomsResponse']], 'SearchSkillGroups' => ['name' => 'SearchSkillGroups', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchSkillGroupsRequest'], 'output' => ['shape' => 'SearchSkillGroupsResponse']], 'SearchUsers' => ['name' => 'SearchUsers', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SearchUsersRequest'], 'output' => ['shape' => 'SearchUsersResponse']], 'SendAnnouncement' => ['name' => 'SendAnnouncement', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SendAnnouncementRequest'], 'output' => ['shape' => 'SendAnnouncementResponse'], 'errors' => [['shape' => 'LimitExceededException'], ['shape' => 'AlreadyExistsException']]], 'SendInvitation' => ['name' => 'SendInvitation', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'SendInvitationRequest'], 'output' => ['shape' => 'SendInvitationResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'InvalidUserStatusException'], ['shape' => 'ConcurrentModificationException']]], 'StartDeviceSync' => ['name' => 'StartDeviceSync', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'StartDeviceSyncRequest'], 'output' => ['shape' => 'StartDeviceSyncResponse'], 'errors' => [['shape' => 'DeviceNotRegisteredException']]], 'StartSmartHomeApplianceDiscovery' => ['name' => 'StartSmartHomeApplianceDiscovery', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'StartSmartHomeApplianceDiscoveryRequest'], 'output' => ['shape' => 'StartSmartHomeApplianceDiscoveryResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'TagResource' => ['name' => 'TagResource', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'TagResourceRequest'], 'output' => ['shape' => 'TagResourceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'UntagResource' => ['name' => 'UntagResource', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UntagResourceRequest'], 'output' => ['shape' => 'UntagResourceResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'UpdateAddressBook' => ['name' => 'UpdateAddressBook', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateAddressBookRequest'], 'output' => ['shape' => 'UpdateAddressBookResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateBusinessReportSchedule' => ['name' => 'UpdateBusinessReportSchedule', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateBusinessReportScheduleRequest'], 'output' => ['shape' => 'UpdateBusinessReportScheduleResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateConferenceProvider' => ['name' => 'UpdateConferenceProvider', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateConferenceProviderRequest'], 'output' => ['shape' => 'UpdateConferenceProviderResponse'], 'errors' => [['shape' => 'NotFoundException']]], 'UpdateContact' => ['name' => 'UpdateContact', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateContactRequest'], 'output' => ['shape' => 'UpdateContactResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateDevice' => ['name' => 'UpdateDevice', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateDeviceRequest'], 'output' => ['shape' => 'UpdateDeviceResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'DeviceNotRegisteredException']]], 'UpdateGateway' => ['name' => 'UpdateGateway', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateGatewayRequest'], 'output' => ['shape' => 'UpdateGatewayResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException']]], 'UpdateGatewayGroup' => ['name' => 'UpdateGatewayGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateGatewayGroupRequest'], 'output' => ['shape' => 'UpdateGatewayGroupResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException']]], 'UpdateNetworkProfile' => ['name' => 'UpdateNetworkProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateNetworkProfileRequest'], 'output' => ['shape' => 'UpdateNetworkProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException'], ['shape' => 'InvalidCertificateAuthorityException'], ['shape' => 'InvalidSecretsManagerResourceException']]], 'UpdateProfile' => ['name' => 'UpdateProfile', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateProfileRequest'], 'output' => ['shape' => 'UpdateProfileResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException']]], 'UpdateRoom' => ['name' => 'UpdateRoom', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateRoomRequest'], 'output' => ['shape' => 'UpdateRoomResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException']]], 'UpdateSkillGroup' => ['name' => 'UpdateSkillGroup', 'http' => ['method' => 'POST', 'requestUri' => '/'], 'input' => ['shape' => 'UpdateSkillGroupRequest'], 'output' => ['shape' => 'UpdateSkillGroupResponse'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'NameInUseException'], ['shape' => 'ConcurrentModificationException']]]], 'shapes' => ['Address' => ['type' => 'string', 'max' => 500, 'min' => 1], 'AddressBook' => ['type' => 'structure', 'members' => ['AddressBookArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription']]], 'AddressBookData' => ['type' => 'structure', 'members' => ['AddressBookArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription']]], 'AddressBookDataList' => ['type' => 'list', 'member' => ['shape' => 'AddressBookData']], 'AddressBookDescription' => ['type' => 'string', 'max' => 200, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'AddressBookName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'AlreadyExistsException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'AmazonId' => ['type' => 'string', 'pattern' => '[a-zA-Z0-9]{1,18}'], 'ApplianceDescription' => ['type' => 'string'], 'ApplianceFriendlyName' => ['type' => 'string'], 'ApplianceManufacturerName' => ['type' => 'string'], 'ApproveSkillRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId']]], 'ApproveSkillResponse' => ['type' => 'structure', 'members' => []], 'Arn' => ['type' => 'string', 'pattern' => 'arn:[a-z0-9-\\.]{1,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[^/].{0,1023}'], 'AssociateContactWithAddressBookRequest' => ['type' => 'structure', 'required' => ['ContactArn', 'AddressBookArn'], 'members' => ['ContactArn' => ['shape' => 'Arn'], 'AddressBookArn' => ['shape' => 'Arn']]], 'AssociateContactWithAddressBookResponse' => ['type' => 'structure', 'members' => []], 'AssociateDeviceWithNetworkProfileRequest' => ['type' => 'structure', 'required' => ['DeviceArn', 'NetworkProfileArn'], 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'NetworkProfileArn' => ['shape' => 'Arn']]], 'AssociateDeviceWithNetworkProfileResponse' => ['type' => 'structure', 'members' => []], 'AssociateDeviceWithRoomRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'RoomArn' => ['shape' => 'Arn']]], 'AssociateDeviceWithRoomResponse' => ['type' => 'structure', 'members' => []], 'AssociateSkillGroupWithRoomRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'RoomArn' => ['shape' => 'Arn']]], 'AssociateSkillGroupWithRoomResponse' => ['type' => 'structure', 'members' => []], 'AssociateSkillWithSkillGroupRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId']]], 'AssociateSkillWithSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'AssociateSkillWithUsersRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId']]], 'AssociateSkillWithUsersResponse' => ['type' => 'structure', 'members' => []], 'Audio' => ['type' => 'structure', 'required' => ['Locale', 'Location'], 'members' => ['Locale' => ['shape' => 'Locale'], 'Location' => ['shape' => 'AudioLocation']]], 'AudioList' => ['type' => 'list', 'member' => ['shape' => 'Audio'], 'max' => 1], 'AudioLocation' => ['type' => 'string', 'max' => 1200, 'min' => 0, 'pattern' => 'https://([A-Za-z0-9_.-]+)?(s3-[A-Za-z0-9-]+|s3\\.([A-Za-z0-9-])+|s3|s3.dualstack\\.([A-Za-z0-9-])+)+.amazonaws.com/.*'], 'AuthorizationResult' => ['type' => 'map', 'key' => ['shape' => 'Key'], 'value' => ['shape' => 'Value'], 'sensitive' => \true], 'Boolean' => ['type' => 'boolean'], 'BulletPoint' => ['type' => 'string'], 'BulletPoints' => ['type' => 'list', 'member' => ['shape' => 'BulletPoint']], 'BusinessReport' => ['type' => 'structure', 'members' => ['Status' => ['shape' => 'BusinessReportStatus'], 'FailureCode' => ['shape' => 'BusinessReportFailureCode'], 'S3Location' => ['shape' => 'BusinessReportS3Location'], 'DeliveryTime' => ['shape' => 'BusinessReportDeliveryTime'], 'DownloadUrl' => ['shape' => 'BusinessReportDownloadUrl']]], 'BusinessReportContentRange' => ['type' => 'structure', 'members' => ['Interval' => ['shape' => 'BusinessReportInterval']]], 'BusinessReportDeliveryTime' => ['type' => 'timestamp'], 'BusinessReportDownloadUrl' => ['type' => 'string'], 'BusinessReportFailureCode' => ['type' => 'string', 'enum' => ['ACCESS_DENIED', 'NO_SUCH_BUCKET', 'INTERNAL_FAILURE']], 'BusinessReportFormat' => ['type' => 'string', 'enum' => ['CSV', 'CSV_ZIP']], 'BusinessReportInterval' => ['type' => 'string', 'enum' => ['ONE_DAY', 'ONE_WEEK', 'THIRTY_DAYS']], 'BusinessReportRecurrence' => ['type' => 'structure', 'members' => ['StartDate' => ['shape' => 'Date']]], 'BusinessReportS3Location' => ['type' => 'structure', 'members' => ['Path' => ['shape' => 'BusinessReportS3Path'], 'BucketName' => ['shape' => 'CustomerS3BucketName']]], 'BusinessReportS3Path' => ['type' => 'string'], 'BusinessReportSchedule' => ['type' => 'structure', 'members' => ['ScheduleArn' => ['shape' => 'Arn'], 'ScheduleName' => ['shape' => 'BusinessReportScheduleName'], 'S3BucketName' => ['shape' => 'CustomerS3BucketName'], 'S3KeyPrefix' => ['shape' => 'S3KeyPrefix'], 'Format' => ['shape' => 'BusinessReportFormat'], 'ContentRange' => ['shape' => 'BusinessReportContentRange'], 'Recurrence' => ['shape' => 'BusinessReportRecurrence'], 'LastBusinessReport' => ['shape' => 'BusinessReport']]], 'BusinessReportScheduleList' => ['type' => 'list', 'member' => ['shape' => 'BusinessReportSchedule']], 'BusinessReportScheduleName' => ['type' => 'string', 'max' => 64, 'min' => 0, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'BusinessReportStatus' => ['type' => 'string', 'enum' => ['RUNNING', 'SUCCEEDED', 'FAILED']], 'Category' => ['type' => 'structure', 'members' => ['CategoryId' => ['shape' => 'CategoryId'], 'CategoryName' => ['shape' => 'CategoryName']]], 'CategoryId' => ['type' => 'long', 'min' => 1], 'CategoryList' => ['type' => 'list', 'member' => ['shape' => 'Category']], 'CategoryName' => ['type' => 'string'], 'CertificateTime' => ['type' => 'timestamp'], 'ClientId' => ['type' => 'string', 'pattern' => '^\\S+{1,256}$'], 'ClientRequestToken' => ['type' => 'string', 'max' => 150, 'min' => 10, 'pattern' => '[a-zA-Z0-9][a-zA-Z0-9_-]*'], 'CommsProtocol' => ['type' => 'string', 'enum' => ['SIP', 'SIPS', 'H323']], 'ConcurrentModificationException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'ConferencePreference' => ['type' => 'structure', 'members' => ['DefaultConferenceProviderArn' => ['shape' => 'Arn']]], 'ConferenceProvider' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'ConferenceProviderName'], 'Type' => ['shape' => 'ConferenceProviderType'], 'IPDialIn' => ['shape' => 'IPDialIn'], 'PSTNDialIn' => ['shape' => 'PSTNDialIn'], 'MeetingSetting' => ['shape' => 'MeetingSetting']]], 'ConferenceProviderName' => ['type' => 'string', 'max' => 50, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'ConferenceProviderType' => ['type' => 'string', 'enum' => ['CHIME', 'BLUEJEANS', 'FUZE', 'GOOGLE_HANGOUTS', 'POLYCOM', 'RINGCENTRAL', 'SKYPE_FOR_BUSINESS', 'WEBEX', 'ZOOM', 'CUSTOM']], 'ConferenceProvidersList' => ['type' => 'list', 'member' => ['shape' => 'ConferenceProvider']], 'ConnectionStatus' => ['type' => 'string', 'enum' => ['ONLINE', 'OFFLINE']], 'ConnectionStatusUpdatedTime' => ['type' => 'timestamp'], 'Contact' => ['type' => 'structure', 'members' => ['ContactArn' => ['shape' => 'Arn'], 'DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'RawPhoneNumber'], 'PhoneNumbers' => ['shape' => 'PhoneNumberList'], 'SipAddresses' => ['shape' => 'SipAddressList']]], 'ContactData' => ['type' => 'structure', 'members' => ['ContactArn' => ['shape' => 'Arn'], 'DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'RawPhoneNumber'], 'PhoneNumbers' => ['shape' => 'PhoneNumberList'], 'SipAddresses' => ['shape' => 'SipAddressList']]], 'ContactDataList' => ['type' => 'list', 'member' => ['shape' => 'ContactData']], 'ContactName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'Content' => ['type' => 'structure', 'members' => ['TextList' => ['shape' => 'TextList'], 'SsmlList' => ['shape' => 'SsmlList'], 'AudioList' => ['shape' => 'AudioList']]], 'CountryCode' => ['type' => 'string', 'pattern' => '\\d{1,3}'], 'CreateAddressBookRequest' => ['type' => 'structure', 'required' => ['Name'], 'members' => ['Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateAddressBookResponse' => ['type' => 'structure', 'members' => ['AddressBookArn' => ['shape' => 'Arn']]], 'CreateBusinessReportScheduleRequest' => ['type' => 'structure', 'required' => ['Format', 'ContentRange'], 'members' => ['ScheduleName' => ['shape' => 'BusinessReportScheduleName'], 'S3BucketName' => ['shape' => 'CustomerS3BucketName'], 'S3KeyPrefix' => ['shape' => 'S3KeyPrefix'], 'Format' => ['shape' => 'BusinessReportFormat'], 'ContentRange' => ['shape' => 'BusinessReportContentRange'], 'Recurrence' => ['shape' => 'BusinessReportRecurrence'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateBusinessReportScheduleResponse' => ['type' => 'structure', 'members' => ['ScheduleArn' => ['shape' => 'Arn']]], 'CreateConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderName', 'ConferenceProviderType', 'MeetingSetting'], 'members' => ['ConferenceProviderName' => ['shape' => 'ConferenceProviderName'], 'ConferenceProviderType' => ['shape' => 'ConferenceProviderType'], 'IPDialIn' => ['shape' => 'IPDialIn'], 'PSTNDialIn' => ['shape' => 'PSTNDialIn'], 'MeetingSetting' => ['shape' => 'MeetingSetting'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateConferenceProviderResponse' => ['type' => 'structure', 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn']]], 'CreateContactRequest' => ['type' => 'structure', 'required' => ['FirstName'], 'members' => ['DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'RawPhoneNumber'], 'PhoneNumbers' => ['shape' => 'PhoneNumberList'], 'SipAddresses' => ['shape' => 'SipAddressList'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateContactResponse' => ['type' => 'structure', 'members' => ['ContactArn' => ['shape' => 'Arn']]], 'CreateEndOfMeetingReminder' => ['type' => 'structure', 'required' => ['ReminderAtMinutes', 'ReminderType', 'Enabled'], 'members' => ['ReminderAtMinutes' => ['shape' => 'EndOfMeetingReminderMinutesList'], 'ReminderType' => ['shape' => 'EndOfMeetingReminderType'], 'Enabled' => ['shape' => 'Boolean']]], 'CreateGatewayGroupRequest' => ['type' => 'structure', 'required' => ['Name', 'ClientRequestToken'], 'members' => ['Name' => ['shape' => 'GatewayGroupName'], 'Description' => ['shape' => 'GatewayGroupDescription'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateGatewayGroupResponse' => ['type' => 'structure', 'members' => ['GatewayGroupArn' => ['shape' => 'Arn']]], 'CreateInstantBooking' => ['type' => 'structure', 'required' => ['DurationInMinutes', 'Enabled'], 'members' => ['DurationInMinutes' => ['shape' => 'Minutes'], 'Enabled' => ['shape' => 'Boolean']]], 'CreateMeetingRoomConfiguration' => ['type' => 'structure', 'members' => ['RoomUtilizationMetricsEnabled' => ['shape' => 'Boolean'], 'EndOfMeetingReminder' => ['shape' => 'CreateEndOfMeetingReminder'], 'InstantBooking' => ['shape' => 'CreateInstantBooking'], 'RequireCheckIn' => ['shape' => 'CreateRequireCheckIn']]], 'CreateNetworkProfileRequest' => ['type' => 'structure', 'required' => ['NetworkProfileName', 'Ssid', 'SecurityType', 'ClientRequestToken'], 'members' => ['NetworkProfileName' => ['shape' => 'NetworkProfileName'], 'Description' => ['shape' => 'NetworkProfileDescription'], 'Ssid' => ['shape' => 'NetworkSsid'], 'SecurityType' => ['shape' => 'NetworkSecurityType'], 'EapMethod' => ['shape' => 'NetworkEapMethod'], 'CurrentPassword' => ['shape' => 'CurrentWiFiPassword'], 'NextPassword' => ['shape' => 'NextWiFiPassword'], 'CertificateAuthorityArn' => ['shape' => 'Arn'], 'TrustAnchors' => ['shape' => 'TrustAnchorList'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateNetworkProfileResponse' => ['type' => 'structure', 'members' => ['NetworkProfileArn' => ['shape' => 'Arn']]], 'CreateProfileRequest' => ['type' => 'structure', 'required' => ['ProfileName', 'Timezone', 'Address', 'DistanceUnit', 'TemperatureUnit', 'WakeWord'], 'members' => ['ProfileName' => ['shape' => 'ProfileName'], 'Timezone' => ['shape' => 'Timezone'], 'Address' => ['shape' => 'Address'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'Locale' => ['shape' => 'DeviceLocale'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true], 'SetupModeDisabled' => ['shape' => 'Boolean'], 'MaxVolumeLimit' => ['shape' => 'MaxVolumeLimit'], 'PSTNEnabled' => ['shape' => 'Boolean'], 'MeetingRoomConfiguration' => ['shape' => 'CreateMeetingRoomConfiguration']]], 'CreateProfileResponse' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn']]], 'CreateRequireCheckIn' => ['type' => 'structure', 'required' => ['ReleaseAfterMinutes', 'Enabled'], 'members' => ['ReleaseAfterMinutes' => ['shape' => 'Minutes'], 'Enabled' => ['shape' => 'Boolean']]], 'CreateRoomRequest' => ['type' => 'structure', 'required' => ['RoomName'], 'members' => ['RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProfileArn' => ['shape' => 'Arn'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true], 'Tags' => ['shape' => 'TagList']]], 'CreateRoomResponse' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'CreateSkillGroupRequest' => ['type' => 'structure', 'required' => ['SkillGroupName'], 'members' => ['SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'CreateSkillGroupResponse' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn']]], 'CreateUserRequest' => ['type' => 'structure', 'required' => ['UserId'], 'members' => ['UserId' => ['shape' => 'user_UserId'], 'FirstName' => ['shape' => 'user_FirstName'], 'LastName' => ['shape' => 'user_LastName'], 'Email' => ['shape' => 'Email'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true], 'Tags' => ['shape' => 'TagList']]], 'CreateUserResponse' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn']]], 'CurrentWiFiPassword' => ['type' => 'string', 'max' => 128, 'min' => 5, 'pattern' => '[\\x00-\\x7F]*', 'sensitive' => \true], 'CustomerS3BucketName' => ['type' => 'string', 'pattern' => '[a-z0-9-\\.]{3,63}'], 'Date' => ['type' => 'string', 'pattern' => '^\\d{4}\\-(0?[1-9]|1[012])\\-(0?[1-9]|[12][0-9]|3[01])$'], 'DeleteAddressBookRequest' => ['type' => 'structure', 'required' => ['AddressBookArn'], 'members' => ['AddressBookArn' => ['shape' => 'Arn']]], 'DeleteAddressBookResponse' => ['type' => 'structure', 'members' => []], 'DeleteBusinessReportScheduleRequest' => ['type' => 'structure', 'required' => ['ScheduleArn'], 'members' => ['ScheduleArn' => ['shape' => 'Arn']]], 'DeleteBusinessReportScheduleResponse' => ['type' => 'structure', 'members' => []], 'DeleteConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderArn'], 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn']]], 'DeleteConferenceProviderResponse' => ['type' => 'structure', 'members' => []], 'DeleteContactRequest' => ['type' => 'structure', 'required' => ['ContactArn'], 'members' => ['ContactArn' => ['shape' => 'Arn']]], 'DeleteContactResponse' => ['type' => 'structure', 'members' => []], 'DeleteDeviceRequest' => ['type' => 'structure', 'required' => ['DeviceArn'], 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'DeleteDeviceResponse' => ['type' => 'structure', 'members' => []], 'DeleteDeviceUsageDataRequest' => ['type' => 'structure', 'required' => ['DeviceArn', 'DeviceUsageType'], 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceUsageType' => ['shape' => 'DeviceUsageType']]], 'DeleteDeviceUsageDataResponse' => ['type' => 'structure', 'members' => []], 'DeleteGatewayGroupRequest' => ['type' => 'structure', 'required' => ['GatewayGroupArn'], 'members' => ['GatewayGroupArn' => ['shape' => 'Arn']]], 'DeleteGatewayGroupResponse' => ['type' => 'structure', 'members' => []], 'DeleteNetworkProfileRequest' => ['type' => 'structure', 'required' => ['NetworkProfileArn'], 'members' => ['NetworkProfileArn' => ['shape' => 'Arn']]], 'DeleteNetworkProfileResponse' => ['type' => 'structure', 'members' => []], 'DeleteProfileRequest' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn']]], 'DeleteProfileResponse' => ['type' => 'structure', 'members' => []], 'DeleteRoomRequest' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'DeleteRoomResponse' => ['type' => 'structure', 'members' => []], 'DeleteRoomSkillParameterRequest' => ['type' => 'structure', 'required' => ['SkillId', 'ParameterKey'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId'], 'ParameterKey' => ['shape' => 'RoomSkillParameterKey']]], 'DeleteRoomSkillParameterResponse' => ['type' => 'structure', 'members' => []], 'DeleteSkillAuthorizationRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId'], 'RoomArn' => ['shape' => 'Arn']]], 'DeleteSkillAuthorizationResponse' => ['type' => 'structure', 'members' => []], 'DeleteSkillGroupRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn']]], 'DeleteSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'DeleteUserRequest' => ['type' => 'structure', 'required' => ['EnrollmentId'], 'members' => ['UserArn' => ['shape' => 'Arn'], 'EnrollmentId' => ['shape' => 'EnrollmentId']]], 'DeleteUserResponse' => ['type' => 'structure', 'members' => []], 'DeveloperInfo' => ['type' => 'structure', 'members' => ['DeveloperName' => ['shape' => 'DeveloperName'], 'PrivacyPolicy' => ['shape' => 'PrivacyPolicy'], 'Email' => ['shape' => 'Email'], 'Url' => ['shape' => 'Url']]], 'DeveloperName' => ['type' => 'string'], 'Device' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceSerialNumber' => ['shape' => 'DeviceSerialNumber'], 'DeviceType' => ['shape' => 'DeviceType'], 'DeviceName' => ['shape' => 'DeviceName'], 'SoftwareVersion' => ['shape' => 'SoftwareVersion'], 'MacAddress' => ['shape' => 'MacAddress'], 'RoomArn' => ['shape' => 'Arn'], 'DeviceStatus' => ['shape' => 'DeviceStatus'], 'DeviceStatusInfo' => ['shape' => 'DeviceStatusInfo'], 'NetworkProfileInfo' => ['shape' => 'DeviceNetworkProfileInfo']]], 'DeviceData' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceSerialNumber' => ['shape' => 'DeviceSerialNumber'], 'DeviceType' => ['shape' => 'DeviceType'], 'DeviceName' => ['shape' => 'DeviceName'], 'SoftwareVersion' => ['shape' => 'SoftwareVersion'], 'MacAddress' => ['shape' => 'MacAddress'], 'DeviceStatus' => ['shape' => 'DeviceStatus'], 'NetworkProfileArn' => ['shape' => 'Arn'], 'NetworkProfileName' => ['shape' => 'NetworkProfileName'], 'RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'DeviceStatusInfo' => ['shape' => 'DeviceStatusInfo'], 'CreatedTime' => ['shape' => 'DeviceDataCreatedTime']]], 'DeviceDataCreatedTime' => ['type' => 'timestamp'], 'DeviceDataList' => ['type' => 'list', 'member' => ['shape' => 'DeviceData']], 'DeviceEvent' => ['type' => 'structure', 'members' => ['Type' => ['shape' => 'DeviceEventType'], 'Value' => ['shape' => 'DeviceEventValue'], 'Timestamp' => ['shape' => 'DeviceEventTime']]], 'DeviceEventList' => ['type' => 'list', 'member' => ['shape' => 'DeviceEvent']], 'DeviceEventTime' => ['type' => 'timestamp'], 'DeviceEventType' => ['type' => 'string', 'enum' => ['CONNECTION_STATUS', 'DEVICE_STATUS']], 'DeviceEventValue' => ['type' => 'string'], 'DeviceLocale' => ['type' => 'string', 'max' => 256, 'min' => 1], 'DeviceName' => ['type' => 'string', 'max' => 100, 'min' => 2, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'DeviceNetworkProfileInfo' => ['type' => 'structure', 'members' => ['NetworkProfileArn' => ['shape' => 'Arn'], 'CertificateArn' => ['shape' => 'Arn'], 'CertificateExpirationTime' => ['shape' => 'CertificateTime']]], 'DeviceNotRegisteredException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'DeviceSerialNumber' => ['type' => 'string', 'pattern' => '[a-zA-Z0-9]{1,200}'], 'DeviceSerialNumberForAVS' => ['type' => 'string', 'pattern' => '^[a-zA-Z0-9]{1,50}$'], 'DeviceStatus' => ['type' => 'string', 'enum' => ['READY', 'PENDING', 'WAS_OFFLINE', 'DEREGISTERED', 'FAILED']], 'DeviceStatusDetail' => ['type' => 'structure', 'members' => ['Feature' => ['shape' => 'Feature'], 'Code' => ['shape' => 'DeviceStatusDetailCode']]], 'DeviceStatusDetailCode' => ['type' => 'string', 'enum' => ['DEVICE_SOFTWARE_UPDATE_NEEDED', 'DEVICE_WAS_OFFLINE', 'CREDENTIALS_ACCESS_FAILURE', 'TLS_VERSION_MISMATCH', 'ASSOCIATION_REJECTION', 'AUTHENTICATION_FAILURE', 'DHCP_FAILURE', 'INTERNET_UNAVAILABLE', 'DNS_FAILURE', 'UNKNOWN_FAILURE', 'CERTIFICATE_ISSUING_LIMIT_EXCEEDED', 'INVALID_CERTIFICATE_AUTHORITY', 'NETWORK_PROFILE_NOT_FOUND', 'INVALID_PASSWORD_STATE', 'PASSWORD_NOT_FOUND']], 'DeviceStatusDetails' => ['type' => 'list', 'member' => ['shape' => 'DeviceStatusDetail']], 'DeviceStatusInfo' => ['type' => 'structure', 'members' => ['DeviceStatusDetails' => ['shape' => 'DeviceStatusDetails'], 'ConnectionStatus' => ['shape' => 'ConnectionStatus'], 'ConnectionStatusUpdatedTime' => ['shape' => 'ConnectionStatusUpdatedTime']]], 'DeviceType' => ['type' => 'string', 'pattern' => '[a-zA-Z0-9]{1,200}'], 'DeviceUsageType' => ['type' => 'string', 'enum' => ['VOICE']], 'DisassociateContactFromAddressBookRequest' => ['type' => 'structure', 'required' => ['ContactArn', 'AddressBookArn'], 'members' => ['ContactArn' => ['shape' => 'Arn'], 'AddressBookArn' => ['shape' => 'Arn']]], 'DisassociateContactFromAddressBookResponse' => ['type' => 'structure', 'members' => []], 'DisassociateDeviceFromRoomRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'DisassociateDeviceFromRoomResponse' => ['type' => 'structure', 'members' => []], 'DisassociateSkillFromSkillGroupRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId']]], 'DisassociateSkillFromSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'DisassociateSkillFromUsersRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId']]], 'DisassociateSkillFromUsersResponse' => ['type' => 'structure', 'members' => []], 'DisassociateSkillGroupFromRoomRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'RoomArn' => ['shape' => 'Arn']]], 'DisassociateSkillGroupFromRoomResponse' => ['type' => 'structure', 'members' => []], 'DistanceUnit' => ['type' => 'string', 'enum' => ['METRIC', 'IMPERIAL']], 'Email' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '([0-9a-zA-Z]([+-.\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z]([-\\w]*[0-9a-zA-Z]+)*\\.)+[a-zA-Z]{2,9})'], 'EnablementType' => ['type' => 'string', 'enum' => ['ENABLED', 'PENDING']], 'EnablementTypeFilter' => ['type' => 'string', 'enum' => ['ENABLED', 'PENDING']], 'EndOfMeetingReminder' => ['type' => 'structure', 'members' => ['ReminderAtMinutes' => ['shape' => 'EndOfMeetingReminderMinutesList'], 'ReminderType' => ['shape' => 'EndOfMeetingReminderType'], 'Enabled' => ['shape' => 'Boolean']]], 'EndOfMeetingReminderMinutesList' => ['type' => 'list', 'member' => ['shape' => 'Minutes'], 'max' => 1, 'min' => 1], 'EndOfMeetingReminderType' => ['type' => 'string', 'enum' => ['ANNOUNCEMENT_TIME_CHECK', 'ANNOUNCEMENT_VARIABLE_TIME_LEFT', 'CHIME', 'KNOCK']], 'EndUserLicenseAgreement' => ['type' => 'string'], 'Endpoint' => ['type' => 'string', 'max' => 256, 'min' => 1], 'EnrollmentId' => ['type' => 'string', 'max' => 128, 'min' => 0], 'EnrollmentStatus' => ['type' => 'string', 'enum' => ['INITIALIZED', 'PENDING', 'REGISTERED', 'DISASSOCIATING', 'DEREGISTERING']], 'ErrorMessage' => ['type' => 'string'], 'Feature' => ['type' => 'string', 'enum' => ['BLUETOOTH', 'VOLUME', 'NOTIFICATIONS', 'LISTS', 'SKILLS', 'NETWORK_PROFILE', 'SETTINGS', 'ALL']], 'Features' => ['type' => 'list', 'member' => ['shape' => 'Feature']], 'Filter' => ['type' => 'structure', 'required' => ['Key', 'Values'], 'members' => ['Key' => ['shape' => 'FilterKey'], 'Values' => ['shape' => 'FilterValueList']]], 'FilterKey' => ['type' => 'string', 'max' => 500, 'min' => 1], 'FilterList' => ['type' => 'list', 'member' => ['shape' => 'Filter'], 'max' => 25], 'FilterValue' => ['type' => 'string', 'max' => 500, 'min' => 1], 'FilterValueList' => ['type' => 'list', 'member' => ['shape' => 'FilterValue'], 'max' => 50], 'ForgetSmartHomeAppliancesRequest' => ['type' => 'structure', 'required' => ['RoomArn'], 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'ForgetSmartHomeAppliancesResponse' => ['type' => 'structure', 'members' => []], 'Gateway' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'GatewayName'], 'Description' => ['shape' => 'GatewayDescription'], 'GatewayGroupArn' => ['shape' => 'Arn'], 'SoftwareVersion' => ['shape' => 'GatewayVersion']]], 'GatewayDescription' => ['type' => 'string', 'max' => 200, 'min' => 0, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'GatewayGroup' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'GatewayGroupName'], 'Description' => ['shape' => 'GatewayGroupDescription']]], 'GatewayGroupDescription' => ['type' => 'string', 'max' => 200, 'min' => 0], 'GatewayGroupName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'GatewayGroupSummaries' => ['type' => 'list', 'member' => ['shape' => 'GatewayGroupSummary']], 'GatewayGroupSummary' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'GatewayGroupName'], 'Description' => ['shape' => 'GatewayGroupDescription']]], 'GatewayName' => ['type' => 'string', 'max' => 253, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'GatewaySummaries' => ['type' => 'list', 'member' => ['shape' => 'GatewaySummary']], 'GatewaySummary' => ['type' => 'structure', 'members' => ['Arn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'GatewayName'], 'Description' => ['shape' => 'GatewayDescription'], 'GatewayGroupArn' => ['shape' => 'Arn'], 'SoftwareVersion' => ['shape' => 'GatewayVersion']]], 'GatewayVersion' => ['type' => 'string', 'max' => 50, 'min' => 1], 'GenericKeyword' => ['type' => 'string'], 'GenericKeywords' => ['type' => 'list', 'member' => ['shape' => 'GenericKeyword']], 'GetAddressBookRequest' => ['type' => 'structure', 'required' => ['AddressBookArn'], 'members' => ['AddressBookArn' => ['shape' => 'Arn']]], 'GetAddressBookResponse' => ['type' => 'structure', 'members' => ['AddressBook' => ['shape' => 'AddressBook']]], 'GetConferencePreferenceRequest' => ['type' => 'structure', 'members' => []], 'GetConferencePreferenceResponse' => ['type' => 'structure', 'members' => ['Preference' => ['shape' => 'ConferencePreference']]], 'GetConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderArn'], 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn']]], 'GetConferenceProviderResponse' => ['type' => 'structure', 'members' => ['ConferenceProvider' => ['shape' => 'ConferenceProvider']]], 'GetContactRequest' => ['type' => 'structure', 'required' => ['ContactArn'], 'members' => ['ContactArn' => ['shape' => 'Arn']]], 'GetContactResponse' => ['type' => 'structure', 'members' => ['Contact' => ['shape' => 'Contact']]], 'GetDeviceRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'GetDeviceResponse' => ['type' => 'structure', 'members' => ['Device' => ['shape' => 'Device']]], 'GetGatewayGroupRequest' => ['type' => 'structure', 'required' => ['GatewayGroupArn'], 'members' => ['GatewayGroupArn' => ['shape' => 'Arn']]], 'GetGatewayGroupResponse' => ['type' => 'structure', 'members' => ['GatewayGroup' => ['shape' => 'GatewayGroup']]], 'GetGatewayRequest' => ['type' => 'structure', 'required' => ['GatewayArn'], 'members' => ['GatewayArn' => ['shape' => 'Arn']]], 'GetGatewayResponse' => ['type' => 'structure', 'members' => ['Gateway' => ['shape' => 'Gateway']]], 'GetInvitationConfigurationRequest' => ['type' => 'structure', 'members' => []], 'GetInvitationConfigurationResponse' => ['type' => 'structure', 'members' => ['OrganizationName' => ['shape' => 'OrganizationName'], 'ContactEmail' => ['shape' => 'Email'], 'PrivateSkillIds' => ['shape' => 'ShortSkillIdList']]], 'GetNetworkProfileRequest' => ['type' => 'structure', 'required' => ['NetworkProfileArn'], 'members' => ['NetworkProfileArn' => ['shape' => 'Arn']]], 'GetNetworkProfileResponse' => ['type' => 'structure', 'members' => ['NetworkProfile' => ['shape' => 'NetworkProfile']]], 'GetProfileRequest' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn']]], 'GetProfileResponse' => ['type' => 'structure', 'members' => ['Profile' => ['shape' => 'Profile']]], 'GetRoomRequest' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'GetRoomResponse' => ['type' => 'structure', 'members' => ['Room' => ['shape' => 'Room']]], 'GetRoomSkillParameterRequest' => ['type' => 'structure', 'required' => ['SkillId', 'ParameterKey'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId'], 'ParameterKey' => ['shape' => 'RoomSkillParameterKey']]], 'GetRoomSkillParameterResponse' => ['type' => 'structure', 'members' => ['RoomSkillParameter' => ['shape' => 'RoomSkillParameter']]], 'GetSkillGroupRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn']]], 'GetSkillGroupResponse' => ['type' => 'structure', 'members' => ['SkillGroup' => ['shape' => 'SkillGroup']]], 'IPDialIn' => ['type' => 'structure', 'required' => ['Endpoint', 'CommsProtocol'], 'members' => ['Endpoint' => ['shape' => 'Endpoint'], 'CommsProtocol' => ['shape' => 'CommsProtocol']]], 'IconUrl' => ['type' => 'string'], 'InstantBooking' => ['type' => 'structure', 'members' => ['DurationInMinutes' => ['shape' => 'Minutes'], 'Enabled' => ['shape' => 'Boolean']]], 'InvalidCertificateAuthorityException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvalidDeviceException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvalidSecretsManagerResourceException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvalidServiceLinkedRoleStateException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvalidUserStatusException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'InvocationPhrase' => ['type' => 'string'], 'Key' => ['type' => 'string', 'min' => 1], 'LimitExceededException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'ListBusinessReportSchedulesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListBusinessReportSchedulesResponse' => ['type' => 'structure', 'members' => ['BusinessReportSchedules' => ['shape' => 'BusinessReportScheduleList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListConferenceProvidersRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListConferenceProvidersResponse' => ['type' => 'structure', 'members' => ['ConferenceProviders' => ['shape' => 'ConferenceProvidersList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListDeviceEventsRequest' => ['type' => 'structure', 'required' => ['DeviceArn'], 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'EventType' => ['shape' => 'DeviceEventType'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListDeviceEventsResponse' => ['type' => 'structure', 'members' => ['DeviceEvents' => ['shape' => 'DeviceEventList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListGatewayGroupsRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListGatewayGroupsResponse' => ['type' => 'structure', 'members' => ['GatewayGroups' => ['shape' => 'GatewayGroupSummaries'], 'NextToken' => ['shape' => 'NextToken']]], 'ListGatewaysRequest' => ['type' => 'structure', 'members' => ['GatewayGroupArn' => ['shape' => 'Arn'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListGatewaysResponse' => ['type' => 'structure', 'members' => ['Gateways' => ['shape' => 'GatewaySummaries'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSkillsRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'EnablementType' => ['shape' => 'EnablementTypeFilter'], 'SkillType' => ['shape' => 'SkillTypeFilter'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'SkillListMaxResults']]], 'ListSkillsResponse' => ['type' => 'structure', 'members' => ['SkillSummaries' => ['shape' => 'SkillSummaryList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSkillsStoreCategoriesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListSkillsStoreCategoriesResponse' => ['type' => 'structure', 'members' => ['CategoryList' => ['shape' => 'CategoryList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSkillsStoreSkillsByCategoryRequest' => ['type' => 'structure', 'required' => ['CategoryId'], 'members' => ['CategoryId' => ['shape' => 'CategoryId'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'SkillListMaxResults']]], 'ListSkillsStoreSkillsByCategoryResponse' => ['type' => 'structure', 'members' => ['SkillsStoreSkills' => ['shape' => 'SkillsStoreSkillList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSmartHomeAppliancesRequest' => ['type' => 'structure', 'required' => ['RoomArn'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'MaxResults' => ['shape' => 'MaxResults'], 'NextToken' => ['shape' => 'NextToken']]], 'ListSmartHomeAppliancesResponse' => ['type' => 'structure', 'members' => ['SmartHomeAppliances' => ['shape' => 'SmartHomeApplianceList'], 'NextToken' => ['shape' => 'NextToken']]], 'ListTagsRequest' => ['type' => 'structure', 'required' => ['Arn'], 'members' => ['Arn' => ['shape' => 'Arn'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'ListTagsResponse' => ['type' => 'structure', 'members' => ['Tags' => ['shape' => 'TagList'], 'NextToken' => ['shape' => 'NextToken']]], 'Locale' => ['type' => 'string', 'enum' => ['en-US']], 'MacAddress' => ['type' => 'string'], 'MaxResults' => ['type' => 'integer', 'max' => 50, 'min' => 1], 'MaxVolumeLimit' => ['type' => 'integer'], 'MeetingRoomConfiguration' => ['type' => 'structure', 'members' => ['RoomUtilizationMetricsEnabled' => ['shape' => 'Boolean'], 'EndOfMeetingReminder' => ['shape' => 'EndOfMeetingReminder'], 'InstantBooking' => ['shape' => 'InstantBooking'], 'RequireCheckIn' => ['shape' => 'RequireCheckIn']]], 'MeetingSetting' => ['type' => 'structure', 'required' => ['RequirePin'], 'members' => ['RequirePin' => ['shape' => 'RequirePin']]], 'Minutes' => ['type' => 'integer'], 'NameInUseException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'NetworkEapMethod' => ['type' => 'string', 'enum' => ['EAP_TLS']], 'NetworkProfile' => ['type' => 'structure', 'members' => ['NetworkProfileArn' => ['shape' => 'Arn'], 'NetworkProfileName' => ['shape' => 'NetworkProfileName'], 'Description' => ['shape' => 'NetworkProfileDescription'], 'Ssid' => ['shape' => 'NetworkSsid'], 'SecurityType' => ['shape' => 'NetworkSecurityType'], 'EapMethod' => ['shape' => 'NetworkEapMethod'], 'CurrentPassword' => ['shape' => 'CurrentWiFiPassword'], 'NextPassword' => ['shape' => 'NextWiFiPassword'], 'CertificateAuthorityArn' => ['shape' => 'Arn'], 'TrustAnchors' => ['shape' => 'TrustAnchorList']]], 'NetworkProfileData' => ['type' => 'structure', 'members' => ['NetworkProfileArn' => ['shape' => 'Arn'], 'NetworkProfileName' => ['shape' => 'NetworkProfileName'], 'Description' => ['shape' => 'NetworkProfileDescription'], 'Ssid' => ['shape' => 'NetworkSsid'], 'SecurityType' => ['shape' => 'NetworkSecurityType'], 'EapMethod' => ['shape' => 'NetworkEapMethod'], 'CertificateAuthorityArn' => ['shape' => 'Arn']]], 'NetworkProfileDataList' => ['type' => 'list', 'member' => ['shape' => 'NetworkProfileData']], 'NetworkProfileDescription' => ['type' => 'string', 'max' => 200, 'min' => 0, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'NetworkProfileName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'NetworkSecurityType' => ['type' => 'string', 'enum' => ['OPEN', 'WEP', 'WPA_PSK', 'WPA2_PSK', 'WPA2_ENTERPRISE']], 'NetworkSsid' => ['type' => 'string', 'max' => 32, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'NewInThisVersionBulletPoints' => ['type' => 'list', 'member' => ['shape' => 'BulletPoint']], 'NextToken' => ['type' => 'string', 'max' => 1100, 'min' => 1], 'NextWiFiPassword' => ['type' => 'string', 'max' => 128, 'min' => 0, 'pattern' => '(^$)|([\\x00-\\x7F]{5,})', 'sensitive' => \true], 'NotFoundException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'OneClickIdDelay' => ['type' => 'string', 'max' => 2, 'min' => 1], 'OneClickPinDelay' => ['type' => 'string', 'max' => 2, 'min' => 1], 'OrganizationName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'OutboundPhoneNumber' => ['type' => 'string', 'pattern' => '\\d{10}'], 'PSTNDialIn' => ['type' => 'structure', 'required' => ['CountryCode', 'PhoneNumber', 'OneClickIdDelay', 'OneClickPinDelay'], 'members' => ['CountryCode' => ['shape' => 'CountryCode'], 'PhoneNumber' => ['shape' => 'OutboundPhoneNumber'], 'OneClickIdDelay' => ['shape' => 'OneClickIdDelay'], 'OneClickPinDelay' => ['shape' => 'OneClickPinDelay']]], 'PhoneNumber' => ['type' => 'structure', 'required' => ['Number', 'Type'], 'members' => ['Number' => ['shape' => 'RawPhoneNumber'], 'Type' => ['shape' => 'PhoneNumberType']]], 'PhoneNumberList' => ['type' => 'list', 'member' => ['shape' => 'PhoneNumber'], 'max' => 3, 'min' => 0], 'PhoneNumberType' => ['type' => 'string', 'enum' => ['MOBILE', 'WORK', 'HOME'], 'sensitive' => \true], 'PrivacyPolicy' => ['type' => 'string'], 'ProductDescription' => ['type' => 'string'], 'ProductId' => ['type' => 'string', 'pattern' => '^[a-zA-Z0-9_]{1,256}$'], 'Profile' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName'], 'IsDefault' => ['shape' => 'Boolean'], 'Address' => ['shape' => 'Address'], 'Timezone' => ['shape' => 'Timezone'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'Locale' => ['shape' => 'DeviceLocale'], 'SetupModeDisabled' => ['shape' => 'Boolean'], 'MaxVolumeLimit' => ['shape' => 'MaxVolumeLimit'], 'PSTNEnabled' => ['shape' => 'Boolean'], 'AddressBookArn' => ['shape' => 'Arn'], 'MeetingRoomConfiguration' => ['shape' => 'MeetingRoomConfiguration']]], 'ProfileData' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName'], 'IsDefault' => ['shape' => 'Boolean'], 'Address' => ['shape' => 'Address'], 'Timezone' => ['shape' => 'Timezone'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'Locale' => ['shape' => 'DeviceLocale']]], 'ProfileDataList' => ['type' => 'list', 'member' => ['shape' => 'ProfileData']], 'ProfileName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'ProviderCalendarId' => ['type' => 'string', 'max' => 100, 'min' => 0], 'PutConferencePreferenceRequest' => ['type' => 'structure', 'required' => ['ConferencePreference'], 'members' => ['ConferencePreference' => ['shape' => 'ConferencePreference']]], 'PutConferencePreferenceResponse' => ['type' => 'structure', 'members' => []], 'PutInvitationConfigurationRequest' => ['type' => 'structure', 'required' => ['OrganizationName'], 'members' => ['OrganizationName' => ['shape' => 'OrganizationName'], 'ContactEmail' => ['shape' => 'Email'], 'PrivateSkillIds' => ['shape' => 'ShortSkillIdList']]], 'PutInvitationConfigurationResponse' => ['type' => 'structure', 'members' => []], 'PutRoomSkillParameterRequest' => ['type' => 'structure', 'required' => ['SkillId', 'RoomSkillParameter'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'SkillId' => ['shape' => 'SkillId'], 'RoomSkillParameter' => ['shape' => 'RoomSkillParameter']]], 'PutRoomSkillParameterResponse' => ['type' => 'structure', 'members' => []], 'PutSkillAuthorizationRequest' => ['type' => 'structure', 'required' => ['AuthorizationResult', 'SkillId'], 'members' => ['AuthorizationResult' => ['shape' => 'AuthorizationResult'], 'SkillId' => ['shape' => 'SkillId'], 'RoomArn' => ['shape' => 'Arn']]], 'PutSkillAuthorizationResponse' => ['type' => 'structure', 'members' => []], 'RawPhoneNumber' => ['type' => 'string', 'max' => 50, 'min' => 0, 'pattern' => '^[\\+0-9\\#\\,\\(][\\+0-9\\-\\.\\/\\(\\)\\,\\#\\s]+$', 'sensitive' => \true], 'RegisterAVSDeviceRequest' => ['type' => 'structure', 'required' => ['ClientId', 'UserCode', 'ProductId', 'DeviceSerialNumber', 'AmazonId'], 'members' => ['ClientId' => ['shape' => 'ClientId'], 'UserCode' => ['shape' => 'UserCode'], 'ProductId' => ['shape' => 'ProductId'], 'DeviceSerialNumber' => ['shape' => 'DeviceSerialNumberForAVS'], 'AmazonId' => ['shape' => 'AmazonId']]], 'RegisterAVSDeviceResponse' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn']]], 'RejectSkillRequest' => ['type' => 'structure', 'required' => ['SkillId'], 'members' => ['SkillId' => ['shape' => 'SkillId']]], 'RejectSkillResponse' => ['type' => 'structure', 'members' => []], 'ReleaseDate' => ['type' => 'string'], 'RequireCheckIn' => ['type' => 'structure', 'members' => ['ReleaseAfterMinutes' => ['shape' => 'Minutes'], 'Enabled' => ['shape' => 'Boolean']]], 'RequirePin' => ['type' => 'string', 'enum' => ['YES', 'NO', 'OPTIONAL']], 'ResolveRoomRequest' => ['type' => 'structure', 'required' => ['UserId', 'SkillId'], 'members' => ['UserId' => ['shape' => 'UserId'], 'SkillId' => ['shape' => 'SkillId']]], 'ResolveRoomResponse' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'RoomSkillParameters' => ['shape' => 'RoomSkillParameters']]], 'ResourceAssociatedException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'ResourceInUseException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken']], 'exception' => \true], 'ReviewKey' => ['type' => 'string'], 'ReviewValue' => ['type' => 'string'], 'Reviews' => ['type' => 'map', 'key' => ['shape' => 'ReviewKey'], 'value' => ['shape' => 'ReviewValue']], 'RevokeInvitationRequest' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn'], 'EnrollmentId' => ['shape' => 'EnrollmentId']]], 'RevokeInvitationResponse' => ['type' => 'structure', 'members' => []], 'Room' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ProfileArn' => ['shape' => 'Arn']]], 'RoomData' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName']]], 'RoomDataList' => ['type' => 'list', 'member' => ['shape' => 'RoomData']], 'RoomDescription' => ['type' => 'string', 'max' => 200, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'RoomName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'RoomSkillParameter' => ['type' => 'structure', 'required' => ['ParameterKey', 'ParameterValue'], 'members' => ['ParameterKey' => ['shape' => 'RoomSkillParameterKey'], 'ParameterValue' => ['shape' => 'RoomSkillParameterValue']]], 'RoomSkillParameterKey' => ['type' => 'string', 'max' => 256, 'min' => 1], 'RoomSkillParameterValue' => ['type' => 'string', 'max' => 512, 'min' => 1], 'RoomSkillParameters' => ['type' => 'list', 'member' => ['shape' => 'RoomSkillParameter']], 'S3KeyPrefix' => ['type' => 'string', 'max' => 100, 'min' => 0, 'pattern' => '[A-Za-z0-9!_\\-\\.\\*\'()/]*'], 'SampleUtterances' => ['type' => 'list', 'member' => ['shape' => 'Utterance']], 'SearchAddressBooksRequest' => ['type' => 'structure', 'members' => ['Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'SearchAddressBooksResponse' => ['type' => 'structure', 'members' => ['AddressBooks' => ['shape' => 'AddressBookDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchContactsRequest' => ['type' => 'structure', 'members' => ['Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList'], 'NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults']]], 'SearchContactsResponse' => ['type' => 'structure', 'members' => ['Contacts' => ['shape' => 'ContactDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchDevicesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchDevicesResponse' => ['type' => 'structure', 'members' => ['Devices' => ['shape' => 'DeviceDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchNetworkProfilesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchNetworkProfilesResponse' => ['type' => 'structure', 'members' => ['NetworkProfiles' => ['shape' => 'NetworkProfileDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchProfilesRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchProfilesResponse' => ['type' => 'structure', 'members' => ['Profiles' => ['shape' => 'ProfileDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchRoomsRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchRoomsResponse' => ['type' => 'structure', 'members' => ['Rooms' => ['shape' => 'RoomDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchSkillGroupsRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchSkillGroupsResponse' => ['type' => 'structure', 'members' => ['SkillGroups' => ['shape' => 'SkillGroupDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SearchUsersRequest' => ['type' => 'structure', 'members' => ['NextToken' => ['shape' => 'NextToken'], 'MaxResults' => ['shape' => 'MaxResults'], 'Filters' => ['shape' => 'FilterList'], 'SortCriteria' => ['shape' => 'SortList']]], 'SearchUsersResponse' => ['type' => 'structure', 'members' => ['Users' => ['shape' => 'UserDataList'], 'NextToken' => ['shape' => 'NextToken'], 'TotalCount' => ['shape' => 'TotalCount']]], 'SendAnnouncementRequest' => ['type' => 'structure', 'required' => ['RoomFilters', 'Content', 'ClientRequestToken'], 'members' => ['RoomFilters' => ['shape' => 'FilterList'], 'Content' => ['shape' => 'Content'], 'TimeToLiveInSeconds' => ['shape' => 'TimeToLiveInSeconds'], 'ClientRequestToken' => ['shape' => 'ClientRequestToken', 'idempotencyToken' => \true]]], 'SendAnnouncementResponse' => ['type' => 'structure', 'members' => ['AnnouncementArn' => ['shape' => 'Arn']]], 'SendInvitationRequest' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn']]], 'SendInvitationResponse' => ['type' => 'structure', 'members' => []], 'ShortDescription' => ['type' => 'string'], 'ShortSkillIdList' => ['type' => 'list', 'member' => ['shape' => 'SkillId'], 'max' => 3, 'min' => 0], 'SipAddress' => ['type' => 'structure', 'required' => ['Uri', 'Type'], 'members' => ['Uri' => ['shape' => 'SipUri'], 'Type' => ['shape' => 'SipType']]], 'SipAddressList' => ['type' => 'list', 'member' => ['shape' => 'SipAddress'], 'max' => 1, 'min' => 0], 'SipType' => ['type' => 'string', 'enum' => ['WORK'], 'sensitive' => \true], 'SipUri' => ['type' => 'string', 'max' => 256, 'min' => 1, 'pattern' => '^sip[s]?:([^@:]+)\\@([^@]+)$', 'sensitive' => \true], 'SkillDetails' => ['type' => 'structure', 'members' => ['ProductDescription' => ['shape' => 'ProductDescription'], 'InvocationPhrase' => ['shape' => 'InvocationPhrase'], 'ReleaseDate' => ['shape' => 'ReleaseDate'], 'EndUserLicenseAgreement' => ['shape' => 'EndUserLicenseAgreement'], 'GenericKeywords' => ['shape' => 'GenericKeywords'], 'BulletPoints' => ['shape' => 'BulletPoints'], 'NewInThisVersionBulletPoints' => ['shape' => 'NewInThisVersionBulletPoints'], 'SkillTypes' => ['shape' => 'SkillTypes'], 'Reviews' => ['shape' => 'Reviews'], 'DeveloperInfo' => ['shape' => 'DeveloperInfo']]], 'SkillGroup' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription']]], 'SkillGroupData' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription']]], 'SkillGroupDataList' => ['type' => 'list', 'member' => ['shape' => 'SkillGroupData']], 'SkillGroupDescription' => ['type' => 'string', 'max' => 200, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'SkillGroupName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'SkillId' => ['type' => 'string', 'pattern' => '(^amzn1\\.ask\\.skill\\.[0-9a-f\\-]{1,200})|(^amzn1\\.echo-sdk-ams\\.app\\.[0-9a-f\\-]{1,200})'], 'SkillListMaxResults' => ['type' => 'integer', 'max' => 10, 'min' => 1], 'SkillName' => ['type' => 'string', 'max' => 100, 'min' => 1, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'SkillNotLinkedException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'SkillStoreType' => ['type' => 'string'], 'SkillSummary' => ['type' => 'structure', 'members' => ['SkillId' => ['shape' => 'SkillId'], 'SkillName' => ['shape' => 'SkillName'], 'SupportsLinking' => ['shape' => 'boolean'], 'EnablementType' => ['shape' => 'EnablementType'], 'SkillType' => ['shape' => 'SkillType']]], 'SkillSummaryList' => ['type' => 'list', 'member' => ['shape' => 'SkillSummary']], 'SkillType' => ['type' => 'string', 'enum' => ['PUBLIC', 'PRIVATE'], 'max' => 100, 'min' => 1, 'pattern' => '[a-zA-Z0-9][a-zA-Z0-9_-]*'], 'SkillTypeFilter' => ['type' => 'string', 'enum' => ['PUBLIC', 'PRIVATE', 'ALL']], 'SkillTypes' => ['type' => 'list', 'member' => ['shape' => 'SkillStoreType']], 'SkillsStoreSkill' => ['type' => 'structure', 'members' => ['SkillId' => ['shape' => 'SkillId'], 'SkillName' => ['shape' => 'SkillName'], 'ShortDescription' => ['shape' => 'ShortDescription'], 'IconUrl' => ['shape' => 'IconUrl'], 'SampleUtterances' => ['shape' => 'SampleUtterances'], 'SkillDetails' => ['shape' => 'SkillDetails'], 'SupportsLinking' => ['shape' => 'boolean']]], 'SkillsStoreSkillList' => ['type' => 'list', 'member' => ['shape' => 'SkillsStoreSkill']], 'SmartHomeAppliance' => ['type' => 'structure', 'members' => ['FriendlyName' => ['shape' => 'ApplianceFriendlyName'], 'Description' => ['shape' => 'ApplianceDescription'], 'ManufacturerName' => ['shape' => 'ApplianceManufacturerName']]], 'SmartHomeApplianceList' => ['type' => 'list', 'member' => ['shape' => 'SmartHomeAppliance']], 'SoftwareVersion' => ['type' => 'string'], 'Sort' => ['type' => 'structure', 'required' => ['Key', 'Value'], 'members' => ['Key' => ['shape' => 'SortKey'], 'Value' => ['shape' => 'SortValue']]], 'SortKey' => ['type' => 'string', 'max' => 500, 'min' => 1], 'SortList' => ['type' => 'list', 'member' => ['shape' => 'Sort'], 'max' => 25], 'SortValue' => ['type' => 'string', 'enum' => ['ASC', 'DESC']], 'Ssml' => ['type' => 'structure', 'required' => ['Locale', 'Value'], 'members' => ['Locale' => ['shape' => 'Locale'], 'Value' => ['shape' => 'SsmlValue']]], 'SsmlList' => ['type' => 'list', 'member' => ['shape' => 'Ssml'], 'max' => 1], 'SsmlValue' => ['type' => 'string', 'max' => 4096, 'min' => 0, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'StartDeviceSyncRequest' => ['type' => 'structure', 'required' => ['Features'], 'members' => ['RoomArn' => ['shape' => 'Arn'], 'DeviceArn' => ['shape' => 'Arn'], 'Features' => ['shape' => 'Features']]], 'StartDeviceSyncResponse' => ['type' => 'structure', 'members' => []], 'StartSmartHomeApplianceDiscoveryRequest' => ['type' => 'structure', 'required' => ['RoomArn'], 'members' => ['RoomArn' => ['shape' => 'Arn']]], 'StartSmartHomeApplianceDiscoveryResponse' => ['type' => 'structure', 'members' => []], 'Tag' => ['type' => 'structure', 'required' => ['Key', 'Value'], 'members' => ['Key' => ['shape' => 'TagKey'], 'Value' => ['shape' => 'TagValue']]], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$'], 'TagKeyList' => ['type' => 'list', 'member' => ['shape' => 'TagKey']], 'TagList' => ['type' => 'list', 'member' => ['shape' => 'Tag']], 'TagResourceRequest' => ['type' => 'structure', 'required' => ['Arn', 'Tags'], 'members' => ['Arn' => ['shape' => 'Arn'], 'Tags' => ['shape' => 'TagList']]], 'TagResourceResponse' => ['type' => 'structure', 'members' => []], 'TagValue' => ['type' => 'string', 'max' => 256, 'min' => 0, 'pattern' => '^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$'], 'TemperatureUnit' => ['type' => 'string', 'enum' => ['FAHRENHEIT', 'CELSIUS']], 'Text' => ['type' => 'structure', 'required' => ['Locale', 'Value'], 'members' => ['Locale' => ['shape' => 'Locale'], 'Value' => ['shape' => 'TextValue']]], 'TextList' => ['type' => 'list', 'member' => ['shape' => 'Text'], 'max' => 1], 'TextValue' => ['type' => 'string', 'max' => 4096, 'min' => 0, 'pattern' => '[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u0085\\u00A0-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]*'], 'TimeToLiveInSeconds' => ['type' => 'integer', 'max' => 3600, 'min' => 1], 'Timezone' => ['type' => 'string', 'max' => 100, 'min' => 1], 'TotalCount' => ['type' => 'integer'], 'TrustAnchor' => ['type' => 'string', 'pattern' => '-{5}BEGIN CERTIFICATE-{5}\\u000D?\\u000A([A-Za-z0-9/+]{64}\\u000D?\\u000A)*[A-Za-z0-9/+]{1,64}={0,2}\\u000D?\\u000A-{5}END CERTIFICATE-{5}(\\u000D?\\u000A)?'], 'TrustAnchorList' => ['type' => 'list', 'member' => ['shape' => 'TrustAnchor'], 'max' => 5, 'min' => 1], 'UnauthorizedException' => ['type' => 'structure', 'members' => ['Message' => ['shape' => 'ErrorMessage']], 'exception' => \true], 'UntagResourceRequest' => ['type' => 'structure', 'required' => ['Arn', 'TagKeys'], 'members' => ['Arn' => ['shape' => 'Arn'], 'TagKeys' => ['shape' => 'TagKeyList']]], 'UntagResourceResponse' => ['type' => 'structure', 'members' => []], 'UpdateAddressBookRequest' => ['type' => 'structure', 'required' => ['AddressBookArn'], 'members' => ['AddressBookArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'AddressBookName'], 'Description' => ['shape' => 'AddressBookDescription']]], 'UpdateAddressBookResponse' => ['type' => 'structure', 'members' => []], 'UpdateBusinessReportScheduleRequest' => ['type' => 'structure', 'required' => ['ScheduleArn'], 'members' => ['ScheduleArn' => ['shape' => 'Arn'], 'S3BucketName' => ['shape' => 'CustomerS3BucketName'], 'S3KeyPrefix' => ['shape' => 'S3KeyPrefix'], 'Format' => ['shape' => 'BusinessReportFormat'], 'ScheduleName' => ['shape' => 'BusinessReportScheduleName'], 'Recurrence' => ['shape' => 'BusinessReportRecurrence']]], 'UpdateBusinessReportScheduleResponse' => ['type' => 'structure', 'members' => []], 'UpdateConferenceProviderRequest' => ['type' => 'structure', 'required' => ['ConferenceProviderArn', 'ConferenceProviderType', 'MeetingSetting'], 'members' => ['ConferenceProviderArn' => ['shape' => 'Arn'], 'ConferenceProviderType' => ['shape' => 'ConferenceProviderType'], 'IPDialIn' => ['shape' => 'IPDialIn'], 'PSTNDialIn' => ['shape' => 'PSTNDialIn'], 'MeetingSetting' => ['shape' => 'MeetingSetting']]], 'UpdateConferenceProviderResponse' => ['type' => 'structure', 'members' => []], 'UpdateContactRequest' => ['type' => 'structure', 'required' => ['ContactArn'], 'members' => ['ContactArn' => ['shape' => 'Arn'], 'DisplayName' => ['shape' => 'ContactName'], 'FirstName' => ['shape' => 'ContactName'], 'LastName' => ['shape' => 'ContactName'], 'PhoneNumber' => ['shape' => 'RawPhoneNumber'], 'PhoneNumbers' => ['shape' => 'PhoneNumberList'], 'SipAddresses' => ['shape' => 'SipAddressList']]], 'UpdateContactResponse' => ['type' => 'structure', 'members' => []], 'UpdateDeviceRequest' => ['type' => 'structure', 'members' => ['DeviceArn' => ['shape' => 'Arn'], 'DeviceName' => ['shape' => 'DeviceName']]], 'UpdateDeviceResponse' => ['type' => 'structure', 'members' => []], 'UpdateEndOfMeetingReminder' => ['type' => 'structure', 'members' => ['ReminderAtMinutes' => ['shape' => 'EndOfMeetingReminderMinutesList'], 'ReminderType' => ['shape' => 'EndOfMeetingReminderType'], 'Enabled' => ['shape' => 'Boolean']]], 'UpdateGatewayGroupRequest' => ['type' => 'structure', 'required' => ['GatewayGroupArn'], 'members' => ['GatewayGroupArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'GatewayGroupName'], 'Description' => ['shape' => 'GatewayGroupDescription']]], 'UpdateGatewayGroupResponse' => ['type' => 'structure', 'members' => []], 'UpdateGatewayRequest' => ['type' => 'structure', 'required' => ['GatewayArn'], 'members' => ['GatewayArn' => ['shape' => 'Arn'], 'Name' => ['shape' => 'GatewayName'], 'Description' => ['shape' => 'GatewayDescription'], 'SoftwareVersion' => ['shape' => 'GatewayVersion']]], 'UpdateGatewayResponse' => ['type' => 'structure', 'members' => []], 'UpdateInstantBooking' => ['type' => 'structure', 'members' => ['DurationInMinutes' => ['shape' => 'Minutes'], 'Enabled' => ['shape' => 'Boolean']]], 'UpdateMeetingRoomConfiguration' => ['type' => 'structure', 'members' => ['RoomUtilizationMetricsEnabled' => ['shape' => 'Boolean'], 'EndOfMeetingReminder' => ['shape' => 'UpdateEndOfMeetingReminder'], 'InstantBooking' => ['shape' => 'UpdateInstantBooking'], 'RequireCheckIn' => ['shape' => 'UpdateRequireCheckIn']]], 'UpdateNetworkProfileRequest' => ['type' => 'structure', 'required' => ['NetworkProfileArn'], 'members' => ['NetworkProfileArn' => ['shape' => 'Arn'], 'NetworkProfileName' => ['shape' => 'NetworkProfileName'], 'Description' => ['shape' => 'NetworkProfileDescription'], 'CurrentPassword' => ['shape' => 'CurrentWiFiPassword'], 'NextPassword' => ['shape' => 'NextWiFiPassword'], 'CertificateAuthorityArn' => ['shape' => 'Arn'], 'TrustAnchors' => ['shape' => 'TrustAnchorList']]], 'UpdateNetworkProfileResponse' => ['type' => 'structure', 'members' => []], 'UpdateProfileRequest' => ['type' => 'structure', 'members' => ['ProfileArn' => ['shape' => 'Arn'], 'ProfileName' => ['shape' => 'ProfileName'], 'IsDefault' => ['shape' => 'Boolean'], 'Timezone' => ['shape' => 'Timezone'], 'Address' => ['shape' => 'Address'], 'DistanceUnit' => ['shape' => 'DistanceUnit'], 'TemperatureUnit' => ['shape' => 'TemperatureUnit'], 'WakeWord' => ['shape' => 'WakeWord'], 'Locale' => ['shape' => 'DeviceLocale'], 'SetupModeDisabled' => ['shape' => 'Boolean'], 'MaxVolumeLimit' => ['shape' => 'MaxVolumeLimit'], 'PSTNEnabled' => ['shape' => 'Boolean'], 'MeetingRoomConfiguration' => ['shape' => 'UpdateMeetingRoomConfiguration']]], 'UpdateProfileResponse' => ['type' => 'structure', 'members' => []], 'UpdateRequireCheckIn' => ['type' => 'structure', 'members' => ['ReleaseAfterMinutes' => ['shape' => 'Minutes'], 'Enabled' => ['shape' => 'Boolean']]], 'UpdateRoomRequest' => ['type' => 'structure', 'members' => ['RoomArn' => ['shape' => 'Arn'], 'RoomName' => ['shape' => 'RoomName'], 'Description' => ['shape' => 'RoomDescription'], 'ProviderCalendarId' => ['shape' => 'ProviderCalendarId'], 'ProfileArn' => ['shape' => 'Arn']]], 'UpdateRoomResponse' => ['type' => 'structure', 'members' => []], 'UpdateSkillGroupRequest' => ['type' => 'structure', 'members' => ['SkillGroupArn' => ['shape' => 'Arn'], 'SkillGroupName' => ['shape' => 'SkillGroupName'], 'Description' => ['shape' => 'SkillGroupDescription']]], 'UpdateSkillGroupResponse' => ['type' => 'structure', 'members' => []], 'Url' => ['type' => 'string'], 'UserCode' => ['type' => 'string', 'max' => 128, 'min' => 1], 'UserData' => ['type' => 'structure', 'members' => ['UserArn' => ['shape' => 'Arn'], 'FirstName' => ['shape' => 'user_FirstName'], 'LastName' => ['shape' => 'user_LastName'], 'Email' => ['shape' => 'Email'], 'EnrollmentStatus' => ['shape' => 'EnrollmentStatus'], 'EnrollmentId' => ['shape' => 'EnrollmentId']]], 'UserDataList' => ['type' => 'list', 'member' => ['shape' => 'UserData']], 'UserId' => ['type' => 'string', 'pattern' => 'amzn1\\.[A-Za-z0-9+-\\/=.]{1,300}'], 'Utterance' => ['type' => 'string'], 'Value' => ['type' => 'string', 'min' => 1], 'WakeWord' => ['type' => 'string', 'enum' => ['ALEXA', 'AMAZON', 'ECHO', 'COMPUTER']], 'boolean' => ['type' => 'boolean'], 'user_FirstName' => ['type' => 'string', 'max' => 30, 'min' => 0, 'pattern' => '([A-Za-z\\-\' 0-9._]|\\p{IsLetter})*'], 'user_LastName' => ['type' => 'string', 'max' => 30, 'min' => 0, 'pattern' => '([A-Za-z\\-\' 0-9._]|\\p{IsLetter})*'], 'user_UserId' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '[a-zA-Z0-9@_+.-]*']]];
|
@@ -1,4 +1,4 @@
|
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/alexaforbusiness/2017-11-09/paginators-1.json
|
4 |
-
return ['pagination' => ['ListBusinessReportSchedules' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListConferenceProviders' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListDeviceEvents' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSkills' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSkillsStoreCategories' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSkillsStoreSkillsByCategory' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSmartHomeAppliances' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListTags' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchAddressBooks' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchContacts' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchDevices' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchProfiles' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchRooms' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchSkillGroups' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchUsers' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults']]];
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/alexaforbusiness/2017-11-09/paginators-1.json
|
4 |
+
return ['pagination' => ['ListBusinessReportSchedules' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListConferenceProviders' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListDeviceEvents' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListGatewayGroups' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListGateways' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSkills' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSkillsStoreCategories' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSkillsStoreSkillsByCategory' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListSmartHomeAppliances' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'ListTags' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchAddressBooks' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchContacts' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchDevices' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchNetworkProfiles' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchProfiles' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchRooms' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchSkillGroups' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults'], 'SearchUsers' => ['input_token' => 'NextToken', 'output_token' => 'NextToken', 'limit_key' => 'MaxResults']]];
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// This file was auto-generated from sdk-root/src/data/aliases.json
|
4 |
+
return ['operations' => ['ApiGatewayV2' => ['2018-11-29' => ['GetApi' => 'GetApiResource']], 'CloudHSM' => ['2014-05-30' => ['GetConfig' => 'GetConfigFiles']], 'GroundStation' => ['2019-05-23' => ['GetConfig' => 'GetMissionProfileConfig']], 'Pinpoint' => ['2016-12-01' => ['GetEndpoint' => 'GetUserEndpoint', 'UpdateEndpoint' => 'UpdateUserEndpoint', 'UpdateEndpointsBatch' => 'UpdateUserEndpointsBatch']]]];
|
@@ -1,4 +1,4 @@
|
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/amplify/2017-07-25/api-2.json
|
4 |
-
return ['version' => '2.0', 'metadata' => ['apiVersion' => '2017-07-25', 'endpointPrefix' => 'amplify', 'jsonVersion' => '1.1', 'protocol' => 'rest-json', 'serviceAbbreviation' => 'Amplify', 'serviceFullName' => 'AWS Amplify', 'serviceId' => 'Amplify', 'signatureVersion' => 'v4', 'signingName' => 'amplify', 'uid' => 'amplify-2017-07-25'], 'operations' => ['CreateApp' => ['name' => 'CreateApp', 'http' => ['method' => 'POST', 'requestUri' => '/apps'], 'input' => ['shape' => 'CreateAppRequest'], 'output' => ['shape' => 'CreateAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'CreateBranch' => ['name' => 'CreateBranch', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches'], 'input' => ['shape' => 'CreateBranchRequest'], 'output' => ['shape' => 'CreateBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'CreateDomainAssociation' => ['name' => 'CreateDomainAssociation', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/domains'], 'input' => ['shape' => 'CreateDomainAssociationRequest'], 'output' => ['shape' => 'CreateDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteApp' => ['name' => 'DeleteApp', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}'], 'input' => ['shape' => 'DeleteAppRequest'], 'output' => ['shape' => 'DeleteAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'NotFoundException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteBranch' => ['name' => 'DeleteBranch', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/branches/{branchName}'], 'input' => ['shape' => 'DeleteBranchRequest'], 'output' => ['shape' => 'DeleteBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteDomainAssociation' => ['name' => 'DeleteDomainAssociation', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/domains/{domainName}'], 'input' => ['shape' => 'DeleteDomainAssociationRequest'], 'output' => ['shape' => 'DeleteDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteJob' => ['name' => 'DeleteJob', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}'], 'input' => ['shape' => 'DeleteJobRequest'], 'output' => ['shape' => 'DeleteJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'GetApp' => ['name' => 'GetApp', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}'], 'input' => ['shape' => 'GetAppRequest'], 'output' => ['shape' => 'GetAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'NotFoundException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'GetBranch' => ['name' => 'GetBranch', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}'], 'input' => ['shape' => 'GetBranchRequest'], 'output' => ['shape' => 'GetBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException']]], 'GetDomainAssociation' => ['name' => 'GetDomainAssociation', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/domains/{domainName}'], 'input' => ['shape' => 'GetDomainAssociationRequest'], 'output' => ['shape' => 'GetDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException']]], 'GetJob' => ['name' => 'GetJob', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}'], 'input' => ['shape' => 'GetJobRequest'], 'output' => ['shape' => 'GetJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'ListApps' => ['name' => 'ListApps', 'http' => ['method' => 'GET', 'requestUri' => '/apps'], 'input' => ['shape' => 'ListAppsRequest'], 'output' => ['shape' => 'ListAppsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListBranches' => ['name' => 'ListBranches', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches'], 'input' => ['shape' => 'ListBranchesRequest'], 'output' => ['shape' => 'ListBranchesResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListDomainAssociations' => ['name' => 'ListDomainAssociations', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/domains'], 'input' => ['shape' => 'ListDomainAssociationsRequest'], 'output' => ['shape' => 'ListDomainAssociationsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListJobs' => ['name' => 'ListJobs', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs'], 'input' => ['shape' => 'ListJobsRequest'], 'output' => ['shape' => 'ListJobsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException']]], 'StartJob' => ['name' => 'StartJob', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs'], 'input' => ['shape' => 'StartJobRequest'], 'output' => ['shape' => 'StartJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'StopJob' => ['name' => 'StopJob', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}/stop'], 'input' => ['shape' => 'StopJobRequest'], 'output' => ['shape' => 'StopJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'UpdateApp' => ['name' => 'UpdateApp', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}'], 'input' => ['shape' => 'UpdateAppRequest'], 'output' => ['shape' => 'UpdateAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'NotFoundException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'UpdateBranch' => ['name' => 'UpdateBranch', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches/{branchName}'], 'input' => ['shape' => 'UpdateBranchRequest'], 'output' => ['shape' => 'UpdateBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'UpdateDomainAssociation' => ['name' => 'UpdateDomainAssociation', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/domains/{domainName}'], 'input' => ['shape' => 'UpdateDomainAssociationRequest'], 'output' => ['shape' => 'UpdateDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]]], 'shapes' => ['ActiveJobId' => ['type' => 'string', 'max' => 1000], 'App' => ['type' => 'structure', 'required' => ['appId', 'appArn', 'name', 'description', 'repository', 'platform', 'createTime', 'updateTime', 'environmentVariables', 'defaultDomain', 'enableBranchAutoBuild', 'enableBasicAuth'], 'members' => ['appId' => ['shape' => 'AppId'], 'appArn' => ['shape' => 'AppArn'], 'name' => ['shape' => 'Name'], 'tags' => ['shape' => 'Tags'], 'description' => ['shape' => 'Description'], 'repository' => ['shape' => 'Repository'], 'platform' => ['shape' => 'Platform'], 'createTime' => ['shape' => 'CreateTime'], 'updateTime' => ['shape' => 'UpdateTime'], 'iamServiceRoleArn' => ['shape' => 'ServiceRoleArn'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'defaultDomain' => ['shape' => 'DefaultDomain'], 'enableBranchAutoBuild' => ['shape' => 'EnableBranchAutoBuild'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'customRules' => ['shape' => 'CustomRules'], 'productionBranch' => ['shape' => 'ProductionBranch'], 'buildSpec' => ['shape' => 'BuildSpec']]], 'AppArn' => ['type' => 'string', 'max' => 1000], 'AppId' => ['type' => 'string', 'max' => 255, 'min' => 1], 'Apps' => ['type' => 'list', 'member' => ['shape' => 'App']], 'ArtifactsUrl' => ['type' => 'string', 'max' => 1000], 'BadRequestException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 400], 'exception' => \true], 'BasicAuthCredentials' => ['type' => 'string', 'max' => 2000], 'Branch' => ['type' => 'structure', 'required' => ['branchArn', 'branchName', 'description', 'stage', 'enableNotification', 'createTime', 'updateTime', 'environmentVariables', 'enableAutoBuild', 'customDomains', 'framework', 'activeJobId', 'totalNumberOfJobs', 'enableBasicAuth', 'ttl'], 'members' => ['branchArn' => ['shape' => 'BranchArn'], 'branchName' => ['shape' => 'BranchName'], 'description' => ['shape' => 'Description'], 'tags' => ['shape' => 'Tags'], 'stage' => ['shape' => 'Stage'], 'displayName' => ['shape' => 'DisplayName'], 'enableNotification' => ['shape' => 'EnableNotification'], 'createTime' => ['shape' => 'CreateTime'], 'updateTime' => ['shape' => 'UpdateTime'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'customDomains' => ['shape' => 'CustomDomains'], 'framework' => ['shape' => 'Framework'], 'activeJobId' => ['shape' => 'ActiveJobId'], 'totalNumberOfJobs' => ['shape' => 'TotalNumberOfJobs'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'thumbnailUrl' => ['shape' => 'ThumbnailUrl'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'buildSpec' => ['shape' => 'BuildSpec'], 'ttl' => ['shape' => 'TTL']]], 'BranchArn' => ['type' => 'string', 'max' => 1000], 'BranchName' => ['type' => 'string', 'max' => 255, 'min' => 1], 'Branches' => ['type' => 'list', 'member' => ['shape' => 'Branch'], 'max' => 255], 'BuildSpec' => ['type' => 'string', 'max' => 25000, 'min' => 1], 'CertificateVerificationDNSRecord' => ['type' => 'string', 'max' => 1000], 'CommitId' => ['type' => 'string', 'max' => 255], 'CommitMessage' => ['type' => 'string', 'max' => 10000], 'CommitTime' => ['type' => 'timestamp'], 'Condition' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'CreateAppRequest' => ['type' => 'structure', 'required' => ['name', 'repository', 'platform', 'oauthToken'], 'members' => ['name' => ['shape' => 'Name'], 'description' => ['shape' => 'Description'], 'repository' => ['shape' => 'Repository'], 'platform' => ['shape' => 'Platform'], 'iamServiceRoleArn' => ['shape' => 'ServiceRoleArn'], 'oauthToken' => ['shape' => 'OauthToken'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'enableBranchAutoBuild' => ['shape' => 'EnableBranchAutoBuild'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'customRules' => ['shape' => 'CustomRules'], 'tags' => ['shape' => 'Tags'], 'buildSpec' => ['shape' => 'BuildSpec']]], 'CreateAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'CreateBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName'], 'description' => ['shape' => 'Description'], 'stage' => ['shape' => 'Stage'], 'framework' => ['shape' => 'Framework'], 'enableNotification' => ['shape' => 'EnableNotification'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'tags' => ['shape' => 'Tags'], 'buildSpec' => ['shape' => 'BuildSpec'], 'ttl' => ['shape' => 'TTL']]], 'CreateBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'CreateDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName', 'subDomainSettings'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName'], 'enableAutoSubDomain' => ['shape' => 'EnableAutoSubDomain'], 'subDomainSettings' => ['shape' => 'SubDomainSettings']]], 'CreateDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'CreateTime' => ['type' => 'timestamp'], 'CustomDomain' => ['type' => 'string', 'max' => 255], 'CustomDomains' => ['type' => 'list', 'member' => ['shape' => 'CustomDomain'], 'max' => 255], 'CustomRule' => ['type' => 'structure', 'required' => ['source', 'target'], 'members' => ['source' => ['shape' => 'Source'], 'target' => ['shape' => 'Target'], 'status' => ['shape' => 'Status'], 'condition' => ['shape' => 'Condition']]], 'CustomRules' => ['type' => 'list', 'member' => ['shape' => 'CustomRule']], 'DNSRecord' => ['type' => 'string', 'max' => 1000], 'DefaultDomain' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'DeleteAppRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId']]], 'DeleteAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'DeleteBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName']]], 'DeleteBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'DeleteDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName', 'location' => 'uri', 'locationName' => 'domainName']]], 'DeleteDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'DeleteJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId']]], 'DeleteJobResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'DependentServiceFailureException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 503], 'exception' => \true], 'Description' => ['type' => 'string', 'max' => 1000], 'DisplayName' => ['type' => 'string', 'max' => 255], 'DomainAssociation' => ['type' => 'structure', 'required' => ['domainAssociationArn', 'domainName', 'enableAutoSubDomain', 'domainStatus', 'statusReason', 'certificateVerificationDNSRecord', 'subDomains'], 'members' => ['domainAssociationArn' => ['shape' => 'DomainAssociationArn'], 'domainName' => ['shape' => 'DomainName'], 'enableAutoSubDomain' => ['shape' => 'EnableAutoSubDomain'], 'domainStatus' => ['shape' => 'DomainStatus'], 'statusReason' => ['shape' => 'StatusReason'], 'certificateVerificationDNSRecord' => ['shape' => 'CertificateVerificationDNSRecord'], 'subDomains' => ['shape' => 'SubDomains']]], 'DomainAssociationArn' => ['type' => 'string', 'max' => 1000], 'DomainAssociations' => ['type' => 'list', 'member' => ['shape' => 'DomainAssociation'], 'max' => 255], 'DomainName' => ['type' => 'string', 'max' => 255], 'DomainPrefix' => ['type' => 'string', 'max' => 255], 'DomainStatus' => ['type' => 'string', 'enum' => ['PENDING_VERIFICATION', 'IN_PROGRESS', 'AVAILABLE', 'PENDING_DEPLOYMENT', 'FAILED']], 'EnableAutoBuild' => ['type' => 'boolean'], 'EnableAutoSubDomain' => ['type' => 'boolean'], 'EnableBasicAuth' => ['type' => 'boolean'], 'EnableBranchAutoBuild' => ['type' => 'boolean'], 'EnableNotification' => ['type' => 'boolean'], 'EndTime' => ['type' => 'timestamp'], 'EnvKey' => ['type' => 'string', 'max' => 255], 'EnvValue' => ['type' => 'string', 'max' => 1000], 'EnvironmentVariables' => ['type' => 'map', 'key' => ['shape' => 'EnvKey'], 'value' => ['shape' => 'EnvValue']], 'ErrorMessage' => ['type' => 'string', 'max' => 255], 'Framework' => ['type' => 'string', 'max' => 255], 'GetAppRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId']]], 'GetAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'GetBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName']]], 'GetBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'GetDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName', 'location' => 'uri', 'locationName' => 'domainName']]], 'GetDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'GetJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId']]], 'GetJobResult' => ['type' => 'structure', 'required' => ['job'], 'members' => ['job' => ['shape' => 'Job']]], 'InternalFailureException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 500], 'exception' => \true, 'fault' => \true], 'Job' => ['type' => 'structure', 'required' => ['summary', 'steps'], 'members' => ['summary' => ['shape' => 'JobSummary'], 'steps' => ['shape' => 'Steps']]], 'JobArn' => ['type' => 'string', 'max' => 1000], 'JobId' => ['type' => 'string', 'max' => 255], 'JobReason' => ['type' => 'string', 'max' => 255], 'JobStatus' => ['type' => 'string', 'enum' => ['PENDING', 'PROVISIONING', 'RUNNING', 'FAILED', 'SUCCEED', 'CANCELLING', 'CANCELLED']], 'JobSummaries' => ['type' => 'list', 'member' => ['shape' => 'JobSummary']], 'JobSummary' => ['type' => 'structure', 'required' => ['jobArn', 'jobId', 'commitId', 'commitMessage', 'commitTime', 'startTime', 'status', 'jobType'], 'members' => ['jobArn' => ['shape' => 'JobArn'], 'jobId' => ['shape' => 'JobId'], 'commitId' => ['shape' => 'CommitId'], 'commitMessage' => ['shape' => 'CommitMessage'], 'commitTime' => ['shape' => 'CommitTime'], 'startTime' => ['shape' => 'StartTime'], 'status' => ['shape' => 'JobStatus'], 'endTime' => ['shape' => 'EndTime'], 'jobType' => ['shape' => 'JobType']]], 'JobType' => ['type' => 'string', 'enum' => ['RELEASE', 'RETRY', 'WEB_HOOK'], 'max' => 10], 'LastDeployTime' => ['type' => 'timestamp'], 'LimitExceededException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 429], 'exception' => \true], 'ListAppsRequest' => ['type' => 'structure', 'members' => ['nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListAppsResult' => ['type' => 'structure', 'required' => ['apps'], 'members' => ['apps' => ['shape' => 'Apps'], 'nextToken' => ['shape' => 'NextToken']]], 'ListBranchesRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListBranchesResult' => ['type' => 'structure', 'required' => ['branches'], 'members' => ['branches' => ['shape' => 'Branches'], 'nextToken' => ['shape' => 'NextToken']]], 'ListDomainAssociationsRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListDomainAssociationsResult' => ['type' => 'structure', 'required' => ['domainAssociations'], 'members' => ['domainAssociations' => ['shape' => 'DomainAssociations'], 'nextToken' => ['shape' => 'NextToken']]], 'ListJobsRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListJobsResult' => ['type' => 'structure', 'required' => ['jobSummaries'], 'members' => ['jobSummaries' => ['shape' => 'JobSummaries'], 'nextToken' => ['shape' => 'NextToken']]], 'LogUrl' => ['type' => 'string', 'max' => 1000], 'MaxResults' => ['type' => 'integer', 'max' => 100, 'min' => 1], 'Name' => ['type' => 'string', 'max' => 255, 'min' => 1], 'NextToken' => ['type' => 'string', 'max' => 2000], 'NotFoundException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 404], 'exception' => \true], 'OauthToken' => ['type' => 'string', 'max' => 100], 'Platform' => ['type' => 'string', 'enum' => ['IOS', 'ANDROID', 'WEB', 'REACT_NATIVE']], 'ProductionBranch' => ['type' => 'structure', 'members' => ['lastDeployTime' => ['shape' => 'LastDeployTime'], 'status' => ['shape' => 'Status'], 'thumbnailUrl' => ['shape' => 'ThumbnailUrl'], 'branchName' => ['shape' => 'BranchName']]], 'Repository' => ['type' => 'string', 'max' => 1000], 'Screenshots' => ['type' => 'map', 'key' => ['shape' => 'ThumbnailName'], 'value' => ['shape' => 'ThumbnailUrl']], 'ServiceRoleArn' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'Source' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'Stage' => ['type' => 'string', 'enum' => ['PRODUCTION', 'BETA', 'DEVELOPMENT', 'EXPERIMENTAL']], 'StartJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobType'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId'], 'jobType' => ['shape' => 'JobType'], 'jobReason' => ['shape' => 'JobReason'], 'commitId' => ['shape' => 'CommitId'], 'commitMessage' => ['shape' => 'CommitMessage'], 'commitTime' => ['shape' => 'CommitTime']]], 'StartJobResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'StartTime' => ['type' => 'timestamp'], 'Status' => ['type' => 'string', 'max' => 3, 'min' => 3], 'StatusReason' => ['type' => 'string', 'max' => 1000], 'Step' => ['type' => 'structure', 'required' => ['stepName', 'startTime', 'status', 'endTime'], 'members' => ['stepName' => ['shape' => 'StepName'], 'startTime' => ['shape' => 'StartTime'], 'status' => ['shape' => 'JobStatus'], 'endTime' => ['shape' => 'EndTime'], 'logUrl' => ['shape' => 'LogUrl'], 'artifactsUrl' => ['shape' => 'ArtifactsUrl'], 'screenshots' => ['shape' => 'Screenshots']]], 'StepName' => ['type' => 'string', 'max' => 255], 'Steps' => ['type' => 'list', 'member' => ['shape' => 'Step']], 'StopJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId']]], 'StopJobResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'SubDomain' => ['type' => 'structure', 'required' => ['subDomainSetting', 'verified', 'dnsRecord'], 'members' => ['subDomainSetting' => ['shape' => 'SubDomainSetting'], 'verified' => ['shape' => 'Verified'], 'dnsRecord' => ['shape' => 'DNSRecord']]], 'SubDomainSetting' => ['type' => 'structure', 'required' => ['prefix', 'branchName'], 'members' => ['prefix' => ['shape' => 'DomainPrefix'], 'branchName' => ['shape' => 'BranchName']]], 'SubDomainSettings' => ['type' => 'list', 'member' => ['shape' => 'SubDomainSetting'], 'max' => 255], 'SubDomains' => ['type' => 'list', 'member' => ['shape' => 'SubDomain'], 'max' => 255], 'TTL' => ['type' => 'string'], 'TagKey' => ['type' => 'string', 'max' => 1000], 'TagValue' => ['type' => 'string', 'max' => 1000], 'Tags' => ['type' => 'map', 'key' => ['shape' => 'TagKey'], 'value' => ['shape' => 'TagValue']], 'Target' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'ThumbnailName' => ['type' => 'string', 'max' => 256], 'ThumbnailUrl' => ['type' => 'string', 'max' => 2000, 'min' => 1], 'TotalNumberOfJobs' => ['type' => 'string', 'max' => 1000], 'UnauthorizedException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 401], 'exception' => \true], 'UpdateAppRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'name' => ['shape' => 'Name'], 'description' => ['shape' => 'Description'], 'platform' => ['shape' => 'Platform'], 'iamServiceRoleArn' => ['shape' => 'ServiceRoleArn'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'enableBranchAutoBuild' => ['shape' => 'EnableAutoBuild'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'customRules' => ['shape' => 'CustomRules'], 'buildSpec' => ['shape' => 'BuildSpec']]], 'UpdateAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'UpdateBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'description' => ['shape' => 'Description'], 'framework' => ['shape' => 'Framework'], 'stage' => ['shape' => 'Stage'], 'enableNotification' => ['shape' => 'EnableNotification'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'buildSpec' => ['shape' => 'BuildSpec'], 'ttl' => ['shape' => 'TTL']]], 'UpdateBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'UpdateDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName', 'subDomainSettings'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName', 'location' => 'uri', 'locationName' => 'domainName'], 'enableAutoSubDomain' => ['shape' => 'EnableAutoSubDomain'], 'subDomainSettings' => ['shape' => 'SubDomainSettings']]], 'UpdateDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'UpdateTime' => ['type' => 'timestamp'], 'Verified' => ['type' => 'boolean']]];
|
1 |
<?php
|
2 |
|
3 |
// This file was auto-generated from sdk-root/src/data/amplify/2017-07-25/api-2.json
|
4 |
+
return ['version' => '2.0', 'metadata' => ['apiVersion' => '2017-07-25', 'endpointPrefix' => 'amplify', 'jsonVersion' => '1.1', 'protocol' => 'rest-json', 'serviceAbbreviation' => 'Amplify', 'serviceFullName' => 'AWS Amplify', 'serviceId' => 'Amplify', 'signatureVersion' => 'v4', 'signingName' => 'amplify', 'uid' => 'amplify-2017-07-25'], 'operations' => ['CreateApp' => ['name' => 'CreateApp', 'http' => ['method' => 'POST', 'requestUri' => '/apps'], 'input' => ['shape' => 'CreateAppRequest'], 'output' => ['shape' => 'CreateAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'CreateBackendEnvironment' => ['name' => 'CreateBackendEnvironment', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/backendenvironments'], 'input' => ['shape' => 'CreateBackendEnvironmentRequest'], 'output' => ['shape' => 'CreateBackendEnvironmentResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException']]], 'CreateBranch' => ['name' => 'CreateBranch', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches'], 'input' => ['shape' => 'CreateBranchRequest'], 'output' => ['shape' => 'CreateBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'CreateDeployment' => ['name' => 'CreateDeployment', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches/{branchName}/deployments'], 'input' => ['shape' => 'CreateDeploymentRequest'], 'output' => ['shape' => 'CreateDeploymentResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException']]], 'CreateDomainAssociation' => ['name' => 'CreateDomainAssociation', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/domains'], 'input' => ['shape' => 'CreateDomainAssociationRequest'], 'output' => ['shape' => 'CreateDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'CreateWebhook' => ['name' => 'CreateWebhook', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/webhooks'], 'input' => ['shape' => 'CreateWebhookRequest'], 'output' => ['shape' => 'CreateWebhookResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteApp' => ['name' => 'DeleteApp', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}'], 'input' => ['shape' => 'DeleteAppRequest'], 'output' => ['shape' => 'DeleteAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'NotFoundException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteBackendEnvironment' => ['name' => 'DeleteBackendEnvironment', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/backendenvironments/{environmentName}'], 'input' => ['shape' => 'DeleteBackendEnvironmentRequest'], 'output' => ['shape' => 'DeleteBackendEnvironmentResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteBranch' => ['name' => 'DeleteBranch', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/branches/{branchName}'], 'input' => ['shape' => 'DeleteBranchRequest'], 'output' => ['shape' => 'DeleteBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteDomainAssociation' => ['name' => 'DeleteDomainAssociation', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/domains/{domainName}'], 'input' => ['shape' => 'DeleteDomainAssociationRequest'], 'output' => ['shape' => 'DeleteDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'DeleteJob' => ['name' => 'DeleteJob', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}'], 'input' => ['shape' => 'DeleteJobRequest'], 'output' => ['shape' => 'DeleteJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'DeleteWebhook' => ['name' => 'DeleteWebhook', 'http' => ['method' => 'DELETE', 'requestUri' => '/webhooks/{webhookId}'], 'input' => ['shape' => 'DeleteWebhookRequest'], 'output' => ['shape' => 'DeleteWebhookResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'GenerateAccessLogs' => ['name' => 'GenerateAccessLogs', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/accesslogs'], 'input' => ['shape' => 'GenerateAccessLogsRequest'], 'output' => ['shape' => 'GenerateAccessLogsResult'], 'errors' => [['shape' => 'NotFoundException'], ['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'GetApp' => ['name' => 'GetApp', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}'], 'input' => ['shape' => 'GetAppRequest'], 'output' => ['shape' => 'GetAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'NotFoundException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'GetArtifactUrl' => ['name' => 'GetArtifactUrl', 'http' => ['method' => 'GET', 'requestUri' => '/artifacts/{artifactId}'], 'input' => ['shape' => 'GetArtifactUrlRequest'], 'output' => ['shape' => 'GetArtifactUrlResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'GetBackendEnvironment' => ['name' => 'GetBackendEnvironment', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/backendenvironments/{environmentName}'], 'input' => ['shape' => 'GetBackendEnvironmentRequest'], 'output' => ['shape' => 'GetBackendEnvironmentResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException']]], 'GetBranch' => ['name' => 'GetBranch', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}'], 'input' => ['shape' => 'GetBranchRequest'], 'output' => ['shape' => 'GetBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException']]], 'GetDomainAssociation' => ['name' => 'GetDomainAssociation', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/domains/{domainName}'], 'input' => ['shape' => 'GetDomainAssociationRequest'], 'output' => ['shape' => 'GetDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException']]], 'GetJob' => ['name' => 'GetJob', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}'], 'input' => ['shape' => 'GetJobRequest'], 'output' => ['shape' => 'GetJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'GetWebhook' => ['name' => 'GetWebhook', 'http' => ['method' => 'GET', 'requestUri' => '/webhooks/{webhookId}'], 'input' => ['shape' => 'GetWebhookRequest'], 'output' => ['shape' => 'GetWebhookResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'ListApps' => ['name' => 'ListApps', 'http' => ['method' => 'GET', 'requestUri' => '/apps'], 'input' => ['shape' => 'ListAppsRequest'], 'output' => ['shape' => 'ListAppsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListArtifacts' => ['name' => 'ListArtifacts', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}/artifacts'], 'input' => ['shape' => 'ListArtifactsRequest'], 'output' => ['shape' => 'ListArtifactsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException']]], 'ListBackendEnvironments' => ['name' => 'ListBackendEnvironments', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/backendenvironments'], 'input' => ['shape' => 'ListBackendEnvironmentsRequest'], 'output' => ['shape' => 'ListBackendEnvironmentsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListBranches' => ['name' => 'ListBranches', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches'], 'input' => ['shape' => 'ListBranchesRequest'], 'output' => ['shape' => 'ListBranchesResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListDomainAssociations' => ['name' => 'ListDomainAssociations', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/domains'], 'input' => ['shape' => 'ListDomainAssociationsRequest'], 'output' => ['shape' => 'ListDomainAssociationsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'ListJobs' => ['name' => 'ListJobs', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs'], 'input' => ['shape' => 'ListJobsRequest'], 'output' => ['shape' => 'ListJobsResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException']]], 'ListTagsForResource' => ['name' => 'ListTagsForResource', 'http' => ['method' => 'GET', 'requestUri' => '/tags/{resourceArn}'], 'input' => ['shape' => 'ListTagsForResourceRequest'], 'output' => ['shape' => 'ListTagsForResourceResponse'], 'errors' => [['shape' => 'InternalFailureException'], ['shape' => 'BadRequestException'], ['shape' => 'ResourceNotFoundException']]], 'ListWebhooks' => ['name' => 'ListWebhooks', 'http' => ['method' => 'GET', 'requestUri' => '/apps/{appId}/webhooks'], 'input' => ['shape' => 'ListWebhooksRequest'], 'output' => ['shape' => 'ListWebhooksResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'LimitExceededException']]], 'StartDeployment' => ['name' => 'StartDeployment', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches/{branchName}/deployments/start'], 'input' => ['shape' => 'StartDeploymentRequest'], 'output' => ['shape' => 'StartDeploymentResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'StartJob' => ['name' => 'StartJob', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs'], 'input' => ['shape' => 'StartJobRequest'], 'output' => ['shape' => 'StartJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'StopJob' => ['name' => 'StopJob', 'http' => ['method' => 'DELETE', 'requestUri' => '/apps/{appId}/branches/{branchName}/jobs/{jobId}/stop'], 'input' => ['shape' => 'StopJobRequest'], 'output' => ['shape' => 'StopJobResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException'], ['shape' => 'NotFoundException'], ['shape' => 'LimitExceededException']]], 'TagResource' => ['name' => 'TagResource', 'http' => ['method' => 'POST', 'requestUri' => '/tags/{resourceArn}'], 'input' => ['shape' => 'TagResourceRequest'], 'output' => ['shape' => 'TagResourceResponse'], 'errors' => [['shape' => 'InternalFailureException'], ['shape' => 'BadRequestException'], ['shape' => 'ResourceNotFoundException']]], 'UntagResource' => ['name' => 'UntagResource', 'http' => ['method' => 'DELETE', 'requestUri' => '/tags/{resourceArn}'], 'input' => ['shape' => 'UntagResourceRequest'], 'output' => ['shape' => 'UntagResourceResponse'], 'errors' => [['shape' => 'InternalFailureException'], ['shape' => 'BadRequestException'], ['shape' => 'ResourceNotFoundException']]], 'UpdateApp' => ['name' => 'UpdateApp', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}'], 'input' => ['shape' => 'UpdateAppRequest'], 'output' => ['shape' => 'UpdateAppResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'NotFoundException'], ['shape' => 'UnauthorizedException'], ['shape' => 'InternalFailureException']]], 'UpdateBranch' => ['name' => 'UpdateBranch', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/branches/{branchName}'], 'input' => ['shape' => 'UpdateBranchRequest'], 'output' => ['shape' => 'UpdateBranchResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'UpdateDomainAssociation' => ['name' => 'UpdateDomainAssociation', 'http' => ['method' => 'POST', 'requestUri' => '/apps/{appId}/domains/{domainName}'], 'input' => ['shape' => 'UpdateDomainAssociationRequest'], 'output' => ['shape' => 'UpdateDomainAssociationResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]], 'UpdateWebhook' => ['name' => 'UpdateWebhook', 'http' => ['method' => 'POST', 'requestUri' => '/webhooks/{webhookId}'], 'input' => ['shape' => 'UpdateWebhookRequest'], 'output' => ['shape' => 'UpdateWebhookResult'], 'errors' => [['shape' => 'BadRequestException'], ['shape' => 'UnauthorizedException'], ['shape' => 'NotFoundException'], ['shape' => 'InternalFailureException'], ['shape' => 'DependentServiceFailureException']]]], 'shapes' => ['AccessToken' => ['type' => 'string', 'max' => 255, 'min' => 1], 'ActiveJobId' => ['type' => 'string', 'max' => 1000], 'App' => ['type' => 'structure', 'required' => ['appId', 'appArn', 'name', 'description', 'repository', 'platform', 'createTime', 'updateTime', 'environmentVariables', 'defaultDomain', 'enableBranchAutoBuild', 'enableBasicAuth'], 'members' => ['appId' => ['shape' => 'AppId'], 'appArn' => ['shape' => 'AppArn'], 'name' => ['shape' => 'Name'], 'tags' => ['shape' => 'TagMap'], 'description' => ['shape' => 'Description'], 'repository' => ['shape' => 'Repository'], 'platform' => ['shape' => 'Platform'], 'createTime' => ['shape' => 'CreateTime'], 'updateTime' => ['shape' => 'UpdateTime'], 'iamServiceRoleArn' => ['shape' => 'ServiceRoleArn'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'defaultDomain' => ['shape' => 'DefaultDomain'], 'enableBranchAutoBuild' => ['shape' => 'EnableBranchAutoBuild'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'customRules' => ['shape' => 'CustomRules'], 'productionBranch' => ['shape' => 'ProductionBranch'], 'buildSpec' => ['shape' => 'BuildSpec'], 'enableAutoBranchCreation' => ['shape' => 'EnableAutoBranchCreation'], 'autoBranchCreationPatterns' => ['shape' => 'AutoBranchCreationPatterns'], 'autoBranchCreationConfig' => ['shape' => 'AutoBranchCreationConfig']]], 'AppArn' => ['type' => 'string', 'max' => 1000], 'AppId' => ['type' => 'string', 'max' => 255, 'min' => 1], 'Apps' => ['type' => 'list', 'member' => ['shape' => 'App']], 'Artifact' => ['type' => 'structure', 'required' => ['artifactFileName', 'artifactId'], 'members' => ['artifactFileName' => ['shape' => 'ArtifactFileName'], 'artifactId' => ['shape' => 'ArtifactId']]], 'ArtifactFileName' => ['type' => 'string', 'max' => 1000], 'ArtifactId' => ['type' => 'string', 'max' => 255], 'ArtifactUrl' => ['type' => 'string', 'max' => 1000], 'Artifacts' => ['type' => 'list', 'member' => ['shape' => 'Artifact']], 'ArtifactsUrl' => ['type' => 'string', 'max' => 1000], 'AssociatedResource' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'AssociatedResources' => ['type' => 'list', 'member' => ['shape' => 'AssociatedResource']], 'AutoBranchCreationConfig' => ['type' => 'structure', 'members' => ['stage' => ['shape' => 'Stage'], 'framework' => ['shape' => 'Framework'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'buildSpec' => ['shape' => 'BuildSpec'], 'enablePullRequestPreview' => ['shape' => 'EnablePullRequestPreview'], 'pullRequestEnvironmentName' => ['shape' => 'PullRequestEnvironmentName']]], 'AutoBranchCreationPattern' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'AutoBranchCreationPatterns' => ['type' => 'list', 'member' => ['shape' => 'AutoBranchCreationPattern']], 'BackendEnvironment' => ['type' => 'structure', 'required' => ['backendEnvironmentArn', 'environmentName', 'createTime', 'updateTime'], 'members' => ['backendEnvironmentArn' => ['shape' => 'BackendEnvironmentArn'], 'environmentName' => ['shape' => 'EnvironmentName'], 'stackName' => ['shape' => 'StackName'], 'deploymentArtifacts' => ['shape' => 'DeploymentArtifacts'], 'createTime' => ['shape' => 'CreateTime'], 'updateTime' => ['shape' => 'UpdateTime']]], 'BackendEnvironmentArn' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'BackendEnvironments' => ['type' => 'list', 'member' => ['shape' => 'BackendEnvironment']], 'BadRequestException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 400], 'exception' => \true], 'BasicAuthCredentials' => ['type' => 'string', 'max' => 2000], 'Branch' => ['type' => 'structure', 'required' => ['branchArn', 'branchName', 'description', 'stage', 'displayName', 'enableNotification', 'createTime', 'updateTime', 'environmentVariables', 'enableAutoBuild', 'customDomains', 'framework', 'activeJobId', 'totalNumberOfJobs', 'enableBasicAuth', 'ttl', 'enablePullRequestPreview'], 'members' => ['branchArn' => ['shape' => 'BranchArn'], 'branchName' => ['shape' => 'BranchName'], 'description' => ['shape' => 'Description'], 'tags' => ['shape' => 'TagMap'], 'stage' => ['shape' => 'Stage'], 'displayName' => ['shape' => 'DisplayName'], 'enableNotification' => ['shape' => 'EnableNotification'], 'createTime' => ['shape' => 'CreateTime'], 'updateTime' => ['shape' => 'UpdateTime'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'customDomains' => ['shape' => 'CustomDomains'], 'framework' => ['shape' => 'Framework'], 'activeJobId' => ['shape' => 'ActiveJobId'], 'totalNumberOfJobs' => ['shape' => 'TotalNumberOfJobs'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'thumbnailUrl' => ['shape' => 'ThumbnailUrl'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'buildSpec' => ['shape' => 'BuildSpec'], 'ttl' => ['shape' => 'TTL'], 'associatedResources' => ['shape' => 'AssociatedResources'], 'enablePullRequestPreview' => ['shape' => 'EnablePullRequestPreview'], 'pullRequestEnvironmentName' => ['shape' => 'PullRequestEnvironmentName'], 'destinationBranch' => ['shape' => 'BranchName'], 'sourceBranch' => ['shape' => 'BranchName'], 'backendEnvironmentArn' => ['shape' => 'BackendEnvironmentArn']]], 'BranchArn' => ['type' => 'string', 'max' => 1000], 'BranchName' => ['type' => 'string', 'max' => 255, 'min' => 1], 'Branches' => ['type' => 'list', 'member' => ['shape' => 'Branch'], 'max' => 255], 'BuildSpec' => ['type' => 'string', 'max' => 25000, 'min' => 1], 'CertificateVerificationDNSRecord' => ['type' => 'string', 'max' => 1000], 'Code' => ['type' => 'string'], 'CommitId' => ['type' => 'string', 'max' => 255], 'CommitMessage' => ['type' => 'string', 'max' => 10000], 'CommitTime' => ['type' => 'timestamp'], 'Condition' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'Context' => ['type' => 'string'], 'CreateAppRequest' => ['type' => 'structure', 'required' => ['name'], 'members' => ['name' => ['shape' => 'Name'], 'description' => ['shape' => 'Description'], 'repository' => ['shape' => 'Repository'], 'platform' => ['shape' => 'Platform'], 'iamServiceRoleArn' => ['shape' => 'ServiceRoleArn'], 'oauthToken' => ['shape' => 'OauthToken'], 'accessToken' => ['shape' => 'AccessToken'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'enableBranchAutoBuild' => ['shape' => 'EnableBranchAutoBuild'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'customRules' => ['shape' => 'CustomRules'], 'tags' => ['shape' => 'TagMap'], 'buildSpec' => ['shape' => 'BuildSpec'], 'enableAutoBranchCreation' => ['shape' => 'EnableAutoBranchCreation'], 'autoBranchCreationPatterns' => ['shape' => 'AutoBranchCreationPatterns'], 'autoBranchCreationConfig' => ['shape' => 'AutoBranchCreationConfig']]], 'CreateAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'CreateBackendEnvironmentRequest' => ['type' => 'structure', 'required' => ['appId', 'environmentName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'environmentName' => ['shape' => 'EnvironmentName'], 'stackName' => ['shape' => 'StackName'], 'deploymentArtifacts' => ['shape' => 'DeploymentArtifacts']]], 'CreateBackendEnvironmentResult' => ['type' => 'structure', 'required' => ['backendEnvironment'], 'members' => ['backendEnvironment' => ['shape' => 'BackendEnvironment']]], 'CreateBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName'], 'description' => ['shape' => 'Description'], 'stage' => ['shape' => 'Stage'], 'framework' => ['shape' => 'Framework'], 'enableNotification' => ['shape' => 'EnableNotification'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'tags' => ['shape' => 'TagMap'], 'buildSpec' => ['shape' => 'BuildSpec'], 'ttl' => ['shape' => 'TTL'], 'displayName' => ['shape' => 'DisplayName'], 'enablePullRequestPreview' => ['shape' => 'EnablePullRequestPreview'], 'pullRequestEnvironmentName' => ['shape' => 'PullRequestEnvironmentName'], 'backendEnvironmentArn' => ['shape' => 'BackendEnvironmentArn']]], 'CreateBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'CreateDeploymentRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'fileMap' => ['shape' => 'FileMap']]], 'CreateDeploymentResult' => ['type' => 'structure', 'required' => ['fileUploadUrls', 'zipUploadUrl'], 'members' => ['jobId' => ['shape' => 'JobId'], 'fileUploadUrls' => ['shape' => 'FileUploadUrls'], 'zipUploadUrl' => ['shape' => 'UploadUrl']]], 'CreateDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName', 'subDomainSettings'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName'], 'enableAutoSubDomain' => ['shape' => 'EnableAutoSubDomain'], 'subDomainSettings' => ['shape' => 'SubDomainSettings']]], 'CreateDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'CreateTime' => ['type' => 'timestamp'], 'CreateWebhookRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName'], 'description' => ['shape' => 'Description']]], 'CreateWebhookResult' => ['type' => 'structure', 'required' => ['webhook'], 'members' => ['webhook' => ['shape' => 'Webhook']]], 'CustomDomain' => ['type' => 'string', 'max' => 255], 'CustomDomains' => ['type' => 'list', 'member' => ['shape' => 'CustomDomain'], 'max' => 255], 'CustomRule' => ['type' => 'structure', 'required' => ['source', 'target'], 'members' => ['source' => ['shape' => 'Source'], 'target' => ['shape' => 'Target'], 'status' => ['shape' => 'Status'], 'condition' => ['shape' => 'Condition']]], 'CustomRules' => ['type' => 'list', 'member' => ['shape' => 'CustomRule']], 'DNSRecord' => ['type' => 'string', 'max' => 1000], 'DefaultDomain' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'DeleteAppRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId']]], 'DeleteAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'DeleteBackendEnvironmentRequest' => ['type' => 'structure', 'required' => ['appId', 'environmentName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'environmentName' => ['shape' => 'EnvironmentName', 'location' => 'uri', 'locationName' => 'environmentName']]], 'DeleteBackendEnvironmentResult' => ['type' => 'structure', 'required' => ['backendEnvironment'], 'members' => ['backendEnvironment' => ['shape' => 'BackendEnvironment']]], 'DeleteBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName']]], 'DeleteBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'DeleteDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName', 'location' => 'uri', 'locationName' => 'domainName']]], 'DeleteDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'DeleteJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId']]], 'DeleteJobResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'DeleteWebhookRequest' => ['type' => 'structure', 'required' => ['webhookId'], 'members' => ['webhookId' => ['shape' => 'WebhookId', 'location' => 'uri', 'locationName' => 'webhookId']]], 'DeleteWebhookResult' => ['type' => 'structure', 'required' => ['webhook'], 'members' => ['webhook' => ['shape' => 'Webhook']]], 'DependentServiceFailureException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 503], 'exception' => \true], 'DeploymentArtifacts' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'Description' => ['type' => 'string', 'max' => 1000], 'DisplayName' => ['type' => 'string', 'max' => 255], 'DomainAssociation' => ['type' => 'structure', 'required' => ['domainAssociationArn', 'domainName', 'enableAutoSubDomain', 'domainStatus', 'statusReason', 'subDomains'], 'members' => ['domainAssociationArn' => ['shape' => 'DomainAssociationArn'], 'domainName' => ['shape' => 'DomainName'], 'enableAutoSubDomain' => ['shape' => 'EnableAutoSubDomain'], 'domainStatus' => ['shape' => 'DomainStatus'], 'statusReason' => ['shape' => 'StatusReason'], 'certificateVerificationDNSRecord' => ['shape' => 'CertificateVerificationDNSRecord'], 'subDomains' => ['shape' => 'SubDomains']]], 'DomainAssociationArn' => ['type' => 'string', 'max' => 1000], 'DomainAssociations' => ['type' => 'list', 'member' => ['shape' => 'DomainAssociation'], 'max' => 255], 'DomainName' => ['type' => 'string', 'max' => 255], 'DomainPrefix' => ['type' => 'string', 'max' => 255], 'DomainStatus' => ['type' => 'string', 'enum' => ['PENDING_VERIFICATION', 'IN_PROGRESS', 'AVAILABLE', 'PENDING_DEPLOYMENT', 'FAILED', 'CREATING', 'REQUESTING_CERTIFICATE', 'UPDATING']], 'EnableAutoBranchCreation' => ['type' => 'boolean'], 'EnableAutoBuild' => ['type' => 'boolean'], 'EnableAutoSubDomain' => ['type' => 'boolean'], 'EnableBasicAuth' => ['type' => 'boolean'], 'EnableBranchAutoBuild' => ['type' => 'boolean'], 'EnableNotification' => ['type' => 'boolean'], 'EnablePullRequestPreview' => ['type' => 'boolean'], 'EndTime' => ['type' => 'timestamp'], 'EnvKey' => ['type' => 'string', 'max' => 255], 'EnvValue' => ['type' => 'string', 'max' => 1000], 'EnvironmentName' => ['type' => 'string', 'max' => 255, 'min' => 1], 'EnvironmentVariables' => ['type' => 'map', 'key' => ['shape' => 'EnvKey'], 'value' => ['shape' => 'EnvValue']], 'ErrorMessage' => ['type' => 'string', 'max' => 255], 'FileMap' => ['type' => 'map', 'key' => ['shape' => 'FileName'], 'value' => ['shape' => 'MD5Hash']], 'FileName' => ['type' => 'string', 'max' => 255], 'FileUploadUrls' => ['type' => 'map', 'key' => ['shape' => 'FileName'], 'value' => ['shape' => 'UploadUrl']], 'Framework' => ['type' => 'string', 'max' => 255], 'GenerateAccessLogsRequest' => ['type' => 'structure', 'required' => ['domainName', 'appId'], 'members' => ['startTime' => ['shape' => 'StartTime'], 'endTime' => ['shape' => 'EndTime'], 'domainName' => ['shape' => 'DomainName'], 'appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId']]], 'GenerateAccessLogsResult' => ['type' => 'structure', 'members' => ['logUrl' => ['shape' => 'LogUrl']]], 'GetAppRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId']]], 'GetAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'GetArtifactUrlRequest' => ['type' => 'structure', 'required' => ['artifactId'], 'members' => ['artifactId' => ['shape' => 'ArtifactId', 'location' => 'uri', 'locationName' => 'artifactId']]], 'GetArtifactUrlResult' => ['type' => 'structure', 'required' => ['artifactId', 'artifactUrl'], 'members' => ['artifactId' => ['shape' => 'ArtifactId'], 'artifactUrl' => ['shape' => 'ArtifactUrl']]], 'GetBackendEnvironmentRequest' => ['type' => 'structure', 'required' => ['appId', 'environmentName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'environmentName' => ['shape' => 'EnvironmentName', 'location' => 'uri', 'locationName' => 'environmentName']]], 'GetBackendEnvironmentResult' => ['type' => 'structure', 'required' => ['backendEnvironment'], 'members' => ['backendEnvironment' => ['shape' => 'BackendEnvironment']]], 'GetBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName']]], 'GetBranchResult' => ['type' => 'structure', 'required' => ['branch'], 'members' => ['branch' => ['shape' => 'Branch']]], 'GetDomainAssociationRequest' => ['type' => 'structure', 'required' => ['appId', 'domainName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'domainName' => ['shape' => 'DomainName', 'location' => 'uri', 'locationName' => 'domainName']]], 'GetDomainAssociationResult' => ['type' => 'structure', 'required' => ['domainAssociation'], 'members' => ['domainAssociation' => ['shape' => 'DomainAssociation']]], 'GetJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId']]], 'GetJobResult' => ['type' => 'structure', 'required' => ['job'], 'members' => ['job' => ['shape' => 'Job']]], 'GetWebhookRequest' => ['type' => 'structure', 'required' => ['webhookId'], 'members' => ['webhookId' => ['shape' => 'WebhookId', 'location' => 'uri', 'locationName' => 'webhookId']]], 'GetWebhookResult' => ['type' => 'structure', 'required' => ['webhook'], 'members' => ['webhook' => ['shape' => 'Webhook']]], 'InternalFailureException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 500], 'exception' => \true, 'fault' => \true], 'Job' => ['type' => 'structure', 'required' => ['summary', 'steps'], 'members' => ['summary' => ['shape' => 'JobSummary'], 'steps' => ['shape' => 'Steps']]], 'JobArn' => ['type' => 'string', 'max' => 1000], 'JobId' => ['type' => 'string', 'max' => 255], 'JobReason' => ['type' => 'string', 'max' => 255], 'JobStatus' => ['type' => 'string', 'enum' => ['PENDING', 'PROVISIONING', 'RUNNING', 'FAILED', 'SUCCEED', 'CANCELLING', 'CANCELLED']], 'JobSummaries' => ['type' => 'list', 'member' => ['shape' => 'JobSummary']], 'JobSummary' => ['type' => 'structure', 'required' => ['jobArn', 'jobId', 'commitId', 'commitMessage', 'commitTime', 'startTime', 'status', 'jobType'], 'members' => ['jobArn' => ['shape' => 'JobArn'], 'jobId' => ['shape' => 'JobId'], 'commitId' => ['shape' => 'CommitId'], 'commitMessage' => ['shape' => 'CommitMessage'], 'commitTime' => ['shape' => 'CommitTime'], 'startTime' => ['shape' => 'StartTime'], 'status' => ['shape' => 'JobStatus'], 'endTime' => ['shape' => 'EndTime'], 'jobType' => ['shape' => 'JobType']]], 'JobType' => ['type' => 'string', 'enum' => ['RELEASE', 'RETRY', 'MANUAL', 'WEB_HOOK'], 'max' => 10], 'LastDeployTime' => ['type' => 'timestamp'], 'LimitExceededException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 429], 'exception' => \true], 'ListAppsRequest' => ['type' => 'structure', 'members' => ['nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListAppsResult' => ['type' => 'structure', 'required' => ['apps'], 'members' => ['apps' => ['shape' => 'Apps'], 'nextToken' => ['shape' => 'NextToken']]], 'ListArtifactsRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListArtifactsResult' => ['type' => 'structure', 'required' => ['artifacts'], 'members' => ['artifacts' => ['shape' => 'Artifacts'], 'nextToken' => ['shape' => 'NextToken']]], 'ListBackendEnvironmentsRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'environmentName' => ['shape' => 'EnvironmentName'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListBackendEnvironmentsResult' => ['type' => 'structure', 'required' => ['backendEnvironments'], 'members' => ['backendEnvironments' => ['shape' => 'BackendEnvironments'], 'nextToken' => ['shape' => 'NextToken']]], 'ListBranchesRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListBranchesResult' => ['type' => 'structure', 'required' => ['branches'], 'members' => ['branches' => ['shape' => 'Branches'], 'nextToken' => ['shape' => 'NextToken']]], 'ListDomainAssociationsRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListDomainAssociationsResult' => ['type' => 'structure', 'required' => ['domainAssociations'], 'members' => ['domainAssociations' => ['shape' => 'DomainAssociations'], 'nextToken' => ['shape' => 'NextToken']]], 'ListJobsRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListJobsResult' => ['type' => 'structure', 'required' => ['jobSummaries'], 'members' => ['jobSummaries' => ['shape' => 'JobSummaries'], 'nextToken' => ['shape' => 'NextToken']]], 'ListTagsForResourceRequest' => ['type' => 'structure', 'required' => ['resourceArn'], 'members' => ['resourceArn' => ['shape' => 'ResourceArn', 'location' => 'uri', 'locationName' => 'resourceArn']]], 'ListTagsForResourceResponse' => ['type' => 'structure', 'members' => ['tags' => ['shape' => 'TagMap']]], 'ListWebhooksRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'nextToken' => ['shape' => 'NextToken', 'location' => 'querystring', 'locationName' => 'nextToken'], 'maxResults' => ['shape' => 'MaxResults', 'location' => 'querystring', 'locationName' => 'maxResults']]], 'ListWebhooksResult' => ['type' => 'structure', 'required' => ['webhooks'], 'members' => ['webhooks' => ['shape' => 'Webhooks'], 'nextToken' => ['shape' => 'NextToken']]], 'LogUrl' => ['type' => 'string', 'max' => 1000], 'MD5Hash' => ['type' => 'string', 'max' => 32], 'MaxResults' => ['type' => 'integer', 'max' => 100, 'min' => 1], 'Name' => ['type' => 'string', 'max' => 255, 'min' => 1], 'NextToken' => ['type' => 'string', 'max' => 2000], 'NotFoundException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 404], 'exception' => \true], 'OauthToken' => ['type' => 'string', 'max' => 100], 'Platform' => ['type' => 'string', 'enum' => ['WEB']], 'ProductionBranch' => ['type' => 'structure', 'members' => ['lastDeployTime' => ['shape' => 'LastDeployTime'], 'status' => ['shape' => 'Status'], 'thumbnailUrl' => ['shape' => 'ThumbnailUrl'], 'branchName' => ['shape' => 'BranchName']]], 'PullRequestEnvironmentName' => ['type' => 'string', 'max' => 20], 'Repository' => ['type' => 'string', 'max' => 1000], 'ResourceArn' => ['type' => 'string', 'pattern' => '^arn:aws:amplify:.*'], 'ResourceNotFoundException' => ['type' => 'structure', 'required' => ['code', 'message'], 'members' => ['code' => ['shape' => 'Code'], 'message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 404], 'exception' => \true], 'Screenshots' => ['type' => 'map', 'key' => ['shape' => 'ThumbnailName'], 'value' => ['shape' => 'ThumbnailUrl']], 'ServiceRoleArn' => ['type' => 'string', 'max' => 1000, 'min' => 1], 'Source' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'SourceUrl' => ['type' => 'string', 'max' => 1000], 'StackName' => ['type' => 'string', 'max' => 255, 'min' => 1], 'Stage' => ['type' => 'string', 'enum' => ['PRODUCTION', 'BETA', 'DEVELOPMENT', 'EXPERIMENTAL', 'PULL_REQUEST']], 'StartDeploymentRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId'], 'sourceUrl' => ['shape' => 'SourceUrl']]], 'StartDeploymentResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'StartJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobType'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId'], 'jobType' => ['shape' => 'JobType'], 'jobReason' => ['shape' => 'JobReason'], 'commitId' => ['shape' => 'CommitId'], 'commitMessage' => ['shape' => 'CommitMessage'], 'commitTime' => ['shape' => 'CommitTime']]], 'StartJobResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'StartTime' => ['type' => 'timestamp'], 'Status' => ['type' => 'string', 'max' => 7, 'min' => 3], 'StatusReason' => ['type' => 'string', 'max' => 1000], 'Step' => ['type' => 'structure', 'required' => ['stepName', 'startTime', 'status', 'endTime'], 'members' => ['stepName' => ['shape' => 'StepName'], 'startTime' => ['shape' => 'StartTime'], 'status' => ['shape' => 'JobStatus'], 'endTime' => ['shape' => 'EndTime'], 'logUrl' => ['shape' => 'LogUrl'], 'artifactsUrl' => ['shape' => 'ArtifactsUrl'], 'testArtifactsUrl' => ['shape' => 'TestArtifactsUrl'], 'testConfigUrl' => ['shape' => 'TestConfigUrl'], 'screenshots' => ['shape' => 'Screenshots'], 'statusReason' => ['shape' => 'StatusReason'], 'context' => ['shape' => 'Context']]], 'StepName' => ['type' => 'string', 'max' => 255], 'Steps' => ['type' => 'list', 'member' => ['shape' => 'Step']], 'StopJobRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName', 'jobId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'jobId' => ['shape' => 'JobId', 'location' => 'uri', 'locationName' => 'jobId']]], 'StopJobResult' => ['type' => 'structure', 'required' => ['jobSummary'], 'members' => ['jobSummary' => ['shape' => 'JobSummary']]], 'SubDomain' => ['type' => 'structure', 'required' => ['subDomainSetting', 'verified', 'dnsRecord'], 'members' => ['subDomainSetting' => ['shape' => 'SubDomainSetting'], 'verified' => ['shape' => 'Verified'], 'dnsRecord' => ['shape' => 'DNSRecord']]], 'SubDomainSetting' => ['type' => 'structure', 'required' => ['prefix', 'branchName'], 'members' => ['prefix' => ['shape' => 'DomainPrefix'], 'branchName' => ['shape' => 'BranchName']]], 'SubDomainSettings' => ['type' => 'list', 'member' => ['shape' => 'SubDomainSetting'], 'max' => 255], 'SubDomains' => ['type' => 'list', 'member' => ['shape' => 'SubDomain'], 'max' => 255], 'TTL' => ['type' => 'string'], 'TagKey' => ['type' => 'string', 'max' => 128, 'min' => 1, 'pattern' => '^(?!aws:)[a-zA-Z+-=._:/]+$'], 'TagKeyList' => ['type' => 'list', 'member' => ['shape' => 'TagKey'], 'max' => 50, 'min' => 1], 'TagMap' => ['type' => 'map', 'key' => ['shape' => 'TagKey'], 'value' => ['shape' => 'TagValue'], 'max' => 50, 'min' => 1], 'TagResourceRequest' => ['type' => 'structure', 'required' => ['resourceArn', 'tags'], 'members' => ['resourceArn' => ['shape' => 'ResourceArn', 'location' => 'uri', 'locationName' => 'resourceArn'], 'tags' => ['shape' => 'TagMap']]], 'TagResourceResponse' => ['type' => 'structure', 'members' => []], 'TagValue' => ['type' => 'string', 'max' => 256], 'Target' => ['type' => 'string', 'max' => 2048, 'min' => 1], 'TestArtifactsUrl' => ['type' => 'string', 'max' => 1000], 'TestConfigUrl' => ['type' => 'string', 'max' => 1000], 'ThumbnailName' => ['type' => 'string', 'max' => 256], 'ThumbnailUrl' => ['type' => 'string', 'max' => 2000, 'min' => 1], 'TotalNumberOfJobs' => ['type' => 'string', 'max' => 1000], 'UnauthorizedException' => ['type' => 'structure', 'members' => ['message' => ['shape' => 'ErrorMessage']], 'error' => ['httpStatusCode' => 401], 'exception' => \true], 'UntagResourceRequest' => ['type' => 'structure', 'required' => ['resourceArn', 'tagKeys'], 'members' => ['resourceArn' => ['shape' => 'ResourceArn', 'location' => 'uri', 'locationName' => 'resourceArn'], 'tagKeys' => ['shape' => 'TagKeyList', 'location' => 'querystring', 'locationName' => 'tagKeys']]], 'UntagResourceResponse' => ['type' => 'structure', 'members' => []], 'UpdateAppRequest' => ['type' => 'structure', 'required' => ['appId'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'name' => ['shape' => 'Name'], 'description' => ['shape' => 'Description'], 'platform' => ['shape' => 'Platform'], 'iamServiceRoleArn' => ['shape' => 'ServiceRoleArn'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'enableBranchAutoBuild' => ['shape' => 'EnableAutoBuild'], 'enableBasicAuth' => ['shape' => 'EnableBasicAuth'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'customRules' => ['shape' => 'CustomRules'], 'buildSpec' => ['shape' => 'BuildSpec'], 'enableAutoBranchCreation' => ['shape' => 'EnableAutoBranchCreation'], 'autoBranchCreationPatterns' => ['shape' => 'AutoBranchCreationPatterns'], 'autoBranchCreationConfig' => ['shape' => 'AutoBranchCreationConfig'], 'repository' => ['shape' => 'Repository'], 'oauthToken' => ['shape' => 'OauthToken'], 'accessToken' => ['shape' => 'AccessToken']]], 'UpdateAppResult' => ['type' => 'structure', 'required' => ['app'], 'members' => ['app' => ['shape' => 'App']]], 'UpdateBranchRequest' => ['type' => 'structure', 'required' => ['appId', 'branchName'], 'members' => ['appId' => ['shape' => 'AppId', 'location' => 'uri', 'locationName' => 'appId'], 'branchName' => ['shape' => 'BranchName', 'location' => 'uri', 'locationName' => 'branchName'], 'description' => ['shape' => 'Description'], 'framework' => ['shape' => 'Framework'], 'stage' => ['shape' => 'Stage'], 'enableNotification' => ['shape' => 'EnableNotification'], 'enableAutoBuild' => ['shape' => 'EnableAutoBuild'], 'environmentVariables' => ['shape' => 'EnvironmentVariables'], 'basicAuthCredentials' => ['shape' => 'BasicAuthCredentials'], 'enableBasicA
|