WP Offload S3 Lite - Version 2.0

Version Description

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+.

Download this release

Release Info

Developer deliciousbrains
Plugin Icon 128x128 WP Offload S3 Lite
Version 2.0
Comparing to
See all releases

Code changes from version 1.4.3 to 2.0

Files changed (287) hide show
  1. README.md +45 -26
  2. assets/css/attachment.css +1 -1
  3. assets/css/notice.css +1 -1
  4. assets/css/storage-provider.css +1 -0
  5. assets/css/styles.css +1 -1
  6. assets/img/do-logo.svg +6 -0
  7. assets/js/media.js +17 -17
  8. assets/js/media.min.js +1 -1
  9. assets/js/modal.js +4 -0
  10. assets/js/modal.min.js +1 -1
  11. assets/js/script.js +75 -121
  12. assets/js/script.min.js +1 -1
  13. assets/js/storage-provider.js +85 -0
  14. assets/js/storage-provider.min.js +1 -0
  15. assets/sass/attachment.scss +6 -2
  16. assets/sass/notice.scss +1 -1
  17. assets/sass/storage-provider.scss +112 -0
  18. assets/sass/styles.scss +85 -71
  19. classes/amazon-s3-and-cloudfront.php +599 -528
  20. classes/as3cf-compatibility-check.php +3 -2
  21. classes/as3cf-error.php +1 -1
  22. classes/as3cf-notices.php +1 -1
  23. classes/as3cf-plugin-base.php +29 -12
  24. classes/as3cf-plugin-compatibility.php +66 -64
  25. classes/as3cf-utils.php +103 -14
  26. classes/filters/as3cf-local-to-s3.php +2 -1
  27. classes/filters/as3cf-s3-to-local.php +2 -1
  28. classes/providers/aws-provider.php +132 -17
  29. classes/providers/digitalocean-provider.php +179 -0
  30. classes/providers/null-provider.php +3 -3
  31. classes/providers/provider.php +308 -25
  32. classes/providers/streams/aws-s3-stream-wrapper.php +7 -6
  33. classes/upgrades/exceptions/batch-limits-exceeded-exception.php +1 -1
  34. classes/upgrades/exceptions/no-more-blogs-exception.php +1 -1
  35. classes/upgrades/exceptions/too-many-errors-exception.php +1 -1
  36. classes/upgrades/network-upgrade.php +1 -1
  37. classes/upgrades/upgrade-content-replace-urls.php +5 -5
  38. classes/upgrades/upgrade-edd-replace-urls.php +1 -1
  39. classes/upgrades/upgrade-file-sizes.php +14 -14
  40. classes/upgrades/upgrade-filter-post-excerpt.php +1 -1
  41. classes/upgrades/upgrade-filter-post.php +4 -4
  42. classes/upgrades/upgrade-meta-wp-error.php +9 -9
  43. classes/upgrades/upgrade-region-meta.php +7 -7
  44. classes/upgrades/upgrade-wpos3-to-as3cf.php +107 -0
  45. classes/upgrades/upgrade.php +6 -6
  46. composer.json +2 -2
  47. languages/amazon-s3-and-cloudfront-en.pot +359 -301
  48. readme.txt +39 -24
  49. vendor/Aws3/Aws/Api/AbstractModel.php +3 -3
  50. vendor/Aws3/Aws/Api/ApiProvider.php +5 -5
  51. vendor/Aws3/Aws/Api/DateTimeResult.php +1 -1
  52. vendor/Aws3/Aws/Api/DocModel.php +1 -1
  53. vendor/Aws3/Aws/Api/ErrorParser/JsonParserTrait.php +4 -4
  54. vendor/Aws3/Aws/Api/ErrorParser/JsonRpcErrorParser.php +3 -3
  55. vendor/Aws3/Aws/Api/ErrorParser/RestJsonErrorParser.php +3 -3
  56. vendor/Aws3/Aws/Api/ErrorParser/XmlErrorParser.php +5 -5
  57. vendor/Aws3/Aws/Api/ListShape.php +4 -4
  58. vendor/Aws3/Aws/Api/MapShape.php +5 -5
  59. vendor/Aws3/Aws/Api/Operation.php +5 -5
  60. vendor/Aws3/Aws/Api/Parser/AbstractParser.php +7 -7
  61. vendor/Aws3/Aws/Api/Parser/AbstractRestParser.php +16 -16
  62. vendor/Aws3/Aws/Api/Parser/Crc32ValidatingParser.php +9 -9
  63. vendor/Aws3/Aws/Api/Parser/Exception/ParserException.php +1 -1
  64. vendor/Aws3/Aws/Api/Parser/JsonParser.php +5 -5
  65. vendor/Aws3/Aws/Api/Parser/JsonRpcParser.php +10 -10
  66. vendor/Aws3/Aws/Api/Parser/PayloadParserTrait.php +4 -4
  67. vendor/Aws3/Aws/Api/Parser/QueryParser.php +10 -10
  68. vendor/Aws3/Aws/Api/Parser/RestJsonParser.php +8 -8
  69. vendor/Aws3/Aws/Api/Parser/RestXmlParser.php +8 -8
  70. vendor/Aws3/Aws/Api/Parser/XmlParser.php +17 -17
  71. vendor/Aws3/Aws/Api/Serializer/Ec2ParamBuilder.php +7 -7
  72. vendor/Aws3/Aws/Api/Serializer/JsonBody.php +9 -9
  73. vendor/Aws3/Aws/Api/Serializer/JsonRpcSerializer.php +10 -10
  74. vendor/Aws3/Aws/Api/Serializer/QueryParamBuilder.php +17 -17
  75. vendor/Aws3/Aws/Api/Serializer/QuerySerializer.php +9 -9
  76. vendor/Aws3/Aws/Api/Serializer/RestJsonSerializer.php +8 -8
  77. vendor/Aws3/Aws/Api/Serializer/RestSerializer.php +27 -27
  78. vendor/Aws3/Aws/Api/Serializer/RestXmlSerializer.php +7 -7
  79. vendor/Aws3/Aws/Api/Serializer/XmlBody.php +21 -21
  80. vendor/Aws3/Aws/Api/Service.php +14 -14
  81. vendor/Aws3/Aws/Api/Shape.php +4 -4
  82. vendor/Aws3/Aws/Api/ShapeMap.php +2 -2
  83. vendor/Aws3/Aws/Api/StructureShape.php +3 -3
  84. vendor/Aws3/Aws/Api/TimestampShape.php +3 -3
  85. vendor/Aws3/Aws/Api/Validator.php +18 -18
  86. vendor/Aws3/Aws/AwsClient.php +19 -19
  87. vendor/Aws3/Aws/AwsClientInterface.php +5 -5
  88. vendor/Aws3/Aws/AwsClientTrait.php +6 -6
  89. vendor/Aws3/Aws/CacheInterface.php +1 -1
  90. vendor/Aws3/Aws/ClientResolver.php +52 -52
  91. vendor/Aws3/Aws/Command.php +4 -4
  92. vendor/Aws3/Aws/CommandInterface.php +1 -1
  93. vendor/Aws3/Aws/CommandPool.php +7 -7
  94. vendor/Aws3/Aws/Credentials/AssumeRoleCredentialProvider.php +7 -7
  95. vendor/Aws3/Aws/Credentials/CredentialProvider.php +17 -17
  96. vendor/Aws3/Aws/Credentials/Credentials.php +2 -2
  97. vendor/Aws3/Aws/Credentials/CredentialsInterface.php +1 -1
  98. vendor/Aws3/Aws/Credentials/EcsCredentialProvider.php +11 -11
  99. vendor/Aws3/Aws/Credentials/InstanceProfileProvider.php +14 -14
  100. vendor/Aws3/Aws/Crypto/AbstractCryptoClient.php +6 -6
  101. vendor/Aws3/Aws/Crypto/AesDecryptingStream.php +6 -6
  102. vendor/Aws3/Aws/Crypto/AesEncryptingStream.php +6 -6
  103. vendor/Aws3/Aws/Crypto/AesGcmDecryptingStream.php +7 -7
  104. vendor/Aws3/Aws/Crypto/AesGcmEncryptingStream.php +7 -7
  105. vendor/Aws3/Aws/Crypto/AesStreamInterface.php +2 -2
  106. vendor/Aws3/Aws/Crypto/Cipher/Cbc.php +2 -2
  107. vendor/Aws3/Aws/Crypto/Cipher/CipherBuilderTrait.php +2 -2
  108. vendor/Aws3/Aws/Crypto/Cipher/CipherMethod.php +1 -1
  109. vendor/Aws3/Aws/Crypto/DecryptionTrait.php +15 -15
  110. vendor/Aws3/Aws/Crypto/EncryptionTrait.php +19 -19
  111. vendor/Aws3/Aws/Crypto/KmsMaterialsProvider.php +8 -8
  112. vendor/Aws3/Aws/Crypto/MaterialsProvider.php +2 -2
  113. vendor/Aws3/Aws/Crypto/MetadataEnvelope.php +2 -2
  114. vendor/Aws3/Aws/Crypto/MetadataStrategyInterface.php +2 -2
  115. vendor/Aws3/Aws/DoctrineCacheAdapter.php +4 -4
  116. vendor/Aws3/Aws/Endpoint/EndpointProvider.php +5 -5
  117. vendor/Aws3/Aws/Endpoint/Partition.php +3 -3
  118. vendor/Aws3/Aws/Endpoint/PartitionEndpointProvider.php +3 -3
  119. vendor/Aws3/Aws/Endpoint/PartitionInterface.php +1 -1
  120. vendor/Aws3/Aws/Endpoint/PatternEndpointProvider.php +1 -1
  121. vendor/Aws3/Aws/Exception/AwsException.php +6 -6
  122. vendor/Aws3/Aws/Exception/CouldNotCreateChecksumException.php +1 -1
  123. vendor/Aws3/Aws/Exception/CredentialsException.php +1 -1
  124. vendor/Aws3/Aws/Exception/MultipartUploadException.php +3 -3
  125. vendor/Aws3/Aws/Exception/UnresolvedApiException.php +1 -1
  126. vendor/Aws3/Aws/Exception/UnresolvedEndpointException.php +1 -1
  127. vendor/Aws3/Aws/Exception/UnresolvedSignatureException.php +1 -1
  128. vendor/Aws3/Aws/Handler/GuzzleV5/GuzzleHandler.php +27 -27
  129. vendor/Aws3/Aws/Handler/GuzzleV5/GuzzleStream.php +6 -6
  130. vendor/Aws3/Aws/Handler/GuzzleV5/PsrStream.php +6 -6
  131. vendor/Aws3/Aws/Handler/GuzzleV6/GuzzleHandler.php +14 -14
  132. vendor/Aws3/Aws/HandlerList.php +1 -1
  133. vendor/Aws3/Aws/HasDataTrait.php +1 -1
  134. vendor/Aws3/Aws/HashInterface.php +1 -1
  135. vendor/Aws3/Aws/HashingStream.php +5 -5
  136. vendor/Aws3/Aws/History.php +4 -4
  137. vendor/Aws3/Aws/IdempotencyTokenMiddleware.php +6 -6
  138. vendor/Aws3/Aws/JsonCompiler.php +1 -1
  139. vendor/Aws3/Aws/LruArrayCache.php +2 -2
  140. vendor/Aws3/Aws/Middleware.php +34 -34
  141. vendor/Aws3/Aws/MockHandler.php +8 -8
  142. vendor/Aws3/Aws/MultiRegionClient.php +12 -12
  143. vendor/Aws3/Aws/Multipart/AbstractUploadManager.php +24 -24
  144. vendor/Aws3/Aws/Multipart/AbstractUploader.php +10 -10
  145. vendor/Aws3/Aws/Multipart/UploadState.php +1 -1
  146. vendor/Aws3/Aws/PhpHash.php +2 -2
  147. vendor/Aws3/Aws/PresignUrlMiddleware.php +15 -15
  148. vendor/Aws3/Aws/PsrCacheAdapter.php +4 -4
  149. vendor/Aws3/Aws/Result.php +4 -4
  150. vendor/Aws3/Aws/ResultInterface.php +1 -1
  151. vendor/Aws3/Aws/ResultPaginator.php +7 -7
  152. vendor/Aws3/Aws/RetryMiddleware.php +9 -9
  153. vendor/Aws3/Aws/S3/AmbiguousSuccessParser.php +8 -8
  154. vendor/Aws3/Aws/S3/ApplyChecksumMiddleware.php +6 -6
  155. vendor/Aws3/Aws/S3/BatchDelete.php +17 -17
  156. vendor/Aws3/Aws/S3/BucketEndpointMiddleware.php +6 -6
  157. vendor/Aws3/Aws/S3/Crypto/CryptoParamsTrait.php +12 -12
  158. vendor/Aws3/Aws/S3/Crypto/HeadersMetadataStrategy.php +7 -7
  159. vendor/Aws3/Aws/S3/Crypto/InstructionFileMetadataStrategy.php +9 -9
  160. vendor/Aws3/Aws/S3/Crypto/S3EncryptionClient.php +20 -20
  161. vendor/Aws3/Aws/S3/Crypto/S3EncryptionMultipartUploader.php +13 -13
  162. vendor/Aws3/Aws/S3/Exception/DeleteMultipleObjectsException.php +1 -1
  163. vendor/Aws3/Aws/S3/Exception/PermanentRedirectException.php +2 -2
  164. vendor/Aws3/Aws/S3/Exception/S3Exception.php +3 -3
  165. vendor/Aws3/Aws/S3/Exception/S3MultipartUploadException.php +7 -7
  166. vendor/Aws3/Aws/S3/GetBucketLocationParser.php +6 -6
  167. vendor/Aws3/Aws/S3/MultipartCopy.php +8 -8
  168. vendor/Aws3/Aws/S3/MultipartUploader.php +19 -19
  169. vendor/Aws3/Aws/S3/MultipartUploadingTrait.php +12 -12
  170. vendor/Aws3/Aws/S3/ObjectCopier.php +10 -10
  171. vendor/Aws3/Aws/S3/ObjectUploader.php +13 -13
  172. vendor/Aws3/Aws/S3/PermanentRedirectMiddleware.php +8 -8
  173. vendor/Aws3/Aws/S3/PostObject.php +6 -6
  174. vendor/Aws3/Aws/S3/PostObjectV4.php +11 -11
  175. vendor/Aws3/Aws/S3/PutObjectUrlMiddleware.php +6 -6
  176. vendor/Aws3/Aws/S3/RetryableMalformedResponseParser.php +9 -9
  177. vendor/Aws3/Aws/S3/S3Client.php +40 -40
  178. vendor/Aws3/Aws/S3/S3ClientInterface.php +7 -7
  179. vendor/Aws3/Aws/S3/S3ClientTrait.php +21 -21
  180. vendor/Aws3/Aws/S3/S3EndpointMiddleware.php +15 -15
  181. vendor/Aws3/Aws/S3/S3MultiRegionClient.php +15 -15
  182. vendor/Aws3/Aws/S3/S3UriParser.php +8 -8
  183. vendor/Aws3/Aws/S3/SSECMiddleware.php +5 -5
  184. vendor/Aws3/Aws/S3/StreamWrapper.php +16 -16
  185. vendor/Aws3/Aws/S3/Transfer.php +18 -18
  186. vendor/Aws3/Aws/Sdk.php +4 -4
  187. vendor/Aws3/Aws/Signature/AnonymousSignature.php +6 -6
  188. vendor/Aws3/Aws/Signature/S3SignatureV4.php +8 -8
  189. vendor/Aws3/Aws/Signature/SignatureInterface.php +5 -5
  190. vendor/Aws3/Aws/Signature/SignatureProvider.php +6 -6
  191. vendor/Aws3/Aws/Signature/SignatureTrait.php +1 -1
  192. vendor/Aws3/Aws/Signature/SignatureV4.php +20 -20
  193. vendor/Aws3/Aws/TraceMiddleware.php +14 -14
  194. vendor/Aws3/Aws/Waiter.php +10 -10
  195. vendor/Aws3/Aws/WrappedHttpHandler.php +12 -12
  196. vendor/Aws3/Aws/functions.php +10 -10
  197. vendor/Aws3/GuzzleHttp/Client.php +32 -32
  198. vendor/Aws3/GuzzleHttp/ClientInterface.php +8 -8
  199. vendor/Aws3/GuzzleHttp/Cookie/CookieJar.php +18 -18
  200. vendor/Aws3/GuzzleHttp/Cookie/CookieJarInterface.php +6 -6
  201. vendor/Aws3/GuzzleHttp/Cookie/FileCookieJar.php +6 -6
  202. vendor/Aws3/GuzzleHttp/Cookie/SessionCookieJar.php +4 -4
  203. vendor/Aws3/GuzzleHttp/Cookie/SetCookie.php +1 -1
  204. vendor/Aws3/GuzzleHttp/Exception/BadResponseException.php +5 -5
  205. vendor/Aws3/GuzzleHttp/Exception/ClientException.php +2 -2
  206. vendor/Aws3/GuzzleHttp/Exception/ConnectException.php +4 -4
  207. vendor/Aws3/GuzzleHttp/Exception/GuzzleException.php +1 -1
  208. vendor/Aws3/GuzzleHttp/Exception/RequestException.php +13 -13
  209. vendor/Aws3/GuzzleHttp/Exception/SeekException.php +4 -4
  210. vendor/Aws3/GuzzleHttp/Exception/ServerException.php +2 -2
  211. vendor/Aws3/GuzzleHttp/Exception/TooManyRedirectsException.php +2 -2
  212. vendor/Aws3/GuzzleHttp/Exception/TransferException.php +2 -2
  213. vendor/Aws3/GuzzleHttp/Handler/CurlFactory.php +33 -33
  214. vendor/Aws3/GuzzleHttp/Handler/CurlFactoryInterface.php +4 -4
  215. vendor/Aws3/GuzzleHttp/Handler/CurlHandler.php +6 -6
  216. vendor/Aws3/GuzzleHttp/Handler/CurlMultiHandler.php +11 -11
  217. vendor/Aws3/GuzzleHttp/Handler/EasyHandle.php +8 -8
  218. vendor/Aws3/GuzzleHttp/Handler/MockHandler.php +16 -16
  219. vendor/Aws3/GuzzleHttp/Handler/Proxy.php +6 -6
  220. vendor/Aws3/GuzzleHttp/Handler/StreamHandler.php +43 -43
  221. vendor/Aws3/GuzzleHttp/HandlerStack.php +7 -7
  222. vendor/Aws3/GuzzleHttp/MessageFormatter.php +8 -8
  223. vendor/Aws3/GuzzleHttp/Middleware.php +16 -16
  224. vendor/Aws3/GuzzleHttp/Pool.php +9 -9
  225. vendor/Aws3/GuzzleHttp/PrepareBodyMiddleware.php +8 -8
  226. vendor/Aws3/GuzzleHttp/Promise/AggregateException.php +2 -2
  227. vendor/Aws3/GuzzleHttp/Promise/CancellationException.php +2 -2
  228. vendor/Aws3/GuzzleHttp/Promise/Coroutine.php +3 -3
  229. vendor/Aws3/GuzzleHttp/Promise/EachPromise.php +5 -5
  230. vendor/Aws3/GuzzleHttp/Promise/FulfilledPromise.php +3 -3
  231. vendor/Aws3/GuzzleHttp/Promise/Promise.php +4 -4
  232. vendor/Aws3/GuzzleHttp/Promise/PromiseInterface.php +1 -1
  233. vendor/Aws3/GuzzleHttp/Promise/PromisorInterface.php +1 -1
  234. vendor/Aws3/GuzzleHttp/Promise/RejectedPromise.php +3 -3
  235. vendor/Aws3/GuzzleHttp/Promise/RejectionException.php +1 -1
  236. vendor/Aws3/GuzzleHttp/Promise/TaskQueue.php +2 -2
  237. vendor/Aws3/GuzzleHttp/Promise/TaskQueueInterface.php +1 -1
  238. vendor/Aws3/GuzzleHttp/Promise/functions.php +29 -29
  239. vendor/Aws3/GuzzleHttp/Promise/functions_include.php +1 -1
  240. vendor/Aws3/GuzzleHttp/Psr7/AppendStream.php +4 -4
  241. vendor/Aws3/GuzzleHttp/Psr7/BufferStream.php +3 -3
  242. vendor/Aws3/GuzzleHttp/Psr7/CachingStream.php +6 -6
  243. vendor/Aws3/GuzzleHttp/Psr7/DroppingStream.php +4 -4
  244. vendor/Aws3/GuzzleHttp/Psr7/FnStream.php +4 -4
  245. vendor/Aws3/GuzzleHttp/Psr7/InflateStream.php +8 -8
  246. vendor/Aws3/GuzzleHttp/Psr7/LazyOpenStream.php +3 -3
  247. vendor/Aws3/GuzzleHttp/Psr7/LimitStream.php +4 -4
  248. vendor/Aws3/GuzzleHttp/Psr7/MessageTrait.php +3 -3
  249. vendor/Aws3/GuzzleHttp/Psr7/MultipartStream.php +6 -6
  250. vendor/Aws3/GuzzleHttp/Psr7/NoSeekStream.php +3 -3
  251. vendor/Aws3/GuzzleHttp/Psr7/PumpStream.php +4 -4
  252. vendor/Aws3/GuzzleHttp/Psr7/Request.php +7 -7
  253. vendor/Aws3/GuzzleHttp/Psr7/Response.php +4 -4
  254. vendor/Aws3/GuzzleHttp/Psr7/ServerRequest.php +10 -10
  255. vendor/Aws3/GuzzleHttp/Psr7/Stream.php +3 -3
  256. vendor/Aws3/GuzzleHttp/Psr7/StreamDecoratorTrait.php +3 -3
  257. vendor/Aws3/GuzzleHttp/Psr7/StreamWrapper.php +3 -3
  258. vendor/Aws3/GuzzleHttp/Psr7/UploadedFile.php +7 -7
  259. vendor/Aws3/GuzzleHttp/Psr7/Uri.php +15 -15
  260. vendor/Aws3/GuzzleHttp/Psr7/UriNormalizer.php +9 -9
  261. vendor/Aws3/GuzzleHttp/Psr7/UriResolver.php +7 -7
  262. vendor/Aws3/GuzzleHttp/Psr7/functions.php +24 -24
  263. vendor/Aws3/GuzzleHttp/Psr7/functions_include.php +1 -1
  264. vendor/Aws3/GuzzleHttp/RedirectMiddleware.php +21 -21
  265. vendor/Aws3/GuzzleHttp/RequestOptions.php +1 -1
  266. vendor/Aws3/GuzzleHttp/RetryMiddleware.php +11 -11
  267. vendor/Aws3/GuzzleHttp/TransferStats.php +5 -5
  268. vendor/Aws3/GuzzleHttp/UriTemplate.php +1 -1
  269. vendor/Aws3/GuzzleHttp/functions.php +11 -11
  270. vendor/Aws3/GuzzleHttp/functions_include.php +1 -1
  271. vendor/Aws3/JmesPath/AstRuntime.php +5 -5
  272. vendor/Aws3/JmesPath/CompilerRuntime.php +5 -5
  273. vendor/Aws3/JmesPath/DebugRuntime.php +5 -5
  274. vendor/Aws3/JmesPath/Env.php +5 -5
  275. vendor/Aws3/JmesPath/FnDispatcher.php +10 -10
  276. vendor/Aws3/JmesPath/JmesPath.php +2 -2
  277. vendor/Aws3/JmesPath/Lexer.php +1 -1
  278. vendor/Aws3/JmesPath/Parser.php +55 -55
  279. vendor/Aws3/JmesPath/SyntaxErrorException.php +1 -1
  280. vendor/Aws3/JmesPath/TreeCompiler.php +1 -1
  281. vendor/Aws3/JmesPath/TreeInterpreter.php +13 -13
  282. vendor/Aws3/JmesPath/Utils.php +1 -1
  283. vendor/Aws3/Psr/Http/Message/MessageInterface.php +2 -2
  284. vendor/Aws3/Psr/Http/Message/RequestInterface.php +2 -2
  285. vendor/Aws3/Psr/Http/Message/ResponseInterface.php +1 -1
  286. vendor/Aws3/Psr/Http/Message/ServerRequestInterface.php +1 -1
  287. vendor/Aws3/Psr/Http/Message/StreamInterface.php +1 -1
README.md CHANGED
@@ -1,68 +1,81 @@
1
- # WP Offload S3 Lite #
2
- **Contributors:** bradt, deliciousbrains
3
- **Tags:** uploads, amazon, s3, amazon s3, mirror, admin, media, cdn, cloudfront
4
- **Requires at least:** 4.6
5
  **Tested up to:** 4.9
6
  **Requires PHP:** 5.5
7
- **Stable tag:** 1.4.3
8
  **License:** GPLv3
9
 
10
- Copies files to Amazon S3 as they are uploaded to the Media Library. Optionally configure Amazon CloudFront for faster delivery.
11
 
12
  ## Description ##
13
 
 
 
14
  https://www.youtube.com/watch?v=_PVybEGaRXc
15
 
16
- This plugin automatically copies images, videos, documents, and any other media added through WordPress' media uploader to [Amazon S3](http://aws.amazon.com/s3/). It then automatically replaces the URL to each media file with their respective Amazon S3 URL or, if you have configured [Amazon CloudFront](http://aws.amazon.com/cloudfront/), the respective CloudFront URL. Image thumbnails are also copied to Amazon S3 and delivered through S3/CloudFront.
17
 
18
- Uploading files *directly* to your Amazon S3 account is not currently supported by this plugin. They are uploaded to your server first, then copied to Amazon S3. There is an option to automatically remove the files from your server once they are copied to Amazon S3 however.
19
 
20
- If you're adding this plugin to a site that's been around for a while, your existing media files will not be copied or served from Amazon S3. Only newly uploaded files will be copied and served from Amazon S3. The pro upgrade has an upload tool to handle existing media files.
21
 
22
  **PRO Upgrade with Email Support and More Features**
23
 
24
- * Upload existing Media Library to Amazon S3
25
- * Control Amazon S3 files from the Media Library
26
- * [Assets addon](https://deliciousbrains.com/wp-offload-s3/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=assets%2Baddon#addons) - Serve your CSS & JS from Amazon S3/CloudFront
27
- * [WooCommerce integration](https://deliciousbrains.com/wp-offload-s3/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=woocommerce%2Baddon#integrations)
28
- * [Easy Digital Downloads integration](https://deliciousbrains.com/wp-offload-s3/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=edd%2Baddon#integrations)
29
  * PriorityExpert™ email support
30
 
31
- [Compare pro vs free →](https://deliciousbrains.com/wp-offload-s3/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
32
 
33
  The video below runs through the pro upgrade features...
34
 
35
  https://www.youtube.com/watch?v=55xNGnbJ_CY
36
 
37
- *This plugin has been completely rewritten, but was originally a fork of
38
- [Amazon S3 for WordPress with CloudFront](http://wordpress.org/extend/plugins/tantan-s3-cloudfront/)
39
- which is a fork of [Amazon S3 for WordPress](http://wordpress.org/extend/plugins/tantan-s3/), also known as tantan-s3.*
40
 
41
  ## Installation ##
42
 
43
  1. Install this plugin using WordPress' built-in installer
44
- 2. Access the *Offload S3* option under *Settings*
45
- 3. Follow the instructions to setup your AWS access keys and configure
46
 
47
- Check out the [Quick Start Guide](https://deliciousbrains.com/wp-offload-s3/doc/quick-start-guide/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting) for more information on configuring WP Offload S3.
48
 
49
  ## Frequently Asked Questions ##
50
 
51
  ### What are the minimum requirements? ###
52
 
53
- You can see the minimum requirements [here](https://deliciousbrains.com/wp-offload-s3/pricing/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=requirements#requirements).
 
 
 
 
54
 
55
  ## Screenshots ##
56
 
57
- ### 1. Choosing/creating a bucket ###
58
- ![Choosing/creating a bucket](https://raw.githubusercontent.com/deliciousbrains/wp-wp-offload-s3-lite/assets/screenshot-1.png)
 
 
 
59
 
60
- ### 2. Settings screen ###
61
- ![Settings screen](https://raw.githubusercontent.com/deliciousbrains/wp-wp-offload-s3-lite/assets/screenshot-2.png)
 
 
 
62
 
63
 
64
  ## Upgrade Notice ##
65
 
 
 
 
66
  ### 1.1 ###
67
  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.
68
 
@@ -71,6 +84,12 @@ This version requires PHP 5.3.3+ and the Amazon Web Services plugin
71
 
72
  ## Changelog ##
73
 
 
 
 
 
 
 
74
  ### WP Offload S3 Lite 1.4.3 - 2018-08-02 ###
75
  * Bug fix: Images remotely edited via stream wrapper sometimes set as private on S3
76
 
1
+ # WP Offload Media Lite for Amazon S3 and DigitalOcean Spaces #
2
+ **Contributors:** bradt, deliciousbrains, ianmjones
3
+ **Tags:** uploads, amazon, s3, amazon s3, digitalocean, digitalocean spaces, mirror, admin, media, cdn, cloudfront
4
+ **Requires at least:** 4.7
5
  **Tested up to:** 4.9
6
  **Requires PHP:** 5.5
7
+ **Stable tag:** 2.0
8
  **License:** GPLv3
9
 
10
+ Copies files to Amazon S3 or DigitalOcean Spaces as they are uploaded to the Media Library. Optionally configure Amazon CloudFront or another CDN for faster delivery.
11
 
12
  ## Description ##
13
 
14
+ FORMERLY WP OFFLOAD S3 LITE
15
+
16
  https://www.youtube.com/watch?v=_PVybEGaRXc
17
 
18
+ This plugin automatically copies images, videos, documents, and any other media added through WordPress' media uploader to [Amazon S3](http://aws.amazon.com/s3/) or [DigitalOcean Spaces](https://www.digitalocean.com/products/spaces/). It then automatically replaces the URL to each media file with their respective Amazon S3 or DigitalOcean Spaces URL or, if you have configured [Amazon CloudFront](http://aws.amazon.com/cloudfront/) or another CDN with or without a custom domain, that URL instead. Image thumbnails are also copied to the bucket and delivered through the correct remote URL.
19
 
20
+ Uploading files *directly* to your Amazon S3 or DigitalOcean Spaces account is not currently supported by this plugin. They are uploaded to your server first, then copied to the bucket. There is an option to automatically remove the files from your server once they are copied to the bucket however.
21
 
22
+ If you're adding this plugin to a site that's been around for a while, your existing media files will not be copied to or served from Amazon S3 or DigitalOcean Spaces. Only newly uploaded files will be copied to and served from the bucket. The pro upgrade has an upload tool to handle existing media files.
23
 
24
  **PRO Upgrade with Email Support and More Features**
25
 
26
+ * Upload existing Media Library to Amazon S3 or DigitalOcean Spaces
27
+ * Control offloaded files from the Media Library
28
+ * [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
29
+ * [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)
30
+ * [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)
31
  * PriorityExpert™ email support
32
 
33
+ [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)
34
 
35
  The video below runs through the pro upgrade features...
36
 
37
  https://www.youtube.com/watch?v=55xNGnbJ_CY
38
 
39
+ *This plugin has been completely rewritten, but was originally a fork of [Amazon S3 for WordPress with CloudFront](http://wordpress.org/extend/plugins/tantan-s3-cloudfront/) which is a fork of [Amazon S3 for WordPress](http://wordpress.org/extend/plugins/tantan-s3/), also known as tantan-s3.*
 
 
40
 
41
  ## Installation ##
42
 
43
  1. Install this plugin using WordPress' built-in installer
44
+ 2. Access the *Offload Media* option under *Settings*
45
+ 3. Follow the instructions to set up your AWS or DigitalOcean access keys and configure
46
 
47
+ Check out the [Quick Start Guide](https://deliciousbrains.com/wp-offload-media/doc/quick-start-guide/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting) for more information on configuring WP Offload Media.
48
 
49
  ## Frequently Asked Questions ##
50
 
51
  ### What are the minimum requirements? ###
52
 
53
+ You can see the minimum requirements [here](https://deliciousbrains.com/wp-offload-media/pricing/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=requirements#requirements).
54
+
55
+ ### Do you offer email support? ###
56
+
57
+ If you upgrade to the pro version of [WP Offload Media](https://deliciousbrains.com/wp-offload-media/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting), we will gladly provide you with email support. We take pride in delivering exceptional customer support. We do not provide email support for the free version.
58
 
59
  ## Screenshots ##
60
 
61
+ ### 1. Select Cloud Storage Provider ###
62
+ ![Select Cloud Storage Provider](https://raw.githubusercontent.com/deliciousbrains/wp-wp-offload-media-lite-for-amazon-s3-and-digitalocean-spaces/assets/screenshot-1.png)
63
+
64
+ ### 2. Select or Create Bucket ###
65
+ ![Select or Create Bucket](https://raw.githubusercontent.com/deliciousbrains/wp-wp-offload-media-lite-for-amazon-s3-and-digitalocean-spaces/assets/screenshot-2.png)
66
 
67
+ ### 3. Settings Screen ###
68
+ ![Settings Screen](https://raw.githubusercontent.com/deliciousbrains/wp-wp-offload-media-lite-for-amazon-s3-and-digitalocean-spaces/assets/screenshot-3.png)
69
+
70
+ ### 4. Custom Domain Used With CDN ###
71
+ ![Custom Domain Used With CDN](https://raw.githubusercontent.com/deliciousbrains/wp-wp-offload-media-lite-for-amazon-s3-and-digitalocean-spaces/assets/screenshot-4.png)
72
 
73
 
74
  ## Upgrade Notice ##
75
 
76
+ ### 2.0 ###
77
+ 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+.
78
+
79
  ### 1.1 ###
80
  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.
81
 
84
 
85
  ## Changelog ##
86
 
87
+ ### WP Offload Media Lite 2.0 - 2018-09-24 ###
88
+ * [Release Summary Blog Post](https://deliciousbrains.com/wp-offload-media-supports-digitalocean-spaces/)
89
+ * New: DigitalOcean Spaces is now supported
90
+ * New: Plugin name updated from WP Offload S3 Lite to WP Offload Media Lite
91
+ * Improvement: More logical UI layout and better description of each setting
92
+
93
  ### WP Offload S3 Lite 1.4.3 - 2018-08-02 ###
94
  * Bug fix: Images remotely edited via stream wrapper sometimes set as private on S3
95
 
assets/css/attachment.css CHANGED
@@ -1 +1 @@
1
- #s3-actions.postbox .inside{margin:0;padding:0}#s3-actions.postbox a,#s3-actions.postbox a:hover{text-decoration:none}#s3-actions.postbox .s3-details{padding:6px 0}#s3-actions.postbox .s3-details .misc-pub-section{clear:both;float:left;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}#s3-actions.postbox .s3-details .misc-pub-section .s3-key{float:left;width:20%}#s3-actions.postbox .s3-details .misc-pub-section .s3-value{font-weight:bold;float:left;width:80%}#s3-actions.postbox .s3-details .not-copied{color:#666666}#s3-actions.postbox .s3-actions{padding:10px;clear:both;border-top:1px solid #ddd;border-bottom:1px solid #ddd;background:#f5f5f5}#s3-actions.postbox .s3-actions .copy-action{text-align:right;float:right;line-height:23px}#s3-actions.postbox .s3-actions .remove-action{line-height:28px;vertical-align:middle;text-align:left;float:left}#s3-actions.postbox .s3-actions .remove-action a.local-warning{color:#a00}#s3-actions.postbox .s3-actions .remove-action a.local-warning:hover{color:#f00}
1
+ #s3-actions.postbox .inside{margin:0;padding:0}#s3-actions.postbox a,#s3-actions.postbox a:hover{text-decoration:none}#s3-actions.postbox .s3-details{padding:6px 0}#s3-actions.postbox .s3-details .misc-pub-section{clear:both;float:left;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}#s3-actions.postbox .s3-details .misc-pub-section .s3-key{float:left;width:20%;white-space:nowrap}#s3-actions.postbox .s3-details .misc-pub-section .s3-value{font-weight:bold;float:left;width:80%}#s3-actions.postbox .s3-details .misc-pub-section input.error{color:#a00}#s3-actions.postbox .s3-details .not-copied{color:#666}#s3-actions.postbox .s3-actions{padding:10px;clear:both;border-top:1px solid #ddd;border-bottom:1px solid #ddd;background:#f5f5f5}#s3-actions.postbox .s3-actions .copy-action{text-align:right;float:right;line-height:23px}#s3-actions.postbox .s3-actions .remove-action{line-height:28px;vertical-align:middle;text-align:left;float:left}#s3-actions.postbox .s3-actions .remove-action a.local-warning{color:#a00}#s3-actions.postbox .s3-actions .remove-action a.local-warning:hover{color:#f00}
assets/css/notice.css CHANGED
@@ -1 +1 @@
1
- .as3cf-notice p,.as3cf-compatibility-notice p{max-width:800px}.as3cf-license-notice p:not(.as3cf-before):before{display:none}.as3cf-notice-warning{border-left-color:#ffba00}
1
+ .as3cf-notice p,.as3cf-compatibility-notice p{max-width:800px}.as3cf-licence-notice p:not(.as3cf-before):before{display:none}.as3cf-notice-warning{border-left-color:#ffba00}
assets/css/storage-provider.css ADDED
@@ -0,0 +1 @@
 
1
+ .as3cf-provider-select h3{font-size:20px}.as3cf-provider-select table{border-collapse:collapse}.as3cf-provider-select .as3cf-provider-title{margin:0;padding:0;background:#f1f1f1}.as3cf-provider-select .as3cf-provider-title label{position:relative;display:inline-block}.as3cf-provider-select .as3cf-provider-title label:hover{cursor:pointer}.as3cf-provider-select .as3cf-provider-title .as3cf-provider-logo{color:white;padding:1em}.as3cf-provider-select .as3cf-provider-title h3{display:inline-block;position:absolute;top:50%;left:76px;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);font-weight:bold;text-transform:none;padding:0;margin:0 15px;white-space:nowrap}.as3cf-provider-select .as3cf-provider-title.as3cf-provider-selected{cursor:default}.as3cf-provider-select .as3cf-provider-title.as3cf-provider-aws .as3cf-provider-logo{background-color:#f7a80d}.as3cf-provider-select .as3cf-provider-title.as3cf-provider-do .as3cf-provider-logo{background-color:#0080ff}.as3cf-provider-select .as3cf-provider-content td{padding-bottom:10px}.as3cf-provider-select .as3cf-provider-content table{background:#e5e5e5}.as3cf-provider-select .as3cf-provider-content table th{padding:10px 0 10px 10px}.as3cf-provider-select .as3cf-provider-content table td{padding:10px}.as3cf-provider-select .as3cf-provider-content .asc3f-provider-authmethod-title label{font-weight:bold}.as3cf-provider-select .as3cf-provider-content .asc3f-provider-authmethod-content td{padding-top:0}.as3cf-provider-select .as3cf-provider-content .asc3f-provider-authmethod-content textarea.as3cf-define-snippet.code{width:100%;white-space:pre;overflow:hidden;font-size:11px;padding:10px;margin-top:10px}.as3cf-provider-select .as3cf-provider-content .asc3f-provider-authmethod-content table.as3cf-access-keys{margin-top:10px}.as3cf-provider-select .as3cf-provider-content .asc3f-provider-authmethod-content table.as3cf-access-keys th{padding-left:0}.as3cf-provider-select .as3cf-provider-content .asc3f-provider-authmethod-content table.as3cf-access-keys input{width:100%}
assets/css/styles.css CHANGED
@@ -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{display:none}.as3cf-tab .as3cf-bucket-container{display:block}.as3cf-tab.as3cf-has-bucket .as3cf-main-settings{display:block}.as3cf-tab.as3cf-has-bucket .as3cf-bucket-container{display:none}.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 td{padding:15px 0}.as3cf-tab .form-table tr td:first-child{vertical-align:top;min-width:120px}.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 tr.as3cf-bucket-setting .as3cf-defined-in-config{float:none}.as3cf-tab .form-table h3{padding:0;margin:0}.as3cf-tab .form-table h4{margin:0}.as3cf-tab .as3cf-active-bucket{font-weight:bold;margin-right:10px}.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}#tab-media{display:block}#tab-media .as3cf-main-settings{display:none}#tab-media .as3cf-bucket-setting td{padding-top:5px}#tab-media .as3cf-bucket-container{display:block}#tab-media.as3cf-has-bucket .as3cf-main-settings{display:block}#tab-media.as3cf-has-bucket .as3cf-bucket-container{display:none}.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 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 .bucket-actions .bucket-action-cancel{color:#a00;text-decoration:none}.as3cf-bucket-container .bucket-actions .bucket-action-cancel:hover{color:red}.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-bucket-container .as3cf-bucket-select,.as3cf-bucket-container .as3cf-bucket-create{display:none}.as3cf-bucket-container .bucket-actions.select{display:none}#tab-media{display:block}#tab-settings .as3cf-field-wrap{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}#tab-settings .as3cf-field-wrap input{width:100%}#tab-settings .as3cf-field-wrap button,#tab-settings .as3cf-field-wrap .as3cf-defined-in-config{margin-left:20px}#tab-settings .as3cf-field-wrap .as3cf-defined-in-config{display:none;margin-bottom:0}#tab-settings .as3cf-field-wrap.as3cf-defined button{display:none}#tab-settings .as3cf-field-wrap.as3cf-defined .as3cf-defined-in-config{display:inline-block}#tab-settings .as3cf-field-wrap.as3cf-saved-field .as3cf-activate-licence{display:none}#tab-settings .as3cf-field-wrap.as3cf-licence-not-entered .as3cf-remove-licence{display:none}#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-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-aws-logo{color:white;background-color:#f7a80d;padding:1em}.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{display:none}.as3cf-tab .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab .as3cf-bucket-container{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-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings{display:block}.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-media-settings,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-main-settings .as3cf-media-settings{display:none}.as3cf-tab.as3cf-needs-access-keys .as3cf-bucket-container,.as3cf-tab.as3cf-has-access-keys.as3cf-change-provider .as3cf-bucket-container{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-main-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-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-media-settings{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) .as3cf-bucket-container{display:block}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider) .as3cf-main-settings{display:block}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-provider-select{display:none}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider) .as3cf-main-settings .as3cf-media-settings{display:block}.as3cf-tab.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider) .as3cf-bucket-container{display:none}.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}#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 .bucket-actions .bucket-action-cancel{color:#a00;text-decoration:none}.as3cf-bucket-container .bucket-actions .bucket-action-cancel:hover{color:red}.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-bucket-container .as3cf-bucket-select,.as3cf-bucket-container .as3cf-bucket-create{display:none}.as3cf-bucket-container .bucket-actions.select{display:none}#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}
assets/img/do-logo.svg ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 50 50">
2
+ <g fill="#FFFFFF" fill-rule="evenodd">
3
+ <path d="M24.9153 50v-9.661c10.226 0 18.1638-10.1413 14.2372-20.904-1.4406-3.983-4.6327-7.1751-8.6158-8.6158C19.774 6.921 9.6327 14.8305 9.6327 25.0565H0C0 8.7571 15.7627-3.9548 32.8531 1.3842c7.4576 2.3446 13.418 8.2768 15.7345 15.7344C53.9266 34.2373 41.2429 50 24.9153 50"></path>
4
+ <path d="M15.339 40.3672h9.6045v-9.6045H15.339zM7.9379 47.7684h7.401v-7.4012H7.938zM1.7514 40.3672H7.938v-6.1864H1.7514z"></path>
5
+ </g>
6
+ </svg>
assets/js/media.js CHANGED
@@ -1,6 +1,6 @@
1
  var test = {};
2
 
3
- (function( $, _ ) {
4
 
5
  // Local reference to the WordPress media namespace.
6
  var media = wp.media;
@@ -26,9 +26,9 @@ var test = {};
26
  },
27
 
28
  fetchS3Details: function( id ) {
29
- wp.ajax.send( 'as3cf_get_attachment_s3_details', {
30
  data: {
31
- _nonce: as3cf_media.nonces.get_attachment_s3_details,
32
  id: id
33
  }
34
  } ).done( _.bind( this.renderView, this ) );
@@ -59,11 +59,11 @@ var test = {};
59
  },
60
 
61
  renderS3Details: function( response ) {
62
- if ( ! response || ! response.s3object ) {
63
  return;
64
  }
65
  var $detailsHtml = this.$el.find( '.attachment-info .details' );
66
- var html = this.generateDetails( response, [ 'bucket', 'key', 'region', 'acl' ] );
67
  $detailsHtml.append( html );
68
  },
69
 
@@ -72,18 +72,18 @@ var test = {};
72
  var template = _.template( '<div class="<%= key %>"><strong><%= label %>:</strong> <%= value %></div>' );
73
 
74
  _( keys ).each( function( key ) {
75
- if ( response.s3object[ key ] ) {
76
- var value = response.s3object[ key ];
77
 
78
  if ( 'acl' === key ) {
79
- value = response.s3object[ key ]['name'];
80
 
81
  if ( response.acl_toggle ) {
82
  var acl_template = _.template( '<a href="#" id="as3cfpro-toggle-acl" title="<%= title %>" data-currentACL="<%= acl %>"><%= value %></a>' );
83
 
84
  value = acl_template( {
85
- title: response.s3object[ key ][ 'title' ],
86
- acl: response.s3object[ key ][ 'acl' ],
87
  value: value
88
  } );
89
  }
@@ -123,12 +123,12 @@ var test = {};
123
  }
124
 
125
  wp.ajax.send( 'as3cfpro_update_acl', {
126
- data: {
127
- _ajax_nonce: as3cfpro_media.nonces.singular_update_acl,
128
- id: this.model.get( 'id' ),
129
- acl: newACL
130
- }
131
- } )
132
  .done( _.bind( this.updateACL, this ) )
133
  .fail( _.bind( this.renderACLError, this ) );
134
  },
@@ -160,4 +160,4 @@ var test = {};
160
  }
161
  } );
162
 
163
- })( jQuery, _ );
1
  var test = {};
2
 
3
+ ( function( $, _ ) {
4
 
5
  // Local reference to the WordPress media namespace.
6
  var media = wp.media;
26
  },
27
 
28
  fetchS3Details: function( id ) {
29
+ wp.ajax.send( 'as3cf_get_attachment_provider_details', {
30
  data: {
31
+ _nonce: as3cf_media.nonces.get_attachment_provider_details,
32
  id: id
33
  }
34
  } ).done( _.bind( this.renderView, this ) );
59
  },
60
 
61
  renderS3Details: function( response ) {
62
+ if ( ! response || ! response.provider_object ) {
63
  return;
64
  }
65
  var $detailsHtml = this.$el.find( '.attachment-info .details' );
66
+ var html = this.generateDetails( response, [ 'provider_name', 'region', 'bucket', 'key', 'acl' ] );
67
  $detailsHtml.append( html );
68
  },
69
 
72
  var template = _.template( '<div class="<%= key %>"><strong><%= label %>:</strong> <%= value %></div>' );
73
 
74
  _( keys ).each( function( key ) {
75
+ if ( response.provider_object[ key ] ) {
76
+ var value = response.provider_object[ key ];
77
 
78
  if ( 'acl' === key ) {
79
+ value = response.provider_object[ key ][ 'name' ];
80
 
81
  if ( response.acl_toggle ) {
82
  var acl_template = _.template( '<a href="#" id="as3cfpro-toggle-acl" title="<%= title %>" data-currentACL="<%= acl %>"><%= value %></a>' );
83
 
84
  value = acl_template( {
85
+ title: response.provider_object[ key ][ 'title' ],
86
+ acl: response.provider_object[ key ][ 'acl' ],
87
  value: value
88
  } );
89
  }
123
  }
124
 
125
  wp.ajax.send( 'as3cfpro_update_acl', {
126
+ data: {
127
+ _ajax_nonce: as3cfpro_media.nonces.singular_update_acl,
128
+ id: this.model.get( 'id' ),
129
+ acl: newACL
130
+ }
131
+ } )
132
  .done( _.bind( this.updateACL, this ) )
133
  .fail( _.bind( this.renderACLError, this ) );
134
  },
160
  }
161
  } );
162
 
163
+ } )( jQuery, _ );
assets/js/media.min.js CHANGED
@@ -1 +1 @@
1
- var test={};!function(a,b){var c=wp.media,d=c.view.Attachment.Details.TwoColumn;c.view.Attachment.Details.TwoColumn=d.extend({events:function(){return b.extend({},d.prototype.events,{"click .local-warning":"confirmS3Removal","click #as3cfpro-toggle-acl":"toggleACL"})},render:function(){this.fetchS3Details(this.model.get("id"))},fetchS3Details:function(a){wp.ajax.send("as3cf_get_attachment_s3_details",{data:{_nonce:as3cf_media.nonces.get_attachment_s3_details,id:a}}).done(b.bind(this.renderView,this))},renderView:function(a){d.prototype.render.apply(this),this.renderActionLinks(a),this.renderS3Details(a)},renderActionLinks:function(c){var d=c&&c.links||[],e=this.$el.find(".actions"),f=a("<div />",{"class":"s3-actions"}),g=[];b(d).each(function(a){g.push(a)}),f.append(g.join(" | ")),e.append(f)},renderS3Details:function(a){if(a&&a.s3object){var b=this.$el.find(".attachment-info .details"),c=this.generateDetails(a,["bucket","key","region","acl"]);b.append(c)}},generateDetails:function(a,c){var d="",e=b.template('<div class="<%= key %>"><strong><%= label %>:</strong> <%= value %></div>');return b(c).each(function(c){if(a.s3object[c]){var f=a.s3object[c];if("acl"===c&&(f=a.s3object[c].name,a.acl_toggle)){var g=b.template('<a href="#" id="as3cfpro-toggle-acl" title="<%= title %>" data-currentACL="<%= acl %>"><%= value %></a>');f=g({title:a.s3object[c].title,acl:a.s3object[c].acl,value:f})}d+=e({key:c,label:as3cf_media.strings[c],value:f})}}),d},confirmS3Removal:function(a){if(!confirm(as3cfpro_media.strings.local_warning))return a.preventDefault(),a.stopImmediatePropagation(),!1},toggleACL:function(c){c.preventDefault();var d=a("#as3cfpro-toggle-acl"),e=d.data("currentacl"),f=as3cfpro_media.settings.private_acl;d.hide(),d.after('<span id="as3cfpro-updating">'+as3cfpro_media.strings.updating_acl+"</span>"),e===as3cfpro_media.settings.private_acl&&(f=as3cfpro_media.settings.default_acl),wp.ajax.send("as3cfpro_update_acl",{data:{_ajax_nonce:as3cfpro_media.nonces.singular_update_acl,id:this.model.get("id"),acl:f}}).done(b.bind(this.updateACL,this)).fail(b.bind(this.renderACLError,this))},renderACLError:function(){a("#as3cfpro-updating").remove(),a("#as3cfpro-toggle-acl").show(),alert(as3cfpro_media.strings.change_acl_error)},updateACL:function(b){if(null==b.acl_display||null==b.title||null==b.acl||null==b.url)return void this.renderACLError();this.model.set("url",b.url),this.render();var c=a("#as3cfpro-toggle-acl");a("#as3cfpro-updating").remove(),c.text(b.acl_display),c.attr("title",b.title),c.data("currentacl",b.acl),c.show()}})}(jQuery,_);
1
+ var test={};!function(a,b){var c=wp.media,d=c.view.Attachment.Details.TwoColumn;c.view.Attachment.Details.TwoColumn=d.extend({events:function(){return b.extend({},d.prototype.events,{"click .local-warning":"confirmS3Removal","click #as3cfpro-toggle-acl":"toggleACL"})},render:function(){this.fetchS3Details(this.model.get("id"))},fetchS3Details:function(a){wp.ajax.send("as3cf_get_attachment_provider_details",{data:{_nonce:as3cf_media.nonces.get_attachment_provider_details,id:a}}).done(b.bind(this.renderView,this))},renderView:function(a){d.prototype.render.apply(this),this.renderActionLinks(a),this.renderS3Details(a)},renderActionLinks:function(c){var d=c&&c.links||[],e=this.$el.find(".actions"),f=a("<div />",{"class":"s3-actions"}),g=[];b(d).each(function(a){g.push(a)}),f.append(g.join(" | ")),e.append(f)},renderS3Details:function(a){if(a&&a.provider_object){var b=this.$el.find(".attachment-info .details"),c=this.generateDetails(a,["provider_name","region","bucket","key","acl"]);b.append(c)}},generateDetails:function(a,c){var d="",e=b.template('<div class="<%= key %>"><strong><%= label %>:</strong> <%= value %></div>');return b(c).each(function(c){if(a.provider_object[c]){var f=a.provider_object[c];if("acl"===c&&(f=a.provider_object[c].name,a.acl_toggle)){var g=b.template('<a href="#" id="as3cfpro-toggle-acl" title="<%= title %>" data-currentACL="<%= acl %>"><%= value %></a>');f=g({title:a.provider_object[c].title,acl:a.provider_object[c].acl,value:f})}d+=e({key:c,label:as3cf_media.strings[c],value:f})}}),d},confirmS3Removal:function(a){if(!confirm(as3cfpro_media.strings.local_warning))return a.preventDefault(),a.stopImmediatePropagation(),!1},toggleACL:function(c){c.preventDefault();var d=a("#as3cfpro-toggle-acl"),e=d.data("currentacl"),f=as3cfpro_media.settings.private_acl;d.hide(),d.after('<span id="as3cfpro-updating">'+as3cfpro_media.strings.updating_acl+"</span>"),e===as3cfpro_media.settings.private_acl&&(f=as3cfpro_media.settings.default_acl),wp.ajax.send("as3cfpro_update_acl",{data:{_ajax_nonce:as3cfpro_media.nonces.singular_update_acl,id:this.model.get("id"),acl:f}}).done(b.bind(this.updateACL,this)).fail(b.bind(this.renderACLError,this))},renderACLError:function(){a("#as3cfpro-updating").remove(),a("#as3cfpro-toggle-acl").show(),alert(as3cfpro_media.strings.change_acl_error)},updateACL:function(b){if(null==b.acl_display||null==b.title||null==b.acl||null==b.url)return void this.renderACLError();this.model.set("url",b.url),this.render();var c=a("#as3cfpro-toggle-acl");a("#as3cfpro-updating").remove(),c.text(b.acl_display),c.attr("title",b.title),c.data("currentacl",b.acl),c.show()}})}(jQuery,_);
assets/js/modal.js CHANGED
@@ -140,6 +140,10 @@ var as3cfModal = (function( $ ) {
140
  } );
141
 
142
  $( 'body' ).on( 'click', '#as3cf-overlay, .close-as3cf-modal', function( e ) {
 
 
 
 
143
  e.preventDefault();
144
 
145
  // Don't allow children to bubble up click event
140
  } );
141
 
142
  $( 'body' ).on( 'click', '#as3cf-overlay, .close-as3cf-modal', function( e ) {
143
+ if ( 'A' === e.target.tagName ) {
144
+ return;
145
+ }
146
+
147
  e.preventDefault();
148
 
149
  // Don't allow children to bubble up click event
assets/js/modal.min.js CHANGED
@@ -1 +1 @@
1
- var as3cfModal=function(a){function b(a){return a.replace(/[^a-z]/g,"")}var c={prefix:"as3cf",loading:!1,dismissible:!0},d={};return c.exists=function(c){var e=b(c);return void 0!==d[e]||!!a(c).length},c.open=function(e,f,g){var h=b(e);a("body").append('<div id="as3cf-overlay"></div>');var i=a("#as3cf-overlay");c.dismissible?i.append('<div id="as3cf-modal"><span class="close-as3cf-modal">×</span></div>'):i.append('<div id="as3cf-modal"></div>');var j=a("#as3cf-modal");if(void 0===d[h]){var k=a(e);d[h]=k.clone(!0).css("display","block"),k.remove()}j.data("as3cf-modal-target",e).append(d[h]),void 0!==g&&j.addClass(g),"function"==typeof f&&f(e),a("body").addClass("as3cf-modal-open"),i.fadeIn(150),j.fadeIn(150),a("body").trigger("as3cf-modal-open",[e])},c.close=function(b){if(!c.loading&&c.dismissible){var d=a("#as3cf-modal").data("as3cf-modal-target");a("#as3cf-overlay").fadeOut(150,function(){a("body").removeClass("as3cf-modal-open"),a(this).remove(),"function"==typeof b&&b(d)}),a("body").trigger("as3cf-modal-close",[d])}},c.setLoadingState=function(a){c.loading=a},c.setDismissibleState=function(a){c.dismissible=a},a(document).ready(function(){a("body").on("click","[data-as3cf-modal]",function(b){b.preventDefault(),c.open(a(this).data("as3cf-modal")+"."+c.prefix)}),a("body").on("click","#as3cf-overlay, .close-as3cf-modal",function(a){return a.preventDefault(),a.target===this&&void c.close()})}),c}(jQuery);
1
+ var as3cfModal=function(a){function b(a){return a.replace(/[^a-z]/g,"")}var c={prefix:"as3cf",loading:!1,dismissible:!0},d={};return c.exists=function(c){var e=b(c);return void 0!==d[e]||!!a(c).length},c.open=function(e,f,g){var h=b(e);a("body").append('<div id="as3cf-overlay"></div>');var i=a("#as3cf-overlay");c.dismissible?i.append('<div id="as3cf-modal"><span class="close-as3cf-modal">×</span></div>'):i.append('<div id="as3cf-modal"></div>');var j=a("#as3cf-modal");if(void 0===d[h]){var k=a(e);d[h]=k.clone(!0).css("display","block"),k.remove()}j.data("as3cf-modal-target",e).append(d[h]),void 0!==g&&j.addClass(g),"function"==typeof f&&f(e),a("body").addClass("as3cf-modal-open"),i.fadeIn(150),j.fadeIn(150),a("body").trigger("as3cf-modal-open",[e])},c.close=function(b){if(!c.loading&&c.dismissible){var d=a("#as3cf-modal").data("as3cf-modal-target");a("#as3cf-overlay").fadeOut(150,function(){a("body").removeClass("as3cf-modal-open"),a(this).remove(),"function"==typeof b&&b(d)}),a("body").trigger("as3cf-modal-close",[d])}},c.setLoadingState=function(a){c.loading=a},c.setDismissibleState=function(a){c.dismissible=a},a(document).ready(function(){a("body").on("click","[data-as3cf-modal]",function(b){b.preventDefault(),c.open(a(this).data("as3cf-modal")+"."+c.prefix)}),a("body").on("click","#as3cf-overlay, .close-as3cf-modal",function(a){if("A"!==a.target.tagName)return a.preventDefault(),a.target===this&&void c.close()})}),c}(jQuery);
assets/js/script.js CHANGED
@@ -1,4 +1,4 @@
1
- (function( $, as3cfModal ) {
2
 
3
  var savedSettings = {};
4
  var bucketNamePattern = /[^a-z0-9.-]/;
@@ -60,7 +60,7 @@
60
  * Toggle settings tab
61
  *
62
  * @param string hash
63
- * @param bool persist_updated_notice
64
  */
65
  toggle: function( hash, persist_updated_notice ) {
66
  hash = as3cf.tabs.sanitizeHash( hash );
@@ -151,14 +151,16 @@
151
  /**
152
  * Load bucket list
153
  *
154
- * @param {bool} [forceUpdate]
155
  */
156
  loadList: function( forceUpdate ) {
157
  if ( 'undefined' === typeof forceUpdate ) {
158
  forceUpdate = false;
159
  }
160
 
161
- var $bucketList = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-bucket-list' );
 
 
162
  var selectedBucket = $( '#' + as3cfModal.prefix + '-bucket' ).val();
163
 
164
  if ( false === forceUpdate && $bucketList.find( 'li' ).length > 1 ) {
@@ -176,6 +178,10 @@
176
  _nonce: window[ as3cfModal.prefix.replace( /-/g, '_' ) ].nonces.get_buckets
177
  };
178
 
 
 
 
 
179
  var that = this;
180
 
181
  $.ajax( {
@@ -193,12 +199,16 @@
193
  if ( 'undefined' !== typeof data[ 'success' ] ) {
194
  $( '.as3cf-bucket-error' ).hide();
195
 
196
- $( data[ 'buckets' ] ).each( function( idx, bucket ) {
197
- var bucketClass = bucket.Name === selectedBucket ? 'selected' : '';
198
- $bucketList.append( '<li><a class="' + bucketClass + '" href="#" data-bucket="' + bucket.Name + '"><span class="bucket"><span class="dashicons dashicons-portfolio"></span> ' + bucket.Name + '</span><span class="spinner"></span></span></a></li>' );
199
- } );
 
 
 
200
 
201
- that.scrollToSelected();
 
202
  } else {
203
  that.showError( as3cf.strings.get_buckets_error, data[ 'error' ], 'as3cf-bucket-select' );
204
  }
@@ -254,6 +264,7 @@
254
  */
255
  saveManual: function() {
256
  var $manualBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-manual-save-bucket-form' );
 
257
  var $manualBucketInput = $manualBucketForm.find( '.as3cf-bucket-name' );
258
  var $manualBucketButton = $manualBucketForm.find( 'button[type=submit]' );
259
  var bucketName = $manualBucketInput.val();
@@ -275,6 +286,10 @@
275
  _nonce: window[ as3cfModal.prefix.replace( /-/g, '_' ) ].nonces.manual_bucket
276
  };
277
 
 
 
 
 
278
  var that = this;
279
 
280
  $.ajax( {
@@ -290,7 +305,7 @@
290
  $manualBucketButton.text( originalBucketText );
291
  $manualBucketButton.prop( 'disabled', false );
292
  if ( 'undefined' !== typeof data[ 'success' ] ) {
293
- that.set( bucketName, data[ 'region' ], data[ 'can_write' ] );
294
  $( '#' + as3cfModal.prefix + '-bucket-select' ).val( 'manual' );
295
  $( '.as3cf-bucket-list a' ).removeClass( 'selected' ).filter( '[data-bucket="' + bucketName + '"]' ).addClass( 'selected' );
296
 
@@ -311,8 +326,6 @@
311
  * @param {object} $link
312
  */
313
  saveSelected: function( $link ) {
314
- var $bucketList = $( '.as3cf-bucket-list' );
315
-
316
  if ( this.bucketSelectLock ) {
317
 
318
  // Bail if a bucket has already been clicked
@@ -322,13 +335,17 @@
322
  // Lock the bucket selection
323
  this.bucketSelectLock = true;
324
 
 
 
 
 
325
  if ( $link.hasClass( 'selected' ) ) {
326
  $activeTab.addClass( 'as3cf-has-bucket' );
327
  as3cfModal.close();
328
  return;
329
  }
330
 
331
- var previousBucket = $( '.as3cf-bucket-list a.selected' ).data( 'bucket' );
332
 
333
  $( '.as3cf-bucket-list a' ).removeClass( 'selected' );
334
  $link.addClass( 'selected' );
@@ -343,6 +360,10 @@
343
  _nonce: window[ as3cfModal.prefix.replace( /-/g, '_' ) ].nonces.save_bucket
344
  };
345
 
 
 
 
 
346
  var that = this;
347
 
348
  $.ajax( {
@@ -360,7 +381,7 @@
360
  $link.find( '.spinner' ).hide().css( 'visibility', 'hidden' );
361
  $bucketList.removeClass( 'saving' );
362
  if ( 'undefined' !== typeof data[ 'success' ] ) {
363
- that.set( bucketName, data[ 'region' ], data[ 'can_write' ] );
364
  $( '#' + as3cfModal.prefix + '-bucket-select' ).val( '' );
365
 
366
  as3cf.showSettingsSavedNotice();
@@ -427,10 +448,14 @@
427
  *
428
  * @param {string} bucket
429
  * @param {string} region
430
- * @param {bool} canWrite
 
431
  */
432
- set: function( bucket, region, canWrite ) {
433
- var $manualBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-manual-save-bucket-form' );
 
 
 
434
  var $activeBucket = $( '#' + as3cfModal.prefix + '-active-bucket' );
435
 
436
  if ( 'as3cf' === as3cfModal.prefix && 0 === $activeBucket.text().trim().length ) {
@@ -448,9 +473,15 @@
448
  $( '.as3cf-error.fatal' ).hide();
449
 
450
  $activeBucket.text( bucket );
451
- $manualBucketForm.find( '.as3cf-bucket-name' ).val( bucket );
452
  $( '#' + as3cfModal.prefix + '-bucket' ).val( bucket );
 
 
 
 
 
453
  $( '#' + as3cfModal.prefix + '-region' ).val( region );
 
454
  $( '.updated' ).not( '.as3cf-notice' ).show();
455
 
456
  $activeTab.addClass( 'as3cf-has-bucket' );
@@ -479,7 +510,7 @@
479
  create: function() {
480
  var $createBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-create-bucket-form' );
481
  var $createBucketInput = $createBucketForm.find( '.as3cf-bucket-name' );
482
- var $createBucketSelect = $createBucketForm.find( '.bucket-create-region' );
483
  var $createBucketButton = $createBucketForm.find( 'button[type=submit]' );
484
 
485
  var bucketName = $createBucketInput.val();
@@ -495,8 +526,8 @@
495
  _nonce: window[ as3cfModal.prefix.replace( /-/g, '_' ) ].nonces.create_bucket
496
  };
497
 
498
- if ( $createBucketSelect.val() ) {
499
- data[ 'region' ] = $createBucketSelect.val();
500
  }
501
 
502
  var that = this;
@@ -514,7 +545,7 @@
514
  $createBucketButton.text( origButtonText );
515
  $createBucketButton.prop( 'disabled', false );
516
  if ( 'undefined' !== typeof data[ 'success' ] ) {
517
- that.set( bucketName, data[ 'region' ], data[ 'can_write' ] );
518
 
519
  // Tidy up create bucket form
520
  $( '.as3cf-bucket-select-region' ).hide();
@@ -541,7 +572,7 @@
541
  *
542
  * @param {string} bucketName
543
  *
544
- * @return bool
545
  */
546
  isValidName: function( bucketName ) {
547
  if ( bucketName.length < 3 || bucketName.length > 63 ) {
@@ -619,10 +650,10 @@
619
  var prefix = $objectPrefix.val();
620
 
621
  if ( '' !== prefix ) {
622
- prefix = as3cf.aws_bucket_link_param + encodeURIComponent( prefix );
623
  }
624
 
625
- var url = as3cf.aws_bucket_link + bucket + prefix;
626
 
627
  $( '#' + as3cfModal.prefix + '-view-bucket' ).attr( 'href', url );
628
  }
@@ -658,6 +689,7 @@
658
  success: function( data, textStatus, jqXHR ) {
659
  if ( 'undefined' !== typeof data[ 'success' ] ) {
660
  $( '.as3cf-url-preview' ).html( data[ 'url' ] );
 
661
  } else {
662
  alert( as3cf.strings.get_url_preview_error + data[ 'error' ] );
663
  }
@@ -687,6 +719,17 @@
687
  }
688
  }
689
 
 
 
 
 
 
 
 
 
 
 
 
690
  /**
691
  * Update the UI with the current active tab set in the URL hash.
692
  */
@@ -704,85 +747,6 @@
704
  $( document ).trigger( 'as3cf.tabRendered', [ location.hash.replace( '#', '' ) ] );
705
  }
706
 
707
- /**
708
- * Access Keys API object
709
- * @constructor
710
- */
711
- var AccessKeys = function() {
712
- this.$key = $settings.find( 'input[name="aws-access-key-id"]' );
713
- this.$secret = $settings.find( 'input[name="aws-secret-access-key"]' );
714
- this.$spinner = $settings.find( '[data-as3cf-aws-keys-spinner]' );
715
- this.$feedback = $settings.find( '[data-as3cf-aws-keys-feedback]' );
716
- };
717
-
718
- /**
719
- * Set the access keys using the values in the settings fields.
720
- */
721
- AccessKeys.prototype.set = function() {
722
- this.sendRequest( 'set', {
723
- 'aws-access-key-id': this.$key.val(),
724
- 'aws-secret-access-key': this.$secret.val()
725
- } ).done( function( response ) {
726
- if ( response.success ) {
727
- this.$secret.val( as3cf.strings.not_shown_placeholder );
728
- }
729
- }.bind( this ) );
730
- };
731
-
732
- /**
733
- * Remove the access keys from the database and clear the fields.
734
- */
735
- AccessKeys.prototype.remove = function() {
736
- this.sendRequest( 'remove' )
737
- .done( function( response ) {
738
- if ( response.success ) {
739
- this.$key.val( '' );
740
- this.$secret.val( '' );
741
- }
742
- }.bind( this ) )
743
- ;
744
- };
745
-
746
- /**
747
- * Send the request to the server to update the access keys.
748
- *
749
- * @param {string} action The action to perform with the keys
750
- * @param {undefined|Object} params Extra parameters to send with the request
751
- *
752
- * @returns {jqXHR}
753
- */
754
- AccessKeys.prototype.sendRequest = function( action, params ) {
755
- var data = {
756
- action: 'as3cf-aws-keys-' + action,
757
- _ajax_nonce: as3cf.nonces[ 'aws_keys_' + action ]
758
- };
759
-
760
- if ( _.isObject( params ) ) {
761
- data = _.extend( data, params );
762
- }
763
-
764
- this.$spinner.addClass( 'is-active' );
765
-
766
- return $.post( ajaxurl, data )
767
- .done( function( response ) {
768
- this.$feedback
769
- .toggleClass( 'notice-success', response.success )
770
- .toggleClass( 'notice-error', ! response.success );
771
-
772
- if ( response.data && response.data.message ) {
773
- this.$feedback.html( '<p>' + response.data.message + '</p>' ).show();
774
- }
775
-
776
- if ( response.success ) {
777
- as3cf.reloadUpdated();
778
- }
779
- }.bind( this ) )
780
- .always( function() {
781
- this.$spinner.removeClass( 'is-active' );
782
- }.bind( this ) )
783
- ;
784
- };
785
-
786
  $( document ).ready( function() {
787
 
788
  // Tabs
@@ -945,6 +909,12 @@
945
  as3cf.buckets.loadList( true );
946
  } );
947
 
 
 
 
 
 
 
948
  // Bucket list click handler
949
  $body.on( 'click', '.as3cf-bucket-list a', function( e ) {
950
  e.preventDefault();
@@ -1000,22 +970,6 @@
1000
  $manualBucketForm.find( 'button[type=submit]' ).prop( 'disabled', false );
1001
  }
1002
  } );
1003
-
1004
- $settings
1005
- .on( 'click', '[data-as3cf-toggle-access-keys-form]', function( event ) {
1006
- event.preventDefault();
1007
- $( '#as3cf_access_keys' ).toggle();
1008
- } )
1009
- .on( 'click', '[data-as3cf-aws-keys-action]', function( event ) {
1010
- event.preventDefault();
1011
- var action = $( this ).data( 'as3cfAwsKeysAction' );
1012
- var api = new AccessKeys();
1013
-
1014
- if ( 'function' === typeof api[action] ) {
1015
- api[action]();
1016
- }
1017
- } )
1018
- ;
1019
  } );
1020
 
1021
- })( jQuery, as3cfModal );
1
+ ( function( $, as3cfModal ) {
2
 
3
  var savedSettings = {};
4
  var bucketNamePattern = /[^a-z0-9.-]/;
60
  * Toggle settings tab
61
  *
62
  * @param string hash
63
+ * @param boolean persist_updated_notice
64
  */
65
  toggle: function( hash, persist_updated_notice ) {
66
  hash = as3cf.tabs.sanitizeHash( hash );
151
  /**
152
  * Load bucket list
153
  *
154
+ * @param {boolean} [forceUpdate]
155
  */
156
  loadList: function( forceUpdate ) {
157
  if ( 'undefined' === typeof forceUpdate ) {
158
  forceUpdate = false;
159
  }
160
 
161
+ var $selectBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-bucket-select' );
162
+ var $selectBucketRegion = $selectBucketForm.find( '.bucket-select-region' );
163
+ var $bucketList = $selectBucketForm.find( '.as3cf-bucket-list' );
164
  var selectedBucket = $( '#' + as3cfModal.prefix + '-bucket' ).val();
165
 
166
  if ( false === forceUpdate && $bucketList.find( 'li' ).length > 1 ) {
178
  _nonce: window[ as3cfModal.prefix.replace( /-/g, '_' ) ].nonces.get_buckets
179
  };
180
 
181
+ if ( $selectBucketRegion.val() ) {
182
+ data[ 'region' ] = $selectBucketRegion.val();
183
+ }
184
+
185
  var that = this;
186
 
187
  $.ajax( {
199
  if ( 'undefined' !== typeof data[ 'success' ] ) {
200
  $( '.as3cf-bucket-error' ).hide();
201
 
202
+ if ( 0 === data['buckets'].length ) {
203
+ $bucketList.html( '<li class="loading">' + $bucketList.data( 'nothing-found' ) + '</li>' );
204
+ } else {
205
+ $( data[ 'buckets' ] ).each( function( idx, bucket ) {
206
+ var bucketClass = bucket.Name === selectedBucket ? 'selected' : '';
207
+ $bucketList.append( '<li><a class="' + bucketClass + '" href="#" data-bucket="' + bucket.Name + '"><span class="bucket"><span class="dashicons dashicons-portfolio"></span> ' + bucket.Name + '</span><span class="spinner"></span></span></a></li>' );
208
+ } );
209
 
210
+ that.scrollToSelected();
211
+ }
212
  } else {
213
  that.showError( as3cf.strings.get_buckets_error, data[ 'error' ], 'as3cf-bucket-select' );
214
  }
264
  */
265
  saveManual: function() {
266
  var $manualBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-manual-save-bucket-form' );
267
+ var $manualBucketRegion = $manualBucketForm.find( '.bucket-manual-region' );
268
  var $manualBucketInput = $manualBucketForm.find( '.as3cf-bucket-name' );
269
  var $manualBucketButton = $manualBucketForm.find( 'button[type=submit]' );
270
  var bucketName = $manualBucketInput.val();
286
  _nonce: window[ as3cfModal.prefix.replace( /-/g, '_' ) ].nonces.manual_bucket
287
  };
288
 
289
+ if ( $manualBucketRegion.val() ) {
290
+ data[ 'region' ] = $manualBucketRegion.val();
291
+ }
292
+
293
  var that = this;
294
 
295
  $.ajax( {
305
  $manualBucketButton.text( originalBucketText );
306
  $manualBucketButton.prop( 'disabled', false );
307
  if ( 'undefined' !== typeof data[ 'success' ] ) {
308
+ that.set( bucketName, data[ 'region' ], data['region_name'], data[ 'can_write' ] );
309
  $( '#' + as3cfModal.prefix + '-bucket-select' ).val( 'manual' );
310
  $( '.as3cf-bucket-list a' ).removeClass( 'selected' ).filter( '[data-bucket="' + bucketName + '"]' ).addClass( 'selected' );
311
 
326
  * @param {object} $link
327
  */
328
  saveSelected: function( $link ) {
 
 
329
  if ( this.bucketSelectLock ) {
330
 
331
  // Bail if a bucket has already been clicked
335
  // Lock the bucket selection
336
  this.bucketSelectLock = true;
337
 
338
+ var $selectBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-bucket-select' );
339
+ var $selectBucketRegion = $selectBucketForm.find( '.bucket-select-region' );
340
+ var $bucketList = $selectBucketForm.find( '.as3cf-bucket-list' );
341
+
342
  if ( $link.hasClass( 'selected' ) ) {
343
  $activeTab.addClass( 'as3cf-has-bucket' );
344
  as3cfModal.close();
345
  return;
346
  }
347
 
348
+ var previousBucket = $selectBucketForm.find( '.as3cf-bucket-list a.selected' ).data( 'bucket' );
349
 
350
  $( '.as3cf-bucket-list a' ).removeClass( 'selected' );
351
  $link.addClass( 'selected' );
360
  _nonce: window[ as3cfModal.prefix.replace( /-/g, '_' ) ].nonces.save_bucket
361
  };
362
 
363
+ if ( $selectBucketRegion.val() ) {
364
+ data[ 'region' ] = $selectBucketRegion.val();
365
+ }
366
+
367
  var that = this;
368
 
369
  $.ajax( {
381
  $link.find( '.spinner' ).hide().css( 'visibility', 'hidden' );
382
  $bucketList.removeClass( 'saving' );
383
  if ( 'undefined' !== typeof data[ 'success' ] ) {
384
+ that.set( bucketName, data[ 'region' ], data['region_name'], data[ 'can_write' ] );
385
  $( '#' + as3cfModal.prefix + '-bucket-select' ).val( '' );
386
 
387
  as3cf.showSettingsSavedNotice();
448
  *
449
  * @param {string} bucket
450
  * @param {string} region
451
+ * @param {string} region_name
452
+ * @param {boolean} canWrite
453
  */
454
+ set: function( bucket, region, region_name, canWrite ) {
455
+ var $manualBucket = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-bucket-manual' );
456
+ var $selectBucket = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-bucket-select' );
457
+ var $createBucket = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-bucket-create' );
458
+ var $activeRegion = $( '#' + as3cfModal.prefix + '-active-region' );
459
  var $activeBucket = $( '#' + as3cfModal.prefix + '-active-bucket' );
460
 
461
  if ( 'as3cf' === as3cfModal.prefix && 0 === $activeBucket.text().trim().length ) {
473
  $( '.as3cf-error.fatal' ).hide();
474
 
475
  $activeBucket.text( bucket );
476
+ $manualBucket.find( '.as3cf-bucket-name' ).val( bucket );
477
  $( '#' + as3cfModal.prefix + '-bucket' ).val( bucket );
478
+
479
+ $activeRegion.text( region_name );
480
+ $manualBucket.find( '.bucket-manual-region' ).val( region );
481
+ $selectBucket.find( '.bucket-select-region' ).val( region );
482
+ $createBucket.find( '.bucket-create-region' ).val( region );
483
  $( '#' + as3cfModal.prefix + '-region' ).val( region );
484
+
485
  $( '.updated' ).not( '.as3cf-notice' ).show();
486
 
487
  $activeTab.addClass( 'as3cf-has-bucket' );
510
  create: function() {
511
  var $createBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-create-bucket-form' );
512
  var $createBucketInput = $createBucketForm.find( '.as3cf-bucket-name' );
513
+ var $createBucketRegion = $createBucketForm.find( '.bucket-create-region' );
514
  var $createBucketButton = $createBucketForm.find( 'button[type=submit]' );
515
 
516
  var bucketName = $createBucketInput.val();
526
  _nonce: window[ as3cfModal.prefix.replace( /-/g, '_' ) ].nonces.create_bucket
527
  };
528
 
529
+ if ( $createBucketRegion.val() ) {
530
+ data[ 'region' ] = $createBucketRegion.val();
531
  }
532
 
533
  var that = this;
545
  $createBucketButton.text( origButtonText );
546
  $createBucketButton.prop( 'disabled', false );
547
  if ( 'undefined' !== typeof data[ 'success' ] ) {
548
+ that.set( bucketName, data[ 'region' ], data['region_name'], data[ 'can_write' ] );
549
 
550
  // Tidy up create bucket form
551
  $( '.as3cf-bucket-select-region' ).hide();
572
  *
573
  * @param {string} bucketName
574
  *
575
+ * @return boolean
576
  */
577
  isValidName: function( bucketName ) {
578
  if ( bucketName.length < 3 || bucketName.length > 63 ) {
650
  var prefix = $objectPrefix.val();
651
 
652
  if ( '' !== prefix ) {
653
+ prefix = as3cf.provider_console_url_param + encodeURIComponent( prefix );
654
  }
655
 
656
+ var url = as3cf.provider_console_url + bucket + prefix;
657
 
658
  $( '#' + as3cfModal.prefix + '-view-bucket' ).attr( 'href', url );
659
  }
689
  success: function( data, textStatus, jqXHR ) {
690
  if ( 'undefined' !== typeof data[ 'success' ] ) {
691
  $( '.as3cf-url-preview' ).html( data[ 'url' ] );
692
+ toggleSEOFriendlyURLNotice( data[ 'seo_friendly' ] );
693
  } else {
694
  alert( as3cf.strings.get_url_preview_error + data[ 'error' ] );
695
  }
719
  }
720
  }
721
 
722
+ /*
723
+ * Toggle the seo friendly url notice.
724
+ */
725
+ function toggleSEOFriendlyURLNotice( seo_friendly ) {
726
+ if ( true !== seo_friendly ) {
727
+ $( '#as3cf-seo-friendly-url-notice' ).show();
728
+ } else {
729
+ $( '#as3cf-seo-friendly-url-notice' ).hide();
730
+ }
731
+ }
732
+
733
  /**
734
  * Update the UI with the current active tab set in the URL hash.
735
  */
747
  $( document ).trigger( 'as3cf.tabRendered', [ location.hash.replace( '#', '' ) ] );
748
  }
749
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
750
  $( document ).ready( function() {
751
 
752
  // Tabs
909
  as3cf.buckets.loadList( true );
910
  } );
911
 
912
+ // Bucket list refresh on region change handler
913
+ $body.on( 'change', '.bucket-select-region', function( e ) {
914
+ e.preventDefault();
915
+ as3cf.buckets.loadList( true );
916
+ } );
917
+
918
  // Bucket list click handler
919
  $body.on( 'click', '.as3cf-bucket-list a', function( e ) {
920
  e.preventDefault();
970
  $manualBucketForm.find( 'button[type=submit]' ).prop( 'disabled', false );
971
  }
972
  } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
973
  } );
974
 
975
+ } )( jQuery, as3cfModal );
assets/js/script.min.js CHANGED
@@ -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=k.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("#"+k.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=k.find('input[name="object-prefix"]'),e=d.val();""!==e&&(e=as3cf.aws_bucket_link_param+encodeURIComponent(e));var f=as3cf.aws_bucket_link+c+e;a("#"+b.prefix+"-view-bucket").attr("href",f)}function g(){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):alert(as3cf.strings.get_url_preview_error+b.error)}})}function h(){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 i(){a("#as3cf-remove-local-file").is(":checked")?a("#as3cf-remove-local-notice").show():a("#as3cf-remove-local-notice").hide()}function j(){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 k,l={},m=/[^a-z0-9.-]/,n=!1,o=a("body"),p=a(".as3cf-tab"),q=a(".as3cf-settings");as3cf.tabs={defaultTab:"media",toggle:function(c,d){c=as3cf.tabs.sanitizeHash(c),p.hide(),k=a("#tab-"+c),k.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),k.data("prefix")&&(b.prefix=k.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-list"),e=a("#"+b.prefix+"-bucket").val();if(!1===c&&d.find("li").length>1)return a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected"),void this.scrollToSelected();d.html('<li class="loading">'+d.data("working")+"</li>");var f={action:b.prefix+"-get-buckets",_nonce:window[b.prefix.replace(/-/g,"_")].nonces.get_buckets},g=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:f,error:function(a,b,c){d.html(""),g.showError(as3cf.strings.get_buckets_error,c,"as3cf-bucket-select")},success:function(b,c,f){d.html(""),"undefined"!=typeof b.success?(a(".as3cf-bucket-error").hide(),a(b.buckets).each(function(a,b){var c=b.Name===e?"selected":"";d.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>')}),g.scrollToSelected()):g.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})}},resetModal:function(){var c=a(".as3cf-bucket-container."+b.prefix);!1===k.hasClass("as3cf-has-bucket")||"manual"===a("#"+b.prefix+"-bucket-select").val()?(c.find(".as3cf-bucket-manual").show().siblings().hide(),c.find(".bucket-actions.manual").show().siblings(".bucket-actions").hide()):(c.find(".as3cf-bucket-select").show().siblings().hide(),c.find(".bucket-actions.select").show().siblings(".bucket-actions").hide(),this.loadList(n),n=!1),c.find(".as3cf-bucket-error").hide();var d=a("#"+b.prefix+"-bucket").val();c.find(".as3cf-bucket-manual .as3cf-bucket-name").val(d),this.bucketSelectLock=!1},saveManual:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form"),d=c.find(".as3cf-bucket-name"),e=c.find("button[type=submit]"),f=d.val(),g=e.first().text();if(f===a("#"+b.prefix+"-active-bucket").text())return a(".as3cf-bucket-error").hide(),k.addClass("as3cf-has-bucket"),void b.close();a(".as3cf-bucket-error").hide(),e.text(e.data("working")),e.prop("disabled",!0);var h={action:b.prefix+"-manual-save-bucket",bucket_name:f,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.manual_bucket},i=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:h,error:function(a,b,c){e.text(g),i.showError(as3cf.strings.save_bucket_error,c,"as3cf-bucket-manual")},success:function(c,d,h){e.text(g),e.prop("disabled",!1),"undefined"!=typeof c.success?(i.set(f,c.region,c.can_write),a("#"+b.prefix+"-bucket-select").val("manual"),a(".as3cf-bucket-list a").removeClass("selected").filter('[data-bucket="'+f+'"]').addClass("selected"),n=!0,as3cf.showSettingsSavedNotice()):i.showError(as3cf.strings.save_bucket_error,c.error,"as3cf-bucket-manual")}})},saveSelected:function(c){var d=a(".as3cf-bucket-list");if(!this.bucketSelectLock){if(this.bucketSelectLock=!0,c.hasClass("selected"))return k.addClass("as3cf-has-bucket"),void b.close();var e=a(".as3cf-bucket-list a.selected").data("bucket");a(".as3cf-bucket-list a").removeClass("selected"),c.addClass("selected"),d.addClass("saving"),c.find(".spinner").show().css("visibility","visible");var f=c.data("bucket"),g={action:b.prefix+"-save-bucket",bucket_name:f,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.save_bucket},h=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:g,error:function(b,c,f){d.removeClass("saving"),h.showError(as3cf.strings.save_bucket_error,f,"as3cf-bucket-select"),a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected")},success:function(g,i,j){c.find(".spinner").hide().css("visibility","hidden"),d.removeClass("saving"),"undefined"!=typeof g.success?(h.set(f,g.region,g.can_write),a("#"+b.prefix+"-bucket-select").val(""),as3cf.showSettingsSavedNotice()):(h.showError(as3cf.strings.save_bucket_error,g.error,"as3cf-bucket-select"),a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected"))}})}},disabledButtons:function(){if(0!==a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form").length){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form"),d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");c.find(".as3cf-bucket-name").val().length<3?c.find("button[type=submit]").prop("disabled",!0):c.find("button[type=submit]").prop("disabled",!1),d.find(".as3cf-bucket-name").val().length<3?d.find("button[type=submit]").prop("disabled",!0):d.find("button[type=submit]").prop("disabled",!1)}},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+" &mdash;"),f.find("span.message").html(c),f.show(),this.bucketSelectLock=!1)},set:function(e,h,i){var j=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form"),m=a("#"+b.prefix+"-active-bucket");if("as3cf"===b.prefix&&0===m.text().trim().length){d("as3cf-copy-to-s3-wrap"),d("as3cf-serve-from-s3-wrap");var n=k.attr("id");l[n]=c(n)}a(".as3cf-error.fatal").hide(),m.text(e),j.find(".as3cf-bucket-name").val(e),a("#"+b.prefix+"-bucket").val(e),a("#"+b.prefix+"-region").val(h),a(".updated").not(".as3cf-notice").show(),k.addClass("as3cf-has-bucket"),k.find(".as3cf-can-write-error").toggle(!i),k.find(".as3cf-bucket-error").hide(),"as3cf"===b.prefix&&g(),f(),b.close(function(){k.trigger("bucket-change",[i]),as3cf.buckets.bucketSelectLock=!1})},create:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form"),d=c.find(".as3cf-bucket-name"),e=c.find(".bucket-create-region"),f=c.find("button[type=submit]"),g=d.val(),h=f.text();a(".as3cf-bucket-error").hide(),f.text(f.data("working")),f.prop("disabled",!0);var i={action:b.prefix+"-create-bucket",bucket_name:g,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.create_bucket};e.val()&&(i.region=e.val());var j=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:i,error:function(a,b,c){f.text(h),j.showError(as3cf.strings.create_bucket_error,c,"as3cf-bucket-create")},success:function(b,c,e){f.text(h),f.prop("disabled",!1),"undefined"!=typeof b.success?(j.set(g,b.region,b.can_write),a(".as3cf-bucket-select-region").hide(),a(".as3cf-bucket-select-region").prop("selected",!1),d.val(""),f.prop("disabled",!0),n=!0,as3cf.showSettingsSavedNotice()):j.showError(as3cf.strings.create_bucket_error,b.error,"as3cf-bucket-create")}})},isValidName:function(a){return!(a.length<3||a.length>63)&&!0!==m.test(a)},updateNameNotice:function(b){var c=null;!0===m.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")}};var r=function(){this.$key=q.find('input[name="aws-access-key-id"]'),this.$secret=q.find('input[name="aws-secret-access-key"]'),this.$spinner=q.find("[data-as3cf-aws-keys-spinner]"),this.$feedback=q.find("[data-as3cf-aws-keys-feedback]")};r.prototype.set=function(){this.sendRequest("set",{"aws-access-key-id":this.$key.val(),"aws-secret-access-key":this.$secret.val()}).done(function(a){a.success&&this.$secret.val(as3cf.strings.not_shown_placeholder)}.bind(this))},r.prototype.remove=function(){this.sendRequest("remove").done(function(a){a.success&&(this.$key.val(""),this.$secret.val(""))}.bind(this))},r.prototype.sendRequest=function(b,c){var d={action:"as3cf-aws-keys-"+b,_ajax_nonce:as3cf.nonces["aws_keys_"+b]};return _.isObject(c)&&(d=_.extend(d,c)),this.$spinner.addClass("is-active"),a.post(ajaxurl,d).done(function(a){this.$feedback.toggleClass("notice-success",a.success).toggleClass("notice-error",!a.success),a.data&&a.data.message&&this.$feedback.html("<p>"+a.data.message+"</p>").show(),a.success&&as3cf.reloadUpdated()}.bind(this)).always(function(){this.$spinner.removeClass("is-active")}.bind(this))},a(document).ready(function(){j(),window.onhashchange=function(a){"function"==typeof history.replaceState&&"#"===location.href.slice(-1)&&history.replaceState({},"",location.href.slice(0,-1)),j()};var m=a(".as3cf-main .nav-tab-wrapper");a(".as3cf-compatibility-notice, div.updated, div.error, div.notice").not(".below-h2, .inline").insertAfter(m),p.length&&p.each(function(a,b){l[b.id]=c(b.id)}),a(window).on("beforeunload.as3cf-settings",function(){if(!a.isEmptyObject(l)){var b=k.attr("id");return c(b)!==l[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){g()}),h(),a("#as3cf-serve-from-s3,#as3cf-remove-local-file").on("change",function(a){h()}),i(),a("#as3cf-remove-local-file").on("change",function(a){i()}),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("#"+k.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"),o.on("click",".bucket-action-manual",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual").show().siblings().hide()}),o.on("click",".bucket-action-browse",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select").show().siblings().hide(),as3cf.buckets.loadList(n),n=!1}),o.on("click",".bucket-action-create",function(c){c.preventDefault(),a(".as3cf-bucket-name").val(""),a(".as3cf-invalid-bucket-name").html(""),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create").show().siblings().hide()}),o.on("click",".bucket-action-cancel",function(a){a.preventDefault(),as3cf.buckets.resetModal()}),o.on("click",".bucket-action-save",function(a){a.preventDefault(),as3cf.buckets.saveManual()}),o.on("click",'.as3cf-create-bucket-form button[type="submit"]',function(a){a.preventDefault(),as3cf.buckets.create()}),o.on("click",".bucket-action-refresh",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),o.on("click",".as3cf-bucket-list a",function(b){b.preventDefault(),as3cf.buckets.saveSelected(a(this))}),a(".as3cf-bucket-container").on("click","a.js-link",function(b){return b.preventDefault(),window.open(a(this).attr("href")),!1}),o.on("as3cf-modal-open",function(c,d){if(".as3cf-bucket-container."+b.prefix===d){as3cf.buckets.resetModal();var e=a(".as3cf-bucket-manual h3").data("modal-title");a(".as3cf-bucket-manual h3").text(e),as3cf.buckets.disabledButtons()}}),as3cf.buckets.disabledButtons(),o.on("input keyup",".as3cf-create-bucket-form .as3cf-bucket-name",function(c){var d=a(this).val(),e=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form");as3cf.buckets.isValidName(d)?e.find("button[type=submit]").prop("disabled",!1):e.find("button[type=submit]").prop("disabled",!0),as3cf.buckets.updateNameNotice(d)}),o.on("input keyup",".as3cf-manual-save-bucket-form .as3cf-bucket-name",function(c){var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");d.find(".as3cf-bucket-name").val().length<as3cf.buckets.validLength?d.find("button[type=submit]").prop("disabled",!0):d.find("button[type=submit]").prop("disabled",!1)}),q.on("click","[data-as3cf-toggle-access-keys-form]",function(b){b.preventDefault(),a("#as3cf_access_keys").toggle()}).on("click","[data-as3cf-aws-keys-action]",function(b){b.preventDefault();var c=a(this).data("as3cfAwsKeysAction"),d=new r;"function"==typeof d[c]&&d[c]()})})}(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=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_param+encodeURIComponent(e));var f=as3cf.provider_console_url+c+e;a("#"+b.prefix+"-view-bucket").attr("href",f)}function g(){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),j(b.seo_friendly)):alert(as3cf.strings.get_url_preview_error+b.error)}})}function h(){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 i(){a("#as3cf-remove-local-file").is(":checked")?a("#as3cf-remove-local-notice").show():a("#as3cf-remove-local-notice").hide()}function j(b){!0!==b?a("#as3cf-seo-friendly-url-notice").show():a("#as3cf-seo-friendly-url-notice").hide()}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=!1,p=a("body"),q=a(".as3cf-tab");a(".as3cf-settings");as3cf.tabs={defaultTab:"media",toggle:function(c,d){c=as3cf.tabs.sanitizeHash(c),q.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>");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.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})}},resetModal:function(){var c=a(".as3cf-bucket-container."+b.prefix);!1===l.hasClass("as3cf-has-bucket")||"manual"===a("#"+b.prefix+"-bucket-select").val()?(c.find(".as3cf-bucket-manual").show().siblings().hide(),c.find(".bucket-actions.manual").show().siblings(".bucket-actions").hide()):(c.find(".as3cf-bucket-select").show().siblings().hide(),c.find(".bucket-actions.select").show().siblings(".bucket-actions").hide(),this.loadList(o),o=!1),c.find(".as3cf-bucket-error").hide();var d=a("#"+b.prefix+"-bucket").val();c.find(".as3cf-bucket-manual .as3cf-bucket-name").val(d),this.bucketSelectLock=!1},saveManual:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form"),d=c.find(".bucket-manual-region"),e=c.find(".as3cf-bucket-name"),f=c.find("button[type=submit]"),g=e.val(),h=f.first().text();if(g===a("#"+b.prefix+"-active-bucket").text())return a(".as3cf-bucket-error").hide(),l.addClass("as3cf-has-bucket"),void b.close();a(".as3cf-bucket-error").hide(),f.text(f.data("working")),f.prop("disabled",!0);var i={action:b.prefix+"-manual-save-bucket",bucket_name:g,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.manual_bucket};d.val()&&(i.region=d.val());var j=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:i,error:function(a,b,c){f.text(h),j.showError(as3cf.strings.save_bucket_error,c,"as3cf-bucket-manual")},success:function(c,d,e){f.text(h),f.prop("disabled",!1),"undefined"!=typeof c.success?(j.set(g,c.region,c.region_name,c.can_write),a("#"+b.prefix+"-bucket-select").val("manual"),a(".as3cf-bucket-list a").removeClass("selected").filter('[data-bucket="'+g+'"]').addClass("selected"),o=!0,as3cf.showSettingsSavedNotice()):j.showError(as3cf.strings.save_bucket_error,c.error,"as3cf-bucket-manual")}})},saveSelected:function(c){if(!this.bucketSelectLock){this.bucketSelectLock=!0;var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select"),e=d.find(".bucket-select-region"),f=d.find(".as3cf-bucket-list");if(c.hasClass("selected"))return l.addClass("as3cf-has-bucket"),void b.close();var g=d.find(".as3cf-bucket-list a.selected").data("bucket");a(".as3cf-bucket-list a").removeClass("selected"),c.addClass("selected"),f.addClass("saving"),c.find(".spinner").show().css("visibility","visible");var h=c.data("bucket"),i={action:b.prefix+"-save-bucket",bucket_name:h,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.save_bucket};e.val()&&(i.region=e.val());var j=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:i,error:function(b,c,d){f.removeClass("saving"),j.showError(as3cf.strings.save_bucket_error,d,"as3cf-bucket-select"),a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+g+'"]').addClass("selected")},success:function(d,e,i){c.find(".spinner").hide().css("visibility","hidden"),f.removeClass("saving"),"undefined"!=typeof d.success?(j.set(h,d.region,d.region_name,d.can_write),a("#"+b.prefix+"-bucket-select").val(""),as3cf.showSettingsSavedNotice()):(j.showError(as3cf.strings.save_bucket_error,d.error,"as3cf-bucket-select"),a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+g+'"]').addClass("selected"))}})}},disabledButtons:function(){if(0!==a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form").length){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form"),d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");c.find(".as3cf-bucket-name").val().length<3?c.find("button[type=submit]").prop("disabled",!0):c.find("button[type=submit]").prop("disabled",!1),d.find(".as3cf-bucket-name").val().length<3?d.find("button[type=submit]").prop("disabled",!0):d.find("button[type=submit]").prop("disabled",!1)}},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+" &mdash;"),f.find("span.message").html(c),f.show(),this.bucketSelectLock=!1)},set:function(e,h,i,j){var k=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual"),n=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select"),o=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create"),p=a("#"+b.prefix+"-active-region"),q=a("#"+b.prefix+"-active-bucket");if("as3cf"===b.prefix&&0===q.text().trim().length){d("as3cf-copy-to-s3-wrap"),d("as3cf-serve-from-s3-wrap");var r=l.attr("id");m[r]=c(r)}a(".as3cf-error.fatal").hide(),q.text(e),k.find(".as3cf-bucket-name").val(e),a("#"+b.prefix+"-bucket").val(e),p.text(i),k.find(".bucket-manual-region").val(h),n.find(".bucket-select-region").val(h),o.find(".bucket-create-region").val(h),a("#"+b.prefix+"-region").val(h),a(".updated").not(".as3cf-notice").show(),l.addClass("as3cf-has-bucket"),l.find(".as3cf-can-write-error").toggle(!j),l.find(".as3cf-bucket-error").hide(),"as3cf"===b.prefix&&g(),f(),b.close(function(){l.trigger("bucket-change",[j]),as3cf.buckets.bucketSelectLock=!1})},create:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form"),d=c.find(".as3cf-bucket-name"),e=c.find(".bucket-create-region"),f=c.find("button[type=submit]"),g=d.val(),h=f.text();a(".as3cf-bucket-error").hide(),f.text(f.data("working")),f.prop("disabled",!0);var i={action:b.prefix+"-create-bucket",bucket_name:g,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.create_bucket};e.val()&&(i.region=e.val());var j=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:i,error:function(a,b,c){f.text(h),j.showError(as3cf.strings.create_bucket_error,c,"as3cf-bucket-create")},success:function(b,c,e){f.text(h),f.prop("disabled",!1),"undefined"!=typeof b.success?(j.set(g,b.region,b.region_name,b.can_write),a(".as3cf-bucket-select-region").hide(),a(".as3cf-bucket-select-region").prop("selected",!1),d.val(""),f.prop("disabled",!0),o=!0,as3cf.showSettingsSavedNotice()):j.showError(as3cf.strings.create_bucket_error,b.error,"as3cf-bucket-create")}})},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 j=a(".as3cf-main .nav-tab-wrapper");a(".as3cf-compatibility-notice, div.updated, div.error, div.notice").not(".below-h2, .inline").insertAfter(j),q.length&&q.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"))}),q.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){g()}),h(),a("#as3cf-serve-from-s3,#as3cf-remove-local-file").on("change",function(a){h()}),i(),a("#as3cf-remove-local-file").on("change",function(a){i()}),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"),p.on("click",".bucket-action-manual",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual").show().siblings().hide()}),p.on("click",".bucket-action-browse",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select").show().siblings().hide(),as3cf.buckets.loadList(o),o=!1}),p.on("click",".bucket-action-create",function(c){c.preventDefault(),a(".as3cf-bucket-name").val(""),a(".as3cf-invalid-bucket-name").html(""),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create").show().siblings().hide()}),p.on("click",".bucket-action-cancel",function(a){a.preventDefault(),as3cf.buckets.resetModal()}),p.on("click",".bucket-action-save",function(a){a.preventDefault(),as3cf.buckets.saveManual()}),p.on("click",'.as3cf-create-bucket-form button[type="submit"]',function(a){a.preventDefault(),as3cf.buckets.create()}),p.on("click",".bucket-action-refresh",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),p.on("change",".bucket-select-region",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),p.on("click",".as3cf-bucket-list a",function(b){b.preventDefault(),as3cf.buckets.saveSelected(a(this))}),a(".as3cf-bucket-container").on("click","a.js-link",function(b){return b.preventDefault(),window.open(a(this).attr("href")),!1}),p.on("as3cf-modal-open",function(c,d){if(".as3cf-bucket-container."+b.prefix===d){as3cf.buckets.resetModal();var e=a(".as3cf-bucket-manual h3").data("modal-title");a(".as3cf-bucket-manual h3").text(e),as3cf.buckets.disabledButtons()}}),as3cf.buckets.disabledButtons(),p.on("input keyup",".as3cf-create-bucket-form .as3cf-bucket-name",function(c){var d=a(this).val(),e=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form");as3cf.buckets.isValidName(d)?e.find("button[type=submit]").prop("disabled",!1):e.find("button[type=submit]").prop("disabled",!0),as3cf.buckets.updateNameNotice(d)}),p.on("input keyup",".as3cf-manual-save-bucket-form .as3cf-bucket-name",function(c){var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");d.find(".as3cf-bucket-name").val().length<as3cf.buckets.validLength?d.find("button[type=submit]").prop("disabled",!0):d.find("button[type=submit]").prop("disabled",!1)})})}(jQuery,as3cfModal);
assets/js/storage-provider.js ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ( function( $ ) {
2
+ var $body = $( 'body' );
3
+
4
+ var as3cf = as3cf || {};
5
+
6
+ /**
7
+ * Handle changes to the selected Storage Provider and Access Key saving.
8
+ */
9
+ as3cf.storageProvider = {
10
+ changed: function() {
11
+ var provider = $( 'input[name="provider"]:checked' ).val();
12
+
13
+ // Hide and disable all providers.
14
+ $( '.as3cf-provider-content' ).each( function() {
15
+ as3cf.storageProvider.disableContent( this );
16
+ } );
17
+
18
+ // Show and enable selected provider.
19
+ $( '.as3cf-provider-content[data-provider="' + provider + '"]' ).each( function() {
20
+ as3cf.storageProvider.enableContent( this );
21
+ } );
22
+ },
23
+
24
+ disableContent: function( element ) {
25
+ $( element ).hide();
26
+ $( element ).removeClass( 'as3cf-provider-selected' );
27
+ $( element ).find( 'input' ).prop( 'disabled', true );
28
+ },
29
+
30
+ enableContent: function( element ) {
31
+ $( element ).find( 'input:not( [data-as3cf-disabled="true"] )' ).prop( 'disabled', false );
32
+ $( element ).addClass( 'as3cf-provider-selected' );
33
+ $( element ).show( 'fast', function() {
34
+ as3cf.storageProvider.setSelectedAuthMethod( this );
35
+ } );
36
+ },
37
+
38
+ setSelectedAuthMethod: function( element ) {
39
+ $( element ).find( 'input[name="authmethod"]:checked' ).prop( 'checked', true ).change();
40
+
41
+ // If exactly one auth method isn't selected, select the first.
42
+ var checkedCount = $( element ).find( 'input[name="authmethod"]:checked' ).length;
43
+
44
+ if ( 1 !== checkedCount ) {
45
+ $( element ).find( 'input[name="authmethod"]' ).first().prop( 'checked', true ).change();
46
+ }
47
+ },
48
+
49
+ authMethodChanged: function() {
50
+ var authMethod = $( 'input[name="authmethod"]:checked' ).val();
51
+
52
+ // Hide all auth methods.
53
+ $( '.asc3f-provider-authmethod-content' ).each( function() {
54
+ as3cf.storageProvider.disableAuthMethodContent( this );
55
+ } );
56
+
57
+ // Show selected auth method.
58
+ $( '.asc3f-provider-authmethod-content[data-provider-authmethod="' + authMethod + '"]' ).each( function() {
59
+ as3cf.storageProvider.enableAuthMethodContent( this );
60
+ } );
61
+ },
62
+
63
+ disableAuthMethodContent: function( element ) {
64
+ $( element ).hide();
65
+ },
66
+
67
+ enableAuthMethodContent: function( element ) {
68
+ $( element ).show();
69
+ }
70
+ };
71
+
72
+ $( document ).ready( function() {
73
+ // Switch displayed storage provider content.
74
+ $body.on( 'change', 'input[name="provider"]', function( e ) {
75
+ e.preventDefault();
76
+ as3cf.storageProvider.changed();
77
+ } );
78
+ // Switch displayed storage provider auth method content.
79
+ $body.on( 'change', 'input[name="authmethod"]', function( e ) {
80
+ e.preventDefault();
81
+ as3cf.storageProvider.authMethodChanged();
82
+ } );
83
+ } );
84
+
85
+ } )( jQuery );
assets/js/storage-provider.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(a){var b=a("body"),c=c||{};c.storageProvider={changed:function(){var b=a('input[name="provider"]:checked').val();a(".as3cf-provider-content").each(function(){c.storageProvider.disableContent(this)}),a('.as3cf-provider-content[data-provider="'+b+'"]').each(function(){c.storageProvider.enableContent(this)})},disableContent:function(b){a(b).hide(),a(b).removeClass("as3cf-provider-selected"),a(b).find("input").prop("disabled",!0)},enableContent:function(b){a(b).find('input:not( [data-as3cf-disabled="true"] )').prop("disabled",!1),a(b).addClass("as3cf-provider-selected"),a(b).show("fast",function(){c.storageProvider.setSelectedAuthMethod(this)})},setSelectedAuthMethod:function(b){a(b).find('input[name="authmethod"]:checked').prop("checked",!0).change();var c=a(b).find('input[name="authmethod"]:checked').length;1!==c&&a(b).find('input[name="authmethod"]').first().prop("checked",!0).change()},authMethodChanged:function(){var b=a('input[name="authmethod"]:checked').val();a(".asc3f-provider-authmethod-content").each(function(){c.storageProvider.disableAuthMethodContent(this)}),a('.asc3f-provider-authmethod-content[data-provider-authmethod="'+b+'"]').each(function(){c.storageProvider.enableAuthMethodContent(this)})},disableAuthMethodContent:function(b){a(b).hide()},enableAuthMethodContent:function(b){a(b).show()}},a(document).ready(function(){b.on("change",'input[name="provider"]',function(a){a.preventDefault(),c.storageProvider.changed()}),b.on("change",'input[name="authmethod"]',function(a){a.preventDefault(),c.storageProvider.authMethodChanged()})})}(jQuery);
assets/sass/attachment.scss CHANGED
@@ -8,7 +8,7 @@
8
  }
9
  .s3-details {
10
  padding: 6px 0;
11
-
12
  .misc-pub-section {
13
  clear: both;
14
  float: left;
@@ -20,15 +20,19 @@
20
  .s3-key {
21
  float: left;
22
  width: 20%;
 
23
  }
24
  .s3-value {
25
  font-weight: bold;
26
  float: left;
27
  width: 80%;
28
  }
 
 
 
29
  }
30
  .not-copied {
31
- color: #666666;
32
  }
33
  }
34
  .s3-actions {
8
  }
9
  .s3-details {
10
  padding: 6px 0;
11
+
12
  .misc-pub-section {
13
  clear: both;
14
  float: left;
20
  .s3-key {
21
  float: left;
22
  width: 20%;
23
+ white-space: nowrap;
24
  }
25
  .s3-value {
26
  font-weight: bold;
27
  float: left;
28
  width: 80%;
29
  }
30
+ input.error {
31
+ color: #a00;
32
+ }
33
  }
34
  .not-copied {
35
+ color: #666;
36
  }
37
  }
38
  .s3-actions {
assets/sass/notice.scss CHANGED
@@ -11,7 +11,7 @@
11
  /**
12
  * Prevent WP from adding the circular arrow icon to all P tags inside the notice html.
13
  */
14
- .as3cf-license-notice p:not(.as3cf-before):before {
15
  display: none;
16
  }
17
 
11
  /**
12
  * Prevent WP from adding the circular arrow icon to all P tags inside the notice html.
13
  */
14
+ .as3cf-licence-notice p:not(.as3cf-before):before {
15
  display: none;
16
  }
17
 
assets/sass/storage-provider.scss ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ $aws_orange: #f7a80d;
2
+ $do_blue: #0080ff;
3
+
4
+ .as3cf-provider-select {
5
+ h3 {
6
+ font-size: 20px;
7
+ }
8
+
9
+ table {
10
+ border-collapse: collapse;
11
+ }
12
+
13
+ .as3cf-provider-title {
14
+ margin: 0;
15
+ padding: 0;
16
+ background: #f1f1f1;
17
+
18
+ label {
19
+ position: relative;
20
+ display: inline-block;
21
+
22
+ &:hover {
23
+ cursor: pointer;
24
+ }
25
+ }
26
+
27
+ .as3cf-provider-logo {
28
+ color: white;
29
+ padding: 1em;
30
+ }
31
+
32
+ h3 {
33
+ display: inline-block;
34
+ position: absolute;
35
+ top: 50%;
36
+ left: 76px;
37
+ transform: translateY(-50%);
38
+ font-weight: bold;
39
+ text-transform: none;
40
+ padding: 0;
41
+ margin: 0 15px;
42
+ white-space: nowrap;
43
+ }
44
+
45
+ &.as3cf-provider-selected {
46
+ cursor: default;
47
+ }
48
+
49
+ &.as3cf-provider-aws {
50
+ .as3cf-provider-logo {
51
+ background-color: $aws_orange;
52
+ }
53
+ }
54
+
55
+ &.as3cf-provider-do {
56
+ .as3cf-provider-logo {
57
+ background-color: $do_blue;
58
+ }
59
+ }
60
+ }
61
+
62
+ .as3cf-provider-content {
63
+ td {
64
+ padding-bottom: 10px;
65
+ }
66
+
67
+ table {
68
+ background: #e5e5e5;
69
+
70
+ th {
71
+ padding: 10px 0 10px 10px;
72
+ }
73
+
74
+ td {
75
+ padding: 10px;
76
+ }
77
+ }
78
+
79
+ .asc3f-provider-authmethod-title {
80
+ label {
81
+ font-weight: bold;
82
+ }
83
+ }
84
+
85
+ .asc3f-provider-authmethod-content {
86
+ td {
87
+ padding-top: 0;
88
+ }
89
+
90
+ textarea.as3cf-define-snippet.code {
91
+ width: 100%;
92
+ white-space: pre;
93
+ overflow: hidden;
94
+ font-size: 11px;
95
+ padding: 10px;
96
+ margin-top: 10px;
97
+ }
98
+
99
+ table.as3cf-access-keys {
100
+ margin-top: 10px;
101
+
102
+ th {
103
+ padding-left: 0;
104
+ }
105
+
106
+ input {
107
+ width: 100%;
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
assets/sass/styles.scss CHANGED
@@ -1,4 +1,3 @@
1
- $aws_orange: #f7a80d;
2
  $as3cf_assets: #0769ad;
3
 
4
  .as3cf-content,
@@ -107,20 +106,76 @@ $as3cf_assets: #0769ad;
107
  }
108
 
109
  /**
110
- * Bucket select
111
  */
112
  .as3cf-tab {
113
  .as3cf-main-settings {
114
  display: none;
 
 
 
 
 
 
 
 
115
  }
116
 
117
  .as3cf-bucket-container {
118
- display: block;
119
  }
120
 
121
- &.as3cf-has-bucket {
 
 
 
 
122
  .as3cf-main-settings {
123
  display: block;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  }
125
 
126
  .as3cf-bucket-container {
@@ -294,11 +349,16 @@ $as3cf_assets: #0769ad;
294
  &.as3cf-setting-title:first-child td {
295
  padding-top: 20px;
296
  }
 
 
 
 
297
  td {
298
  padding: 15px 0;
299
  &:first-child {
300
  vertical-align: top;
301
  min-width: 120px;
 
302
  }
303
 
304
  .as3cf-notice:last-child {
@@ -311,10 +371,6 @@ $as3cf_assets: #0769ad;
311
  }
312
  }
313
 
314
- tr.as3cf-bucket-setting .as3cf-defined-in-config {
315
- float: none;
316
- }
317
-
318
  h3 {
319
  padding: 0;
320
  margin: 0;
@@ -324,10 +380,10 @@ $as3cf_assets: #0769ad;
324
  }
325
  }
326
 
327
- .as3cf-active-bucket {
328
- font-weight: bold;
329
- margin-right: 10px;
330
  }
 
331
  .as3cf-view-bucket {
332
  color: #444;
333
  text-decoration: none;
@@ -439,26 +495,13 @@ $as3cf_assets: #0769ad;
439
  #tab-media {
440
  display: block;
441
 
442
- .as3cf-main-settings {
443
- display: none;
 
444
  }
445
 
446
  .as3cf-bucket-setting td {
447
- padding-top: 5px;
448
- }
449
-
450
- .as3cf-bucket-container {
451
- display: block;
452
- }
453
-
454
- &.as3cf-has-bucket {
455
- .as3cf-main-settings {
456
- display: block;
457
- }
458
-
459
- .as3cf-bucket-container {
460
- display: none;
461
- }
462
  }
463
  }
464
 
@@ -487,6 +530,15 @@ $as3cf_assets: #0769ad;
487
  }
488
 
489
  .form-table {
 
 
 
 
 
 
 
 
 
490
  td {
491
  padding: 5px 0;
492
 
@@ -571,43 +623,6 @@ $as3cf_assets: #0769ad;
571
  display: block;
572
  }
573
 
574
- #tab-settings {
575
- .as3cf-field-wrap {
576
- display: flex;
577
- align-items: center;
578
-
579
- input {
580
- width: 100%;
581
- }
582
-
583
- button, .as3cf-defined-in-config {
584
- margin-left: 20px;
585
- }
586
-
587
- .as3cf-defined-in-config {
588
- display: none;
589
- margin-bottom: 0;
590
- }
591
-
592
- &.as3cf-defined {
593
- button {
594
- display: none;
595
- }
596
- .as3cf-defined-in-config {
597
- display: inline-block;
598
- }
599
- }
600
-
601
- &.as3cf-saved-field .as3cf-activate-licence {
602
- display: none;
603
- }
604
-
605
- &.as3cf-licence-not-entered .as3cf-remove-licence {
606
- display: none;
607
- }
608
- }
609
- }
610
-
611
  #tab-support {
612
  min-height: 900px;
613
  .as3cf-sidebar {
@@ -765,6 +780,11 @@ $as3cf_assets: #0769ad;
765
  /**
766
  * Misc
767
  */
 
 
 
 
 
768
  .as3cf-banner {
769
  margin-top: 35px;
770
  width: 292px;
@@ -861,12 +881,6 @@ $as3cf_assets: #0769ad;
861
  }
862
  }
863
 
864
- .as3cf-aws-logo {
865
- color: white;
866
- background-color: $aws_orange;
867
- padding: 1em;
868
- }
869
-
870
  .as3cf-settings {
871
  h3 {
872
  font-size: 20px;
 
1
  $as3cf_assets: #0769ad;
2
 
3
  .as3cf-content,
106
  }
107
 
108
  /**
109
+ * Show Storage Provider / Bucket Select / media Settings
110
  */
111
  .as3cf-tab {
112
  .as3cf-main-settings {
113
  display: none;
114
+
115
+ .as3cf-provider-select {
116
+ display: none;
117
+ }
118
+
119
+ .as3cf-media-settings {
120
+ display: none;
121
+ }
122
  }
123
 
124
  .as3cf-bucket-container {
125
+ display: none;
126
  }
127
 
128
+ &.as3cf-needs-access-keys, &.as3cf-has-access-keys.as3cf-change-provider {
129
+ .as3cf-can-write-error {
130
+ display: none;
131
+ }
132
+
133
  .as3cf-main-settings {
134
  display: block;
135
+
136
+ .as3cf-provider-select {
137
+ display: block;
138
+ }
139
+
140
+ .as3cf-media-settings {
141
+ display: none;
142
+ }
143
+ }
144
+
145
+ .as3cf-bucket-container {
146
+ display: none;
147
+ }
148
+ }
149
+
150
+ &.as3cf-has-access-keys.as3cf-needs-bucket:not(.as3cf-change-provider) {
151
+ .as3cf-main-settings {
152
+ display: none;
153
+
154
+ .as3cf-provider-select {
155
+ display: none;
156
+ }
157
+
158
+ .as3cf-media-settings {
159
+ display: none;
160
+ }
161
+ }
162
+
163
+ .as3cf-bucket-container {
164
+ display: block;
165
+ }
166
+ }
167
+
168
+ &.as3cf-has-access-keys.as3cf-has-bucket:not(.as3cf-change-provider) {
169
+ .as3cf-main-settings {
170
+ display: block;
171
+
172
+ .as3cf-provider-select {
173
+ display: none;
174
+ }
175
+
176
+ .as3cf-media-settings {
177
+ display: block;
178
+ }
179
  }
180
 
181
  .as3cf-bucket-container {
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;
361
+ padding-top: 20px;
362
  }
363
 
364
  .as3cf-notice:last-child {
371
  }
372
  }
373
 
 
 
 
 
374
  h3 {
375
  padding: 0;
376
  margin: 0;
380
  }
381
  }
382
 
383
+ .as3cf-active-region {
384
+ font-style: italic;
 
385
  }
386
+
387
  .as3cf-view-bucket {
388
  color: #444;
389
  text-decoration: none;
495
  #tab-media {
496
  display: block;
497
 
498
+ .as3cf-provider-setting td {
499
+ padding-top: 20px;
500
+ padding-bottom: 5px;
501
  }
502
 
503
  .as3cf-bucket-setting td {
504
+ padding: 5px 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  }
506
  }
507
 
530
  }
531
 
532
  .form-table {
533
+ .as3cf-provider-setting {
534
+ h4 {
535
+ font-weight: inherit;
536
+ margin: 0;
537
+ }
538
+ }
539
+ .as3cf-bucket-list {
540
+ margin: 5px 0 0 0;
541
+ }
542
  td {
543
  padding: 5px 0;
544
 
623
  display: block;
624
  }
625
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
626
  #tab-support {
627
  min-height: 900px;
628
  .as3cf-sidebar {
780
  /**
781
  * Misc
782
  */
783
+ .as3cf-active-provider, .as3cf-active-bucket {
784
+ font-weight: bold;
785
+ margin-right: 10px;
786
+ }
787
+
788
  .as3cf-banner {
789
  margin-top: 35px;
790
  width: 292px;
881
  }
882
  }
883
 
 
 
 
 
 
 
884
  .as3cf-settings {
885
  h3 {
886
  font-size: 20px;
classes/amazon-s3-and-cloudfront.php CHANGED
@@ -1,31 +1,33 @@
1
  <?php
2
 
3
- use DeliciousBrains\WP_Offload_S3\Providers\AWS_Provider;
4
- use DeliciousBrains\WP_Offload_S3\Providers\Null_Provider;
5
- use DeliciousBrains\WP_Offload_S3\Providers\Provider;
6
- use DeliciousBrains\WP_Offload_S3\Upgrades\Upgrade_Content_Replace_URLs;
7
- use DeliciousBrains\WP_Offload_S3\Upgrades\Upgrade_EDD_Replace_URLs;
8
- use DeliciousBrains\WP_Offload_S3\Upgrades\Upgrade_File_Sizes;
9
- use DeliciousBrains\WP_Offload_S3\Upgrades\Upgrade_Filter_Post_Excerpt;
10
- use DeliciousBrains\WP_Offload_S3\Upgrades\Upgrade_Meta_WP_Error;
11
- use DeliciousBrains\WP_Offload_S3\Upgrades\Upgrade_Region_Meta;
 
 
12
 
13
  class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
14
 
15
  /**
16
  * @var Provider
17
  */
18
- private $aws;
19
 
20
  /**
21
  * @var Provider
22
  */
23
- private $s3client;
24
 
25
  /**
26
  * @var string
27
  */
28
- private $s3client_region;
29
 
30
  /**
31
  * @var array
@@ -60,7 +62,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
60
  /**
61
  * @var AS3CF_S3_To_Local
62
  */
63
- public $filter_s3;
64
 
65
  /**
66
  * @var AS3CF_Notices
@@ -77,6 +79,16 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
77
  */
78
  protected static $buckets_check = array();
79
 
 
 
 
 
 
 
 
 
 
 
80
  /**
81
  * @var AS3CF_Plugin_Compatibility
82
  */
@@ -85,7 +97,14 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
85
  const DEFAULT_EXPIRES = 900;
86
 
87
  const SETTINGS_KEY = 'tantan_wordpress_s3';
88
- const SETTINGS_CONSTANT = 'WPOS3_SETTINGS';
 
 
 
 
 
 
 
89
 
90
  const LATEST_UPGRADE_ROUTINE = 6;
91
 
@@ -109,12 +128,19 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
109
  * Abstract class constructor
110
  *
111
  * @param string $plugin_file_path
 
 
112
  */
113
  function init( $plugin_file_path ) {
114
- $this->plugin_title = __( 'Offload S3', 'amazon-s3-and-cloudfront' );
115
- $this->plugin_menu_title = __( 'Offload S3', 'amazon-s3-and-cloudfront' );
 
 
 
 
 
116
 
117
- $this->set_aws( new AWS_Provider( $this ) );
118
 
119
  // Bundled SDK may require AWS setup before data migrations.
120
  $this->handle_aws_access_key_migration();
@@ -125,6 +151,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
125
  new Upgrade_Content_Replace_URLs( $this );
126
  new Upgrade_EDD_Replace_URLs( $this );
127
  new Upgrade_Filter_Post_Excerpt( $this );
 
128
 
129
  // Plugin setup
130
  add_action( 'admin_menu', array( $this, 'admin_menu' ) );
@@ -135,12 +162,12 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
135
  add_filter( 'pre_get_space_used', array( $this, 'multisite_get_space_used' ) );
136
  // display a notice when either lite or pro is automatically deactivated
137
  add_action( 'pre_current_active_plugins', array( $this, 'plugin_deactivated_notice' ) );
138
- add_action( 'as3cf_plugin_load', array( $this, 'remove_aws_keys_if_constants_set' ) );
139
 
140
  // Attachment screens/modals
141
  add_action( 'load-upload.php', array( $this, 'load_media_assets' ), 11 );
142
  add_action( 'admin_enqueue_scripts', array( $this, 'load_attachment_assets' ), 11 );
143
- add_action( 'add_meta_boxes', array( $this, 'attachment_s3_meta_box' ) );
144
 
145
  // UI AJAX
146
  add_action( 'wp_ajax_as3cf-get-buckets', array( $this, 'ajax_get_buckets' ) );
@@ -148,10 +175,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
148
  add_action( 'wp_ajax_as3cf-create-bucket', array( $this, 'ajax_create_bucket' ) );
149
  add_action( 'wp_ajax_as3cf-manual-save-bucket', array( $this, 'ajax_save_bucket' ) );
150
  add_action( 'wp_ajax_as3cf-get-url-preview', array( $this, 'ajax_get_url_preview' ) );
151
- add_action( 'wp_ajax_as3cf_get_attachment_s3_details', array( $this, 'ajax_get_attachment_s3_details' ) );
152
  add_action( 'wp_ajax_as3cf-get-diagnostic-info', array( $this, 'ajax_get_diagnostic_info' ) );
153
- add_action( 'wp_ajax_as3cf-aws-keys-set', array( $this, 'ajax_set_aws_keys' ) );
154
- add_action( 'wp_ajax_as3cf-aws-keys-remove', array( $this, 'ajax_remove_aws_keys' ) );
155
 
156
  // Rewriting URLs, doesn't depend on plugin being setup
157
  add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 99, 2 );
@@ -163,7 +188,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
163
  add_filter( 'wp_audio_shortcode', array( $this, 'wp_media_shortcode' ), 100, 5 );
164
  add_filter( 'wp_video_shortcode', array( $this, 'wp_media_shortcode' ), 100, 5 );
165
 
166
- // Communication with S3, plugin needs to be setup
167
  add_filter( 'wp_handle_upload_prefilter', array( $this, 'wp_handle_upload_prefilter' ), 1 );
168
  add_filter( 'wp_handle_sideload_prefilter', array( $this, 'wp_handle_upload_prefilter' ), 1 );
169
  add_filter( 'wp_update_attachment_metadata', array( $this, 'wp_update_attachment_metadata' ), 110, 2 );
@@ -171,11 +196,13 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
171
  add_filter( 'update_attached_file', array( $this, 'update_attached_file' ), 100, 2 );
172
 
173
  // Listen for settings changes
174
- add_action( 'as3cf_constant_' . static::SETTINGS_CONSTANT . '_changed_bucket', array( $this, 'bucket_changed' ) );
 
 
175
 
176
  // Content filtering
177
- $this->filter_local = new AS3CF_Local_To_S3( $this );
178
- $this->filter_s3 = new AS3CF_S3_To_Local( $this );
179
 
180
  // include compatibility code for other plugins
181
  $this->plugin_compat = new AS3CF_Plugin_Compatibility( $this );
@@ -184,22 +211,86 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
184
 
185
  // Register modal scripts and styles
186
  $this->register_modal_assets();
 
 
 
187
  }
188
 
189
  /**
190
  * @return Provider
191
  */
192
- public function get_aws() {
193
- return $this->aws;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  }
195
 
196
  /**
197
- * TODO: Remove once Provider fully set up, this is currently required for unit tests.
198
  *
199
- * @param Provider $aws
 
 
200
  */
201
- public function set_aws( $aws ) {
202
- $this->aws = $aws;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  }
204
 
205
  /**
@@ -271,7 +362,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
271
  // use settings from $_POST when generating URL preview via AJAX
272
  if ( isset( $_POST['action'] ) && 'as3cf-get-url-preview' == sanitize_key( $_POST['action'] ) ) { // input var okay
273
  $this->verify_ajax_request();
274
- $value = 0;
275
  if ( isset( $_POST[ $key ] ) ) { // input var okay
276
  $value = $_POST[ $key ]; // input var okay
277
  if ( is_array( $value ) ) {
@@ -389,8 +480,35 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
389
  return $force_https;
390
  }
391
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
392
  $value = parent::get_setting( $key, $default );
393
 
 
 
 
 
 
394
  // Bucket
395
  if ( false !== ( $bucket = $this->get_setting_bucket( $key, $value ) ) ) {
396
  return $bucket;
@@ -399,6 +517,31 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
399
  return apply_filters( 'as3cf_setting_' . $key, $value );
400
  }
401
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
  /**
403
  * Get the region setting
404
  *
@@ -428,7 +571,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
428
 
429
  // Region of bucket translation
430
  if ( 'region' === $key && isset( $settings['region'] ) ) {
431
- return $this->get_aws()->sanitize_region( $settings['region'] );
432
  }
433
 
434
  return false;
@@ -437,9 +580,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
437
  /**
438
  * Get the bucket and if a constant save to database and clear region
439
  *
440
- * @param string $key
441
- * @param string $value
442
- * @param string $constant
443
  *
444
  * @return string|false
445
  */
@@ -555,30 +698,16 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
555
 
556
  // Remove disallowed characters from custom domain
557
  if ( 'cloudfront' === $key ) {
558
- $value = $this->sanitize_custom_domain( $value );
559
  }
560
 
561
  parent::set_setting( $key, $value );
562
  }
563
 
564
- /**
565
- * Sanitize custom domain
566
- *
567
- * @param string $domain
568
- *
569
- * @return string
570
- */
571
- function sanitize_custom_domain( $domain ) {
572
- $domain = preg_replace( '@^[a-zA-Z]*:\/\/@', '', $domain );
573
- $domain = preg_replace( '@[^a-zA-Z0-9\.\-]@', '', $domain );
574
-
575
- return $domain;
576
- }
577
-
578
  /**
579
  * Disables the save button if all settings have been defined.
580
  *
581
- * @param string $defined_settings
582
  *
583
  * @return string
584
  */
@@ -637,7 +766,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
637
  }
638
 
639
  /**
640
- * Allowed mime types array that can be edited for specific S3 uploading
641
  *
642
  * @return array
643
  */
@@ -712,7 +841,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
712
  }
713
 
714
  /**
715
- * Generate a preview of the URL of files uploaded to S3
716
  *
717
  * @param bool $escape
718
  * @param string $suffix
@@ -720,7 +849,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
720
  * @return string
721
  */
722
  function get_url_preview( $escape = true, $suffix = 'photo.jpg' ) {
723
- $scheme = $this->get_s3_url_scheme();
724
  $bucket = $this->get_setting( 'bucket' );
725
  $path = $this->maybe_update_cloudfront_path( $this->get_file_prefix() );
726
  $region = $this->get_setting( 'region' );
@@ -728,7 +857,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
728
  $region = '';
729
  }
730
 
731
- $domain = $this->get_s3_url_domain( $bucket, $region, null, array(), true );
732
 
733
  $url = $scheme . '://' . $domain . '/' . $path . $suffix;
734
 
@@ -749,8 +878,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
749
  $url = $this->get_url_preview();
750
 
751
  $out = array(
752
- 'success' => '1',
753
- 'url' => $url,
 
754
  );
755
 
756
  $this->end_ajax( $out );
@@ -771,105 +901,49 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
771
  }
772
 
773
  /**
774
- * Set AWS keys via ajax.
775
  */
776
- public function ajax_set_aws_keys() {
777
- check_ajax_referer( 'as3cf-aws-keys-set' );
778
-
779
- $key_id = filter_input( INPUT_POST, 'aws-access-key-id' );
780
- $secret_key = filter_input( INPUT_POST, 'aws-secret-access-key' );
781
- $response = array(
782
- 'message' => __( 'Access keys updated successfully.', 'amazon-s3-and-cloudfront' ),
783
- );
784
-
785
  if ( AWS_Provider::is_any_access_key_constant_defined() ) {
786
- wp_send_json_error( array(
787
- 'message' => __( 'All access key constants must be removed before keys can be set in the database.', 'amazon-s3-and-cloudfront' ),
788
- ) );
789
- }
790
-
791
- if ( $key_id ) {
792
- $this->set_setting( 'aws-access-key-id', $key_id );
793
- } else {
794
- wp_send_json_error( array(
795
- 'message' => __( 'The Access Key ID must be set.', 'amazon-s3-and-cloudfront' ),
796
- ) );
797
- }
798
-
799
- // Only update the secret key if entered and not set to "-- not shown --".
800
- if ( _x( '-- not shown --', 'placeholder for hidden access key, 39 char max', 'amazon-s3-and-cloudfront' ) !== $secret_key || ! $this->get_setting( 'aws-secret-access-key' ) ) {
801
- // AWS Secret Access keys are 40 char long.
802
- if ( ! $secret_key || strlen( $secret_key ) < 40 ) {
803
- wp_send_json_error( array(
804
- 'message' => __( 'The Secret Access Key must be at least 40 characters long.', 'amazon-s3-and-cloudfront' ),
805
- ) );
806
- }
807
-
808
- $this->set_setting( 'aws-secret-access-key', $secret_key );
809
  }
810
-
811
- $this->save_settings();
812
-
813
- wp_send_json_success( $response );
814
  }
815
 
816
  /**
817
- * Remove AWS access keys via ajax.
818
  */
819
- public function ajax_remove_aws_keys() {
820
- check_ajax_referer( 'as3cf-aws-keys-remove' );
821
-
822
- $this->remove_aws_keys();
823
-
824
- wp_send_json_success( array(
825
- 'message' => __( 'Access keys removed from the database successfully.', 'amazon-s3-and-cloudfront' ),
826
- ) );
827
- }
828
-
829
- /**
830
- * Remove AWS access keys from saved settings if a key constant is defined.
831
- */
832
- public function remove_aws_keys_if_constants_set() {
833
- if ( AWS_Provider::is_any_access_key_constant_defined() ) {
834
- $this->remove_aws_keys();
835
- }
836
- }
837
-
838
- /**
839
- * Remove AWS keys from settings.
840
- */
841
- protected function remove_aws_keys() {
842
- $this->remove_setting( 'aws-access-key-id' );
843
- $this->remove_setting( 'aws-secret-access-key' );
844
  $this->save_settings();
845
  }
846
 
847
  /**
848
- * Delete bulk objects from an S3 bucket
849
  *
850
  * @param string $region
851
  * @param string $bucket
852
  * @param array $objects
853
  * @param bool $log_error
854
  * @param bool $return_on_error
855
- * @param bool $force_new_s3_client if we are deleting in bulk, force new S3 client
856
- * to cope with possible different regions
857
  *
858
  * @return bool
859
  */
860
- function delete_s3_objects( $region, $bucket, $objects, $log_error = false, $return_on_error = false, $force_new_s3_client = false ) {
861
  $chunks = array_chunk( $objects, 1000 );
862
 
863
  try {
864
  foreach ( $chunks as $chunk ) {
865
- $this->get_s3client( $region, $force_new_s3_client )->delete_objects( array(
866
  'Bucket' => $bucket,
867
  'Objects' => $chunk,
868
  ) );
869
  }
870
  } catch ( Exception $e ) {
871
  if ( $log_error ) {
872
- AS3CF_Error::log( 'Error removing files from S3: ' . $e->getMessage() );
873
  }
874
 
875
  return false;
@@ -879,22 +953,22 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
879
  }
880
 
881
  /**
882
- * Removes an attachment's files from S3.
883
  *
884
  * @param int $post_id
885
- * @param array $s3object
886
  * @param bool $remove_backup_sizes remove previous edited image versions
887
  * @param bool $log_error
888
  * @param bool $return_on_error
889
- * @param bool $force_new_s3_client if we are deleting in bulk, force new S3 client
890
  * to cope with possible different regions
891
  */
892
- function remove_attachment_files_from_s3( $post_id, $s3object, $remove_backup_sizes = true, $log_error = false, $return_on_error = false, $force_new_s3_client = false ) {
893
- $prefix = $this->normalize_object_prefix( $s3object['key'] );
894
- $bucket = $s3object['bucket'];
895
- $region = $this->get_s3object_region( $s3object );
896
  $paths = AS3CF_Utils::get_attachment_file_paths( $post_id, false, false, $remove_backup_sizes );
897
- $paths = apply_filters( 'as3cf_remove_attachment_paths', $paths, $post_id, $s3object, $remove_backup_sizes );
898
 
899
  if ( is_wp_error( $region ) ) {
900
  $region = '';
@@ -908,79 +982,85 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
908
  );
909
  }
910
 
911
- // finally delete the objects from S3
912
- $this->delete_s3_objects( $region, $bucket, $objects_to_remove, $log_error, $return_on_error, $force_new_s3_client );
913
  }
914
 
915
  /**
916
- * Removes an attachment and intermediate image size files from S3
917
  *
918
  * @param int $post_id
919
- * @param bool $force_new_s3_client if we are deleting in bulk, force new S3 client
920
- * to cope with possible different regions
921
  */
922
- function delete_attachment( $post_id, $force_new_s3_client = false ) {
923
  if ( ! $this->is_plugin_setup( true ) ) {
924
  return;
925
  }
926
 
927
- if ( ! ( $s3object = $this->get_attachment_s3_info( $post_id ) ) ) {
 
 
 
 
928
  return;
929
  }
930
 
931
- $this->remove_attachment_files_from_s3( $post_id, $s3object, true, true, true, $force_new_s3_client );
932
 
933
  delete_post_meta( $post_id, 'amazonS3_info' );
934
  }
935
 
936
  /**
937
- * Handles the upload of the attachment to S3 when an attachment is updated using
938
  * the 'wp_update_attachment_metadata' filter
939
  *
940
  * @param array $data meta data for attachment
941
  * @param int $post_id
942
  *
943
  * @return array
 
944
  */
945
  function wp_update_attachment_metadata( $data, $post_id ) {
946
  if ( ! $this->is_plugin_setup( true ) ) {
947
  return $data;
948
  }
949
 
950
- if ( ! ( $old_s3object = $this->get_attachment_s3_info( $post_id ) ) && ! $this->get_setting( 'copy-to-s3' ) ) {
951
- // abort if not already uploaded to S3 and the copy setting is off
952
  return $data;
953
  }
954
 
955
- // allow S3 upload to be cancelled for any reason
956
- $pre = apply_filters( 'as3cf_pre_update_attachment_metadata', false, $data, $post_id, $old_s3object );
957
  if ( false !== $pre ) {
958
  return $data;
959
  }
960
 
961
- // upload attachment to S3
962
- $s3_meta = $this->upload_attachment_to_s3( $post_id, $data );
963
 
964
- if ( is_wp_error( $s3_meta ) ) {
965
  return $data;
966
  }
967
 
968
- return $s3_meta;
969
  }
970
 
971
  /**
972
- * Upload attachment to S3
973
  *
974
  * @param int $post_id
975
  * @param array|null $data
976
  * @param string|null $file_path
977
- * @param bool $force_new_s3_client if we are uploading in bulk, force new S3 client
978
- * to cope with possible different regions
979
  * @param bool $remove_local_files
980
  *
981
- * @return array|WP_Error $s3object|$meta If meta is supplied, return it. Else return S3 meta
 
982
  */
983
- public function upload_attachment_to_s3( $post_id, $data = null, $file_path = null, $force_new_s3_client = false, $remove_local_files = true ) {
984
  $return_metadata = null;
985
  if ( is_null( $data ) ) {
986
  $data = wp_get_attachment_metadata( $post_id, true );
@@ -993,10 +1073,10 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
993
  return $data;
994
  }
995
 
996
- // Allow S3 upload to be hijacked / cancelled for any reason
997
  try {
998
  $pre = apply_filters( 'as3cf_pre_upload_attachment', false, $post_id, $data );
999
- } catch ( \Exception $e ) {
1000
  return $this->return_upload_error( $e->getMessage() );
1001
  }
1002
 
@@ -1021,27 +1101,33 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1021
  $type = get_post_mime_type( $post_id );
1022
  $allowed_types = $this->get_allowed_mime_types();
1023
 
1024
- // check mime type of file is in allowed S3 mime types
1025
  if ( ! in_array( $type, $allowed_types ) ) {
1026
  $error_msg = sprintf( __( 'Mime type %s is not allowed', 'amazon-s3-and-cloudfront' ), $type );
1027
 
1028
  return $this->return_upload_error( $error_msg, $return_metadata );
1029
  }
1030
 
1031
- $acl = $this->get_aws()->get_default_acl();
 
 
 
 
 
 
 
1032
 
1033
- // check the attachment already exists in S3, eg. edit or restore image
1034
- if ( ( $old_s3object = $this->get_attachment_s3_info( $post_id ) ) ) {
1035
  // use existing non default ACL if attachment already exists
1036
- if ( isset( $old_s3object['acl'] ) ) {
1037
- $acl = $old_s3object['acl'];
1038
  }
 
1039
  // use existing prefix
1040
- $prefix = $this->normalize_object_prefix( $old_s3object['key'] );
1041
  // use existing bucket
1042
- $bucket = $old_s3object['bucket'];
1043
  // get existing region
1044
- $region = isset( $old_s3object['region'] ) ? $old_s3object['region'] : '';
1045
  } else {
1046
  // derive prefix from various settings
1047
  if ( isset( $data['file'] ) ) {
@@ -1082,46 +1168,47 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1082
  $args['ContentEncoding'] = 'gzip';
1083
  }
1084
 
1085
- $image_size = wp_attachment_is_image( $post_id ) ? 'full' : '';
1086
- $args = apply_filters( 'as3cf_object_meta', $args, $post_id, $image_size, false );
1087
- $s3object = array(
1088
- 'region' => $bucket !== $args['Bucket'] ? $this->get_bucket_region( $args['Bucket'], true ) : $region,
1089
- 'bucket' => $args['Bucket'],
1090
- 'key' => $args['Key'],
1091
- 'acl' => $args['ACL'],
 
1092
  );
1093
 
1094
  // Do not store object ACL if set to the default value.
1095
- if ( $s3object['acl'] === $this->get_aws()->get_default_acl() ) {
1096
- unset( $s3object['acl'] );
1097
  }
1098
 
1099
- do_action( 'as3cf_upload_attachment_pre_remove', $post_id, $s3object, $prefix, $args );
1100
 
1101
  $files_to_remove = array();
1102
 
1103
- $s3client = $this->get_s3client( $s3object['region'], $force_new_s3_client );
1104
 
1105
  try {
1106
- $s3client->upload_object( $args );
1107
  $files_to_remove[] = $file_path;
1108
  } catch ( Exception $e ) {
1109
- $error_msg = sprintf( __( 'Error uploading %s to S3: %s', 'amazon-s3-and-cloudfront' ), $file_path, $e->getMessage() );
1110
 
1111
  return $this->return_upload_error( $error_msg, $return_metadata );
1112
  }
1113
 
1114
  delete_post_meta( $post_id, 'amazonS3_info' );
1115
 
1116
- add_post_meta( $post_id, 'amazonS3_info', $s3object );
1117
 
1118
- $file_paths = AS3CF_Utils::get_attachment_file_paths( $post_id, false, $data );
1119
- $additional_images = array();
1120
- $s3object_sizes = array();
1121
 
1122
  foreach ( $file_paths as $size => $file_path ) {
1123
  if ( ! in_array( $file_path, $files_to_remove ) ) {
1124
- $acl = apply_filters( 'as3cf_upload_acl_sizes', $this->get_aws()->get_default_acl(), $size, $post_id, $data );
1125
 
1126
  $additional_images[ $size ] = array(
1127
  'Key' => $prefix . wp_basename( $file_path ),
@@ -1130,8 +1217,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1130
  'ContentType' => $this->get_mime_type( $file_path ),
1131
  );
1132
 
1133
- if ( $this->get_aws()->get_default_acl() !== $acl ) {
1134
- $s3object_sizes[ $size ]['acl'] = $acl;
1135
  }
1136
  }
1137
  }
@@ -1147,10 +1234,10 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1147
  }
1148
 
1149
  try {
1150
- $s3client->upload_object( $args );
1151
  $files_to_remove[] = $image['SourceFile'];
1152
  } catch ( Exception $e ) {
1153
- $upload_errors[] = $this->return_upload_error( sprintf( __( 'Error uploading %s to S3: %s', 'amazon-s3-and-cloudfront' ), $args['SourceFile'], $e->getMessage() ) );
1154
  }
1155
  }
1156
 
@@ -1180,20 +1267,20 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1180
  }
1181
 
1182
  // Make sure we don't have cached file sizes in the meta if we previously added it.
1183
- if ( ! $remove_local_files_setting && isset( $data['filesize'] ) && ! empty( get_post_meta( $post_id, 'wpos3_filesize_total', true ) ) ) {
1184
  $data = $this->maybe_cleanup_filesize_metadata( $post_id, $data, empty( $return_metadata ) );
1185
  }
1186
 
1187
- if ( ! empty( $s3object_sizes ) ) {
1188
  // Additional image sizes have custom ACLs, update meta
1189
- $s3object['sizes'] = $s3object_sizes;
1190
- update_post_meta( $post_id, 'amazonS3_info', $s3object );
1191
  }
1192
 
1193
  // Keep track of attachments uploaded by this instance.
1194
  $this->uploaded_post_ids[] = $post_id;
1195
 
1196
- do_action( 'wpos3_post_upload_attachment', $post_id, $s3object );
1197
 
1198
  if ( $upload_errors ) {
1199
  return $this->consolidate_upload_errors( $upload_errors );
@@ -1204,7 +1291,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1204
  return $data;
1205
  }
1206
 
1207
- return $s3object;
1208
  }
1209
 
1210
  /**
@@ -1320,7 +1407,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1320
 
1321
  // If we were able to sum up file sizes for an attachment, record it.
1322
  if ( $filesize_total > 0 ) {
1323
- update_post_meta( $attachment_id, 'wpos3_filesize_total', $filesize_total );
1324
  }
1325
  }
1326
 
@@ -1440,7 +1527,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1440
  $name = '';
1441
  }
1442
 
1443
- // Rebuild filename with lowercase extension as S3 will have converted extension on upload.
1444
  $ext = strtolower( $ext );
1445
  $filename = $name . $ext;
1446
  $time = current_time( 'mysql' );
@@ -1451,7 +1538,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1451
  }
1452
 
1453
  if ( ! $this->does_file_exist( $filename, $time ) ) {
1454
- // File doesn't exist locally or on S3, return it.
1455
  return $filename;
1456
  }
1457
 
@@ -1494,7 +1581,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1494
  return true;
1495
  }
1496
 
1497
- if ( ! $this->get_setting( 'object-versioning' ) && $this->does_file_exist_s3( $filename, $time ) ) {
1498
  return true;
1499
  }
1500
 
@@ -1531,14 +1618,15 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1531
  }
1532
 
1533
  /**
1534
- * Does file exist s3
1535
  *
1536
  * @param string $filename
1537
  * @param string $time
1538
  *
1539
  * @return bool
 
1540
  */
1541
- function does_file_exist_s3( $filename, $time ) {
1542
  $bucket = $this->get_setting( 'bucket' );
1543
  $region = $this->get_setting( 'region' );
1544
 
@@ -1546,11 +1634,11 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1546
  return false;
1547
  }
1548
 
1549
- $s3client = $this->get_s3client( $region );
1550
- $prefix = AS3CF_Utils::trailingslash_prefix( $this->get_object_prefix() );
1551
- $prefix .= AS3CF_Utils::trailingslash_prefix( $this->get_dynamic_prefix( $time ) );
1552
 
1553
- return $s3client->does_object_exist( $bucket, $prefix . $filename );
1554
  }
1555
 
1556
  /**
@@ -1575,33 +1663,36 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1575
  }
1576
 
1577
  /**
1578
- * Get attachment s3 info
1579
  *
1580
  * @param int $post_id
1581
  *
1582
  * @return mixed
1583
  */
1584
- public function get_attachment_s3_info( $post_id ) {
1585
- $s3_object = get_post_meta( $post_id, 'amazonS3_info', true );
1586
 
1587
- if ( is_array( $s3_object ) ) {
1588
- $s3_object = array_merge( array(
1589
- 'region' => null,
1590
- ), $s3_object );
 
1591
  }
1592
 
1593
- return apply_filters( 'as3cf_get_attachment_s3_info', $s3_object, $post_id );
 
 
1594
  }
1595
 
1596
  /**
1597
  * Check the plugin is correctly setup
1598
  *
1599
- * @param bool $with_credentials Do S3 credentials need to be set up too? Defaults to false.
1600
  *
1601
  * @return bool
1602
  */
1603
  function is_plugin_setup( $with_credentials = false ) {
1604
- if ( $with_credentials && $this->get_aws()->needs_access_keys() ) {
1605
  // AWS not configured
1606
  return false;
1607
  }
@@ -1621,7 +1712,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1621
  }
1622
 
1623
  /**
1624
- * Generate a link to download a file from Amazon S3 using query string
1625
  * authentication. This link is only valid for a limited amount of time.
1626
  *
1627
  * @param int $post_id Post ID of the attachment
@@ -1647,7 +1738,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1647
  *
1648
  * @return string
1649
  */
1650
- function get_s3_url_scheme( $use_ssl = null ) {
1651
  if ( $this->use_ssl( $use_ssl ) ) {
1652
  $scheme = 'https';
1653
  } else {
@@ -1664,7 +1755,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1664
  *
1665
  * @return bool
1666
  */
1667
- function use_ssl( $use_ssl = null ) {
1668
  if ( is_ssl() ) {
1669
  $use_ssl = true;
1670
  }
@@ -1714,79 +1805,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1714
  }
1715
 
1716
  /**
1717
- * Get the region specific prefix for S3 URL
1718
- *
1719
- * @param string $region
1720
- * @param null|int $expires
1721
- *
1722
- * @return string
1723
- */
1724
- function get_s3_url_prefix( $region = '', $expires = null ) {
1725
- $prefix = 's3';
1726
-
1727
- if ( '' !== $region ) {
1728
- $delimiter = '-';
1729
- if ( 'eu-central-1' == $region && ! is_null( $expires ) ) {
1730
- // if we are creating a secure URL for a Frankfurt base file use the alternative delimiter
1731
- // http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
1732
- $delimiter = '.';
1733
- }
1734
-
1735
- $prefix .= $delimiter . $region;
1736
- }
1737
-
1738
- return apply_filters( 'as3cf_s3_url_prefix', $prefix, $region );
1739
- }
1740
-
1741
- /**
1742
- * Get the S3 url for the files
1743
- *
1744
- * @param string $bucket
1745
- * @param string $region
1746
- * @param int $expires
1747
- * @param array $args Allows you to specify custom URL settings
1748
- * @param bool $preview When generating the URL preview sanitize certain output
1749
- *
1750
- * @return string
1751
- */
1752
- function get_s3_url_domain( $bucket, $region = '', $expires = null, $args = array(), $preview = false ) {
1753
- if ( ! isset( $args['cloudfront'] ) ) {
1754
- $args['cloudfront'] = $this->get_setting( 'cloudfront' );
1755
- }
1756
-
1757
- if ( ! isset( $args['domain'] ) ) {
1758
- $args['domain'] = $this->get_setting( 'domain' );
1759
- }
1760
-
1761
- if ( ! isset( $args['force-https'] ) ) {
1762
- $args['force-https'] = $this->get_setting( 'force-https' );
1763
- }
1764
-
1765
- $prefix = $this->get_s3_url_prefix( $region, $expires );
1766
- $s3_domain = apply_filters( 'as3cf_s3_domain', 'amazonaws.com' );
1767
- $s3_domain = empty( $prefix ) ? $s3_domain : $prefix . '.' . $s3_domain;
1768
-
1769
-
1770
- if ( 'cloudfront' === $args['domain'] && is_null( $expires ) && $args['cloudfront'] ) {
1771
- $cloudfront = $args['cloudfront'];
1772
- if ( $preview ) {
1773
- $cloudfront = $this->sanitize_custom_domain( $cloudfront );
1774
- }
1775
-
1776
- $s3_domain = $cloudfront;
1777
- } elseif ( 'virtual-host' === $args['domain'] ) {
1778
- $s3_domain = $bucket;
1779
- } elseif ( 'path' === $args['domain'] || $this->use_ssl( $args['force-https'] ) ) {
1780
- $s3_domain = $s3_domain . '/' . $bucket;
1781
- } else {
1782
- $s3_domain = $bucket . '.' . $s3_domain;
1783
- }
1784
-
1785
- return $s3_domain;
1786
- }
1787
-
1788
- /**
1789
- * Get the url of the file from Amazon S3
1790
  *
1791
  * @param int $post_id Post ID of the attachment
1792
  * @param int|null $expires Seconds for the link to live
@@ -1797,14 +1816,14 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1797
  * Useful for the EDD and Woo addons to not break download URLs when the
1798
  * option is disabled.
1799
  *
1800
- * @return bool|mixed|void|WP_Error
1801
  */
1802
  public function get_attachment_url( $post_id, $expires = null, $size = null, $meta = null, $headers = array(), $skip_rewrite_check = false ) {
1803
- if ( ! ( $s3object = $this->is_attachment_served_by_s3( $post_id, $skip_rewrite_check ) ) ) {
1804
  return false;
1805
  }
1806
 
1807
- $url = $this->get_attachment_s3_url( $post_id, $s3object, $expires, $size, $meta, $headers );
1808
 
1809
  return apply_filters( 'as3cf_wp_get_attachment_url', $url, $post_id );
1810
  }
@@ -1875,10 +1894,10 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1875
  }
1876
 
1877
  /**
1878
- * Get the S3 URL for an attachment
1879
  *
1880
  * @param int $post_id
1881
- * @param array $s3object
1882
  * @param null|int $expires
1883
  * @param null|string|array $size
1884
  * @param null|array $meta
@@ -1886,13 +1905,13 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1886
  *
1887
  * @return mixed|WP_Error
1888
  */
1889
- public function get_attachment_s3_url( $post_id, $s3object, $expires = null, $size = null, $meta = null, $headers = array() ) {
1890
- $scheme = $this->get_s3_url_scheme();
1891
 
1892
- // We don't use $this->get_s3object_region() here because we don't want
1893
  // to make an AWS API call and slow down page loading
1894
- if ( isset( $s3object['region'] ) && $this->get_aws()->get_default_region() !== $s3object['region'] ) {
1895
- $region = $this->get_aws()->sanitize_region( $s3object['region'] );
1896
  } else {
1897
  $region = '';
1898
  }
@@ -1901,12 +1920,12 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1901
 
1902
  // Force use of secured URL when ACL has been set to private
1903
  if ( is_null( $expires ) ) {
1904
- if ( is_null( $size ) && isset( $s3object['acl'] ) && $this->get_aws()->get_private_acl() === $s3object['acl'] ) {
1905
  // Full size URL private
1906
  $expires = self::DEFAULT_EXPIRES;
1907
  }
1908
 
1909
- if ( ! is_null( $size ) && isset( $s3object['sizes'][ $size ]['acl'] ) && $this->get_aws()->get_private_acl() === $s3object['sizes'][ $size ]['acl'] ) {
1910
  // Alternative size URL private
1911
  $expires = self::DEFAULT_EXPIRES;
1912
  }
@@ -1922,32 +1941,32 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1922
  }
1923
 
1924
  if ( ! empty( $meta ) && isset( $meta['sizes'][ $size ]['file'] ) ) {
1925
- $size_prefix = dirname( $s3object['key'] );
1926
  $size_file_prefix = ( '.' === $size_prefix ) ? '' : $size_prefix . '/';
1927
 
1928
- $s3object['key'] = $size_file_prefix . $meta['sizes'][ $size ]['file'];
1929
  }
1930
  }
1931
 
1932
  if ( ! is_null( $expires ) && $this->is_plugin_setup( true ) ) {
1933
  try {
1934
  $expires = time() + apply_filters( 'as3cf_expires', $expires );
1935
- $secure_url = $this->get_s3client( $region )
1936
- ->get_object_url( $s3object['bucket'], $s3object['key'], $expires, $headers );
1937
 
1938
- return apply_filters( 'as3cf_get_attachment_secure_url', $secure_url, $s3object, $post_id, $expires, $headers );
1939
  } catch ( Exception $e ) {
1940
  return new WP_Error( 'exception', $e->getMessage() );
1941
  }
1942
  }
1943
 
1944
- $s3object['key'] = $this->maybe_update_cloudfront_path( $s3object['key'] );
1945
 
1946
- $domain_bucket = $this->get_s3_url_domain( $s3object['bucket'], $region, $expires );
1947
- $file = $this->encode_filename_in_path( $s3object['key'] );
1948
  $url = $scheme . '://' . $domain_bucket . '/' . $file;
1949
 
1950
- return apply_filters( 'as3cf_get_attachment_url', $url, $s3object, $post_id, $expires, $headers );
1951
  }
1952
 
1953
  /**
@@ -1956,7 +1975,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1956
  * @param string $url
1957
  * @param int $post_id
1958
  *
1959
- * @return bool|mixed|void|WP_Error
1960
  */
1961
  public function wp_get_attachment_url( $url, $post_id ) {
1962
  $new_url = $this->get_attachment_url( $post_id );
@@ -1984,8 +2003,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
1984
  * @return string
1985
  */
1986
  public function maybe_encode_get_image_tag( $html, $id, $alt, $title, $align, $size ) {
1987
- if ( ! ( $s3object = $this->is_attachment_served_by_s3( $id ) ) ) {
1988
- // Not served by S3, return
1989
  return $html;
1990
  }
1991
 
@@ -2001,7 +2020,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2001
  }
2002
 
2003
  $img_src = $matches[1];
2004
- $new_img_src = $this->maybe_sign_intermediate_size( $img_src, $id, $size, $s3object );
2005
  $new_img_src = $this->encode_filename_in_path( $new_img_src );
2006
 
2007
  return str_replace( $img_src, $new_img_src, $html );
@@ -2018,13 +2037,13 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2018
  * @return array
2019
  */
2020
  public function maybe_encode_wp_get_attachment_image_src( $image, $attachment_id, $size, $icon ) {
2021
- if ( ! ( $s3object = $this->is_attachment_served_by_s3( $attachment_id ) ) ) {
2022
- // Not served by S3, return
2023
  return $image;
2024
  }
2025
 
2026
  if ( isset( $image[0] ) ) {
2027
- $url = $this->maybe_sign_intermediate_size( $image[0], $attachment_id, $size, $s3object );
2028
  $url = $this->encode_filename_in_path( $url );
2029
 
2030
  $image[0] = $url;
@@ -2043,8 +2062,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2043
  * @return array
2044
  */
2045
  public function maybe_encode_wp_prepare_attachment_for_js( $response, $attachment, $meta ) {
2046
- if ( ! ( $s3object = $this->is_attachment_served_by_s3( $attachment->ID ) ) ) {
2047
- // Not served by S3, return
2048
  return $response;
2049
  }
2050
 
@@ -2054,7 +2073,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2054
 
2055
  if ( isset( $response['sizes'] ) && is_array( $response['sizes'] ) ) {
2056
  foreach ( $response['sizes'] as $size => $value ) {
2057
- $url = $this->maybe_sign_intermediate_size( $value['url'], $attachment->ID, $size, $s3object );
2058
  $url = $this->encode_filename_in_path( $url );
2059
 
2060
  $response['sizes'][ $size ]['url'] = $url;
@@ -2074,13 +2093,13 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2074
  * @return array
2075
  */
2076
  public function maybe_encode_image_get_intermediate_size( $data, $post_id, $size ) {
2077
- if ( ! ( $s3object = $this->is_attachment_served_by_s3( $post_id ) ) ) {
2078
- // Not served by S3, return
2079
  return $data;
2080
  }
2081
 
2082
  if ( isset( $data['url'] ) ) {
2083
- $url = $this->maybe_sign_intermediate_size( $data['url'], $post_id, $size, $s3object );
2084
  $url = $this->encode_filename_in_path( $url );
2085
 
2086
  $data['url'] = $url;
@@ -2095,20 +2114,20 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2095
  * @param string $url
2096
  * @param int $attachment_id
2097
  * @param string|array $size
2098
- * @param bool|array $s3object
2099
  *
2100
  * @return mixed|WP_Error
2101
  */
2102
- protected function maybe_sign_intermediate_size( $url, $attachment_id, $size, $s3object = false ) {
2103
- if ( ! $s3object ) {
2104
- $s3object = $this->get_attachment_s3_info( $attachment_id );
2105
  }
2106
 
2107
  $size = $this->maybe_convert_size_to_string( $attachment_id, $size );
2108
 
2109
- if ( isset( $s3object['sizes'][ $size ] ) ) {
2110
  // Private file, add AWS signature if required
2111
- return $this->get_attachment_s3_url( $attachment_id, $s3object, null, $size );
2112
  }
2113
 
2114
  return $url;
@@ -2179,25 +2198,36 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2179
  }
2180
 
2181
  /**
2182
- * Is attachment served by S3.
2183
  *
2184
- * @param int $attachment_id
2185
- * @param bool $skip_rewrite_check
 
 
2186
  *
2187
  * @return bool|array
2188
  */
2189
- public function is_attachment_served_by_s3( $attachment_id, $skip_rewrite_check = false ) {
2190
  if ( ! $skip_rewrite_check && ! $this->get_setting( 'serve-from-s3' ) ) {
2191
- // Not serving S3 URLs
 
 
 
 
 
2192
  return false;
2193
  }
2194
 
2195
- if ( ! ( $s3object = $this->get_attachment_s3_info( $attachment_id ) ) ) {
2196
- // File not uploaded to S3
 
 
 
 
2197
  return false;
2198
  }
2199
 
2200
- return $s3object;
2201
  }
2202
 
2203
  /**
@@ -2266,7 +2296,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2266
  }
2267
 
2268
  /**
2269
- * Allow processes to update the file on S3 via update_attached_file()
2270
  *
2271
  * @param string $file
2272
  * @param int $attachment_id
@@ -2278,17 +2308,17 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2278
  return $file;
2279
  }
2280
 
2281
- if ( ! ( $s3object = $this->get_attachment_s3_info( $attachment_id ) ) ) {
2282
  return $file;
2283
  }
2284
 
2285
- $file = apply_filters( 'as3cf_update_attached_file', $file, $attachment_id, $s3object );
2286
 
2287
  return $file;
2288
  }
2289
 
2290
  /**
2291
- * Return the S3 URL when the local file is missing
2292
  * unless we know the calling process is and we are happy
2293
  * to copy the file back to the server to be used
2294
  *
@@ -2298,14 +2328,14 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2298
  * @return string
2299
  */
2300
  function get_attached_file( $file, $attachment_id ) {
2301
- if ( file_exists( $file ) || ! ( $s3object = $this->is_attachment_served_by_s3( $attachment_id ) ) ) {
2302
  return $file;
2303
  }
2304
 
2305
  $url = $this->get_attachment_url( $attachment_id );
2306
 
2307
  // return the URL by default
2308
- $file = apply_filters( 'as3cf_get_attached_file', $url, $file, $attachment_id, $s3object );
2309
 
2310
  return $file;
2311
  }
@@ -2351,6 +2381,38 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2351
  return true;
2352
  }
2353
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2354
  function ajax_check_bucket() {
2355
  if ( ! isset( $_POST['bucket_name'] ) || ! ( $bucket = sanitize_text_field( $_POST['bucket_name'] ) ) ) { // input var okay
2356
  $out = array( 'error' => __( 'No bucket name provided.', 'amazon-s3-and-cloudfront' ) );
@@ -2362,22 +2424,18 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2362
  }
2363
 
2364
  /**
2365
- * Handler for AJAX callback to create a bucket in S3
 
 
2366
  */
2367
  function ajax_create_bucket() {
2368
  $this->verify_ajax_request();
2369
 
 
2370
  $bucket = $this->ajax_check_bucket();
2371
 
2372
- if ( defined( 'AS3CF_REGION' ) ) {
2373
- // Are we defining the region?
2374
- $region = AS3CF_REGION;
2375
- } else {
2376
- // Are we specifying the region via the form?
2377
- $region = isset( $_POST['region'] ) ? sanitize_text_field( $_POST['region'] ) : null; // input var okay
2378
- }
2379
-
2380
  $result = $this->create_bucket( $bucket, $region );
 
2381
  if ( is_wp_error( $result ) ) {
2382
  $out = $this->prepare_bucket_error( $result, false );
2383
 
@@ -2398,11 +2456,11 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2398
  * Create an S3 bucket
2399
  *
2400
  * @param string $bucket_name
2401
- * @param null|string $region option location constraint
2402
  *
2403
  * @return bool|WP_Error
2404
  */
2405
- function create_bucket( $bucket_name, $region = null ) {
2406
  try {
2407
  $args = array( 'Bucket' => $bucket_name );
2408
 
@@ -2411,11 +2469,11 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2411
  $region = AS3CF_REGION;
2412
  }
2413
 
2414
- if ( ! is_null( $region ) && $this->get_aws()->get_default_region() !== $region ) {
2415
  $args['LocationConstraint'] = $region;
2416
  }
2417
 
2418
- $this->get_s3client()->create_bucket( $args );
2419
  } catch ( Exception $e ) {
2420
  return new WP_Error( 'exception', $e->getMessage() );
2421
  }
@@ -2425,10 +2483,13 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2425
 
2426
  /**
2427
  * Handler for AJAX callback to save the selection of a bucket
 
 
2428
  */
2429
  function ajax_save_bucket() {
2430
  $this->verify_ajax_request();
2431
 
 
2432
  $bucket = $this->ajax_check_bucket();
2433
 
2434
  $manual = false;
@@ -2437,7 +2498,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2437
  $manual = true;
2438
  }
2439
 
2440
- $this->save_bucket_for_ajax( $bucket, $manual );
2441
  }
2442
 
2443
  /**
@@ -2447,14 +2508,17 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2447
  * @param bool|false $manual_select
2448
  * @param null|string $region
2449
  * @param array $defaults
 
 
2450
  */
2451
  function save_bucket_for_ajax( $bucket, $manual_select = false, $region = null, $defaults = array() ) {
2452
  $region = $this->save_bucket( $bucket, $manual_select, $region );
2453
 
2454
  if ( ! is_wp_error( $region ) ) {
2455
  $out = array(
2456
- 'success' => '1',
2457
- 'region' => $region,
 
2458
  );
2459
 
2460
  $out = wp_parse_args( $out, $defaults );
@@ -2521,7 +2585,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2521
 
2522
  $this->set_setting( 'bucket', $bucket_name );
2523
 
2524
- if ( is_null( $region ) ) {
2525
  // retrieve the bucket region if not supplied
2526
  $region = $this->get_bucket_region( $bucket_name );
2527
  if ( is_wp_error( $region ) ) {
@@ -2529,7 +2593,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2529
  }
2530
  }
2531
 
2532
- if ( $this->get_aws()->get_default_region() === $region ) {
2533
  $region = '';
2534
  }
2535
 
@@ -2589,56 +2653,57 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2589
  * @return string
2590
  */
2591
  public function get_default_region() {
2592
- return $this->get_aws()->get_default_region();
2593
  }
2594
 
2595
  /**
2596
  * Get the S3 client
2597
  *
2598
  * @param bool|string $region specify region to client for signature
2599
- * @param bool $force force return of new S3 client when swapping regions
2600
  *
2601
  * @return Provider|Null_Provider
 
2602
  */
2603
- public function get_s3client( $region = false, $force = false ) {
2604
- if ( is_null( $this->s3client ) ||
2605
- is_null( $this->s3client_region ) ||
2606
  $force ||
2607
- ( false !== $region && $this->s3client_region !== $region ) ) {
2608
  $args = array();
2609
 
2610
  if ( $force ) {
2611
- $this->set_aws( new AWS_Provider( $this ) );
2612
  }
2613
 
2614
  if ( $region ) {
2615
- $args['region'] = $this->get_aws()->sanitize_region( $region );
2616
  }
2617
 
2618
- $s3client_region = isset( $args['region'] ) ? $args['region'] : $region;
2619
 
2620
  try {
2621
- $this->set_client( $this->get_aws()->get_client( $args ), $s3client_region );
2622
- } catch ( \Exception $e ) {
2623
  AS3CF_Error::log( $e->getMessage() );
2624
  $this->set_client( new Null_Provider );
2625
  }
2626
  }
2627
 
2628
- return $this->s3client;
2629
  }
2630
 
2631
  /**
2632
- * Setter for S3 client
2633
  *
2634
  * @param Provider|Null_Provider $client
2635
  * @param bool|string $region
2636
  */
2637
  public function set_client( $client, $region = false ) {
2638
- $this->s3client = $client;
2639
 
2640
  if ( false !== $region ) {
2641
- $this->s3client_region = $region;
2642
  }
2643
  }
2644
 
@@ -2662,7 +2727,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2662
  }
2663
 
2664
  try {
2665
- $region = $this->get_s3client( false, true )->get_bucket_location( array( 'Bucket' => $bucket ) );
2666
  } catch ( Exception $e ) {
2667
  $error_msg_title = '<strong>' . __( 'Error Getting Bucket Region', 'amazon-s3-and-cloudfront' ) . '</strong> &mdash;';
2668
  $error_msg = sprintf( __( 'There was an error attempting to get the region of the bucket %s: %s', 'amazon-s3-and-cloudfront' ), $bucket, $e->getMessage() );
@@ -2671,7 +2736,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2671
  return new WP_Error( 'exception', $error_msg_title . $error_msg );
2672
  }
2673
 
2674
- $region = $this->get_aws()->sanitize_region( $region );
2675
 
2676
  if ( is_string( $region ) ) {
2677
  $regions[ $bucket ] = $region;
@@ -2682,31 +2747,31 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2682
  }
2683
 
2684
  /**
2685
- * Get the region of the bucket stored in the S3 metadata.
2686
  *
2687
  *
2688
- * @param array $s3object
2689
- * @param int $post_id - if supplied will update the s3 meta if no region found
2690
  *
2691
  * @return string|WP_Error - region name
2692
  */
2693
- function get_s3object_region( $s3object, $post_id = null ) {
2694
- if ( ! isset( $s3object['region'] ) ) {
2695
- // if region hasn't been stored in the s3 metadata retrieve using the bucket
2696
- $region = $this->get_bucket_region( $s3object['bucket'], true );
2697
  if ( is_wp_error( $region ) ) {
2698
  return $region;
2699
  }
2700
 
2701
- $s3object['region'] = $region;
2702
 
2703
  if ( ! is_null( $post_id ) ) {
2704
- // retrospectively update s3 metadata with region
2705
- update_post_meta( $post_id, 'amazonS3_info', $s3object );
2706
  }
2707
  }
2708
 
2709
- return $s3object['region'];
2710
  }
2711
 
2712
  /**
@@ -2715,7 +2780,10 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2715
  function ajax_get_buckets() {
2716
  $this->verify_ajax_request();
2717
 
2718
- $result = $this->get_buckets();
 
 
 
2719
  if ( is_wp_error( $result ) ) {
2720
  $out = $this->prepare_bucket_error( $result, false );
2721
  } else {
@@ -2731,11 +2799,13 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2731
  /**
2732
  * Get a list of buckets from S3
2733
  *
 
 
2734
  * @return array|WP_Error - list of buckets
2735
  */
2736
- function get_buckets() {
2737
  try {
2738
- $result = $this->get_s3client()->list_buckets();
2739
  } catch ( Exception $e ) {
2740
  return new WP_Error( 'exception', $e->getMessage() );
2741
  }
@@ -2750,9 +2820,10 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2750
  * @param string $region
2751
  *
2752
  * @return bool|WP_Error
 
2753
  */
2754
  function check_write_permission( $bucket = null, $region = null ) {
2755
- if ( $this->get_aws()->needs_access_keys() ) {
2756
  // If no access keys set then no need check.
2757
  return false;
2758
  }
@@ -2780,7 +2851,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2780
  $key = $this->get_file_prefix() . 'as3cf-permission-check.txt';
2781
  $file_contents = __( 'This is a test file to check if the user has write permission to S3. Delete me if found.', 'amazon-s3-and-cloudfront' );
2782
 
2783
- $can_write = $this->get_s3client( $region, true )->can_write( $bucket, $key, $file_contents );
2784
 
2785
  // If we get back an unexpected error message, throw an error.
2786
  if ( is_string( $can_write ) ) {
@@ -2823,6 +2894,20 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2823
  wp_register_script( 'as3cf-modal', $src, array( 'jquery' ), $version, true );
2824
  }
2825
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2826
  /**
2827
  * On plugin load.
2828
  */
@@ -2839,13 +2924,13 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2839
 
2840
  add_action( 'network_admin_notices', array( $this, 'settings_saved_notice' ) );
2841
 
2842
- $this->enqueue_style( 'as3cf-styles', 'assets/css/styles', array( 'as3cf-modal' ) );
2843
- $this->enqueue_script( 'as3cf-script', 'assets/js/script', array( 'jquery', 'underscore', 'as3cf-modal' ) );
2844
 
2845
  wp_localize_script( 'as3cf-script',
2846
  'as3cf',
2847
  array(
2848
- 'strings' => array(
2849
  'create_bucket_error' => __( 'Error creating bucket', 'amazon-s3-and-cloudfront' ),
2850
  'create_bucket_name_short' => __( 'Bucket name too short.', 'amazon-s3-and-cloudfront' ),
2851
  'create_bucket_name_long' => __( 'Bucket name too long.', 'amazon-s3-and-cloudfront' ),
@@ -2860,7 +2945,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2860
  // Mimic WP Core's notice text, therefore no translation needed here.
2861
  'settings_saved' => __( 'Settings saved.' ),
2862
  ),
2863
- 'nonces' => array(
2864
  'create_bucket' => wp_create_nonce( 'as3cf-create-bucket' ),
2865
  'manual_bucket' => wp_create_nonce( 'as3cf-manual-save-bucket' ),
2866
  'get_buckets' => wp_create_nonce( 'as3cf-get-buckets' ),
@@ -2870,9 +2955,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2870
  'aws_keys_set' => wp_create_nonce( 'as3cf-aws-keys-set' ),
2871
  'aws_keys_remove' => wp_create_nonce( 'as3cf-aws-keys-remove' ),
2872
  ),
2873
- 'is_pro' => $this->is_pro(),
2874
- 'aws_bucket_link' => $this->get_aws_bucket_link(),
2875
- 'aws_bucket_link_param' => $this->get_aws_bucket_link_param(),
2876
  )
2877
  );
2878
 
@@ -2890,6 +2975,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2890
  */
2891
  function get_settings_whitelist() {
2892
  return array(
 
 
 
2893
  'bucket',
2894
  'region',
2895
  'domain',
@@ -2937,6 +3025,11 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2937
  $post_vars = $this->get_settings_whitelist();
2938
 
2939
  foreach ( $post_vars as $var ) {
 
 
 
 
 
2940
  $this->remove_setting( $var );
2941
 
2942
  if ( ! isset( $_POST[ $var ] ) ) { // input var okay
@@ -2978,10 +3071,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
2978
  */
2979
  function get_settings_tabs() {
2980
  $tabs = array(
2981
- 'media' => _x( 'Media Library', 'Show the media library tab', 'amazon-s3-and-cloudfront' ),
2982
- 'addons' => _x( 'Addons', 'Show the addons tab', 'amazon-s3-and-cloudfront' ),
2983
- 'settings' => _x( 'Settings', 'Show the settings tab', 'amazon-s3-and-cloudfront' ),
2984
- 'support' => _x( 'Support', 'Show the support tab', 'amazon-s3-and-cloudfront' ),
2985
  );
2986
 
2987
  return apply_filters( 'as3cf_settings_tabs', $tabs );
@@ -3147,85 +3239,60 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3147
  return true;
3148
  }
3149
 
3150
- /**
3151
- * Get the link to the bucket on the AWS console
3152
- *
3153
- * @param string $bucket
3154
- * @param string $prefix
3155
- *
3156
- * @return string
3157
- */
3158
- function get_aws_bucket_link( $bucket = '', $prefix = '' ) {
3159
- if ( '' !== $prefix ) {
3160
- $prefix = $this->get_aws_bucket_link_param() . urlencode( apply_filters( 'as3cf_s3_console_url_prefix_value', $prefix ) );
3161
- }
3162
-
3163
- return apply_filters( 'as3cf_s3_console_url', 'https://console.aws.amazon.com/s3/home?bucket=' ) . $bucket . $prefix;
3164
- }
3165
-
3166
- /**
3167
- * Get the link to the bucket on the AWS console's prefix param.
3168
- *
3169
- * @return string
3170
- */
3171
- function get_aws_bucket_link_param() {
3172
- return apply_filters( 'as3cf_s3_console_url_prefix_param', '&prefix=' );
3173
- }
3174
-
3175
  /**
3176
  * Apply ACL to an attachment and associated files
3177
  *
3178
  * @param int $post_id
3179
- * @param array $s3object
3180
  * @param string $acl
3181
  *
3182
  * @return array|bool|WP_Error
3183
  */
3184
- public function set_attachment_acl_on_s3( $post_id, $s3object, $acl ) {
3185
  // Return early if already set to the desired ACL
3186
- if ( isset( $s3object['acl'] ) && $acl === $s3object['acl'] ) {
3187
  return false;
3188
  }
3189
 
3190
  $args = array(
3191
  'ACL' => $acl,
3192
- 'Bucket' => $s3object['bucket'],
3193
- 'Key' => $s3object['key'],
3194
  );
3195
 
3196
- $region = ( isset( $s3object['region'] ) ) ? $s3object['region'] : false;
3197
- $s3client = $this->get_s3client( $region, true );
3198
 
3199
  try {
3200
- $s3client->update_object_acl( $args );
3201
- $s3object['acl'] = $acl;
3202
 
3203
  // update S3 meta data
3204
- if ( $acl == $this->get_aws()->get_default_acl() ) {
3205
- unset( $s3object['acl'] );
3206
  }
3207
 
3208
- update_post_meta( $post_id, 'amazonS3_info', $s3object );
3209
  } catch ( Exception $e ) {
3210
- $msg = 'Error setting ACL to ' . $acl . ' for ' . $s3object['key'] . ': ' . $e->getMessage();
3211
  AS3CF_Error::log( $msg );
3212
 
3213
  return new WP_Error( 'acl_exception', $msg );
3214
  }
3215
 
3216
- return $s3object;
3217
  }
3218
 
3219
  /**
3220
  * Make admin notice for when object ACL has changed
3221
  *
3222
- * @param array $s3object
3223
  */
3224
- function make_acl_admin_notice( $s3object ) {
3225
- $filename = wp_basename( $s3object['key'] );
3226
- $acl = ( isset( $s3object['acl'] ) ) ? $s3object['acl'] : $this->get_aws()->get_default_acl();
3227
  $acl_name = $this->get_acl_display_name( $acl );
3228
- $text = sprintf( __( '<strong>WP Offload S3</strong> &mdash; The file %s has been given %s permissions on Amazon S3.', 'amazon-s3-and-cloudfront' ), "<strong>{$filename}</strong>", "<strong>{$acl_name}</strong>" );
3229
 
3230
  $this->notices->add_notice( $text );
3231
  }
@@ -3244,7 +3311,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3244
 
3245
  if ( ! $gd_enabled && ! $imagick_enabled ) {
3246
  $this->notices->add_notice(
3247
- __( '<strong>WP Offload S3 Requirement Missing</strong> &mdash; Looks like you don\'t have an image manipulation library installed on this server and configured with PHP. You may run into trouble if you try to edit images. Please setup GD or ImageMagick.', 'amazon-s3-and-cloudfront' ),
3248
  array( 'flash' => false, 'only_show_to_user' => false, 'only_show_in_settings' => true )
3249
  );
3250
  }
@@ -3369,7 +3436,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3369
  $output .= esc_html( get_locale() );
3370
  $output .= "\r\n";
3371
 
3372
- $output .= 'Organize uploads by month/year: ';
3373
  $output .= esc_html( get_option( 'uploads_use_yearmonth_folders' ) ? 'Enabled' : 'Disabled' );
3374
  $output .= "\r\n";
3375
 
@@ -3490,7 +3557,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3490
  $output .= number_format_i18n( $media_counts['all'] );
3491
  $output .= "\r\n";
3492
 
3493
- $output .= 'Media Files on S3: ';
3494
  $output .= number_format_i18n( $media_counts['s3'] );
3495
  $output .= "\r\n";
3496
 
@@ -3529,6 +3596,10 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3529
  $output .= esc_html( ( defined( 'AWS_USE_EC2_IAM_ROLE' ) ) ? AWS_USE_EC2_IAM_ROLE : 'Not defined' );
3530
  $output .= "\r\n";
3531
 
 
 
 
 
3532
  $output .= 'AS3CF_BUCKET: ';
3533
  $output .= esc_html( ( defined( 'AS3CF_BUCKET' ) ) ? AS3CF_BUCKET : 'Not defined' );
3534
  $output .= "\r\n";
@@ -3546,7 +3617,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3546
  $output .= $region;
3547
  }
3548
  $output .= "\r\n";
3549
- $output .= 'Copy Files to S3: ';
3550
  $output .= $this->on_off( 'copy-to-s3' );
3551
  $output .= "\r\n";
3552
  $output .= 'Rewrite File URLs: ';
@@ -3557,7 +3628,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3557
  $output .= "Local URL:\r\n";
3558
  $output .= $this->get_local_url_preview( $escape );
3559
  $output .= "\r\n";
3560
- $output .= "S3 URL:\r\n";
3561
  $output .= $this->get_url_preview( $escape );
3562
  $output .= "\r\n";
3563
  $output .= "\r\n";
@@ -3867,11 +3938,11 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3867
  * @return string
3868
  */
3869
  function get_access_denied_notice_message( $single = true ) {
3870
- if ( $this->get_aws()->needs_access_keys() ) {
3871
- return sprintf( __( '<a href="%s">Define your AWS keys</a> to enable write access to the bucket', 'amazon-s3-and-cloudfront' ), '#settings' );
3872
  }
3873
 
3874
- $url = $this->dbrains_url( '/wp-offload-s3/doc/quick-start-guide/', array(
3875
  'utm_campaign' => 'error+messages',
3876
  ), 'bucket-restrictions' );
3877
 
@@ -3899,7 +3970,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3899
  // Sum the total file size (including image sizes) for all S3 attachments
3900
  $sql = "SELECT SUM( meta_value ) AS bytes_total
3901
  FROM {$wpdb->postmeta}
3902
- WHERE meta_key = 'wpos3_filesize_total'";
3903
 
3904
  $space_used = $wpdb->get_var( $sql );
3905
 
@@ -3965,14 +4036,14 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3965
  * Count attachments on a site
3966
  *
3967
  * @param string $prefix
3968
- * @param null|bool $uploaded_to_s3
3969
  * null - All attachments
3970
  * true - Attachments only uploaded to S3
3971
  * false - Attachments not uploaded to S3
3972
  *
3973
  * @return int
3974
  */
3975
- public function count_attachments( $prefix, $uploaded_to_s3 = null ) {
3976
  global $wpdb;
3977
 
3978
  $sql = "SELECT COUNT(DISTINCT p.ID)
@@ -3980,12 +4051,12 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
3980
 
3981
  $where = "WHERE p.post_type = 'attachment'";
3982
 
3983
- if ( ! is_null( $uploaded_to_s3 ) && is_bool( $uploaded_to_s3 ) ) {
3984
  $sql .= " LEFT OUTER JOIN `{$prefix}postmeta` pm
3985
  ON p.`ID` = pm.`post_id`
3986
  AND pm.`meta_key` = 'amazonS3_info'";
3987
 
3988
- $operator = $uploaded_to_s3 ? 'not ' : '';
3989
  $where .= " AND pm.`post_id` is {$operator}null";
3990
  }
3991
 
@@ -4000,24 +4071,24 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4000
  * @return array
4001
  */
4002
  protected function diagnostic_media_counts() {
4003
- if ( false === ( $attachment_counts = get_site_transient( 'wpos3_attachment_counts' ) ) ) {
4004
- $table_prefixes = $this->get_all_blog_table_prefixes();
4005
- $all_media = 0;
4006
- $all_media_s3 = 0;
4007
 
4008
  foreach ( $table_prefixes as $blog_id => $table_prefix ) {
4009
- $count = $this->count_attachments( $table_prefix );
4010
- $all_media += $count;
4011
- $s3_count = $this->count_attachments( $table_prefix, true );
4012
- $all_media_s3 += $s3_count;
4013
  }
4014
 
4015
  $attachment_counts = array(
4016
  'all' => $all_media,
4017
- 's3' => $all_media_s3,
4018
  );
4019
 
4020
- set_site_transient( 'wpos3_attachment_counts', $attachment_counts, 2 * MINUTE_IN_SECONDS );
4021
  }
4022
 
4023
  return $attachment_counts;
@@ -4029,11 +4100,11 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4029
  function plugin_deactivated_notice() {
4030
  if ( false !== ( $deactivated_notice_id = get_transient( 'as3cf_deactivated_notice_id' ) ) ) {
4031
  if ( '1' === $deactivated_notice_id ) {
4032
- $title = __( 'WP Offload S3 Activation', 'amazon-s3-and-cloudfront' );
4033
- $message = __( "WP Offload S3 Lite and WP Offload S3 cannot both be active. We've automatically deactivated WP Offload S3 Lite.", 'amazon-s3-and-cloudfront' );
4034
  } else {
4035
- $title = __( 'WP Offload S3 Lite Activation', 'amazon-s3-and-cloudfront' );
4036
- $message = __( "WP Offload S3 Lite and WP Offload S3 cannot both be active. We've automatically deactivated WP Offload S3.", 'amazon-s3-and-cloudfront' );
4037
  }
4038
 
4039
  $message = sprintf( '<strong>%s</strong> &mdash; %s', esc_html( $title ), esc_html( $message ) );
@@ -4100,7 +4171,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4100
  * @return string
4101
  */
4102
  public function settings_more_info_link( $hash, $utm_content = '' ) {
4103
- return $this->more_info_link( '/wp-offload-s3/doc/settings/', $utm_content, $hash );
4104
  }
4105
 
4106
  /**
@@ -4177,12 +4248,12 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4177
  'flash' => false,
4178
  );
4179
 
4180
- $doc_url = $this->dbrains_url( '/wp-offload-s3/doc/force-http-setting/', array(
4181
  'utm_campaign' => 'support+docs',
4182
  ) );
4183
  $doc_link = AS3CF_Utils::dbrains_link( $doc_url, __( 'this doc' ) );
4184
 
4185
- $message = sprintf( '<strong>%s</strong> &mdash; ', __( 'WP Offload S3 Feature Removed', 'amazon-s3-and-cloudfront' ) );
4186
  $message .= sprintf( __( 'You had the "Always non-SSL" option selected in your settings, but we\'ve removed this option in version 1.3. We\'ll now use HTTPS when the request is HTTPS and regular HTTP when the request is HTTP. This should work fine for your site, but please take a poke around and make sure things are working ok. See %s for more details on why we did this and how you can revert back to the old behavior.', 'amazon-s3-and-cloudfront' ), $doc_link );
4187
 
4188
  $this->notices->add_notice( $message, $notice_args );
@@ -4210,11 +4281,11 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4210
  /**
4211
  * Add the S3 meta box to the attachment screen
4212
  */
4213
- public function attachment_s3_meta_box() {
4214
  add_meta_box(
4215
  's3-actions',
4216
- __( 'Amazon S3', 'amazon-s3-and-cloudfront' ),
4217
- array( $this, 'attachment_s3_actions_meta_box' ),
4218
  'attachment',
4219
  'side',
4220
  'core'
@@ -4244,12 +4315,12 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4244
  /**
4245
  * Render the S3 attachment meta box
4246
  */
4247
- public function attachment_s3_actions_meta_box() {
4248
  global $post;
4249
  $file = get_attached_file( $post->ID, true );
4250
 
4251
  $args = array(
4252
- 's3object' => $this->get_formatted_s3_info( $post->ID ),
4253
  'post' => $post,
4254
  'local_file_exists' => file_exists( $file ),
4255
  'available_actions' => $this->get_available_media_actions( 'singular' ),
@@ -4263,10 +4334,11 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4263
  * Get ACL value string.
4264
  *
4265
  * @param array $acl
 
4266
  *
4267
  * @return string
4268
  */
4269
- protected function get_acl_value_string( $acl ) {
4270
  return $acl['name'];
4271
  }
4272
 
@@ -4274,43 +4346,41 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4274
  * Return a formatted S3 info with display friendly defaults
4275
  *
4276
  * @param int $id
4277
- * @param array|null $s3object
4278
  *
4279
  * @return array
4280
  */
4281
- public function get_formatted_s3_info( $id, $s3object = null ) {
4282
- if ( is_null( $s3object ) ) {
4283
- if ( ! ( $s3object = $this->get_attachment_s3_info( $id ) ) ) {
4284
  return false;
4285
  }
4286
  }
4287
 
4288
- $s3object['url'] = $this->get_attachment_s3_url( $id, $s3object );
4289
 
4290
- $acl = ( isset( $s3object['acl'] ) ) ? $s3object['acl'] : $this->get_aws()->get_default_acl();
4291
  $acl_info = array(
4292
  'acl' => $acl,
4293
  'name' => $this->get_acl_display_name( $acl ),
4294
  'title' => $this->get_media_action_strings( 'change_to_private' ),
4295
  );
4296
 
4297
- if ( $this->get_aws()->get_private_acl() === $acl ) {
4298
  $acl_info['title'] = $this->get_media_action_strings( 'change_to_public' );
4299
  }
4300
 
4301
- $s3object['acl'] = $acl_info;
4302
-
4303
- $regions = $this->get_aws()->get_regions();
4304
 
4305
- if ( isset( $s3object['region'] ) && '' == $s3object['region'] ) {
4306
- $s3object['region'] = $this->get_aws()->get_default_region();
4307
  }
4308
 
4309
- if ( isset( $regions[ $s3object['region'] ] ) ) {
4310
- $s3object['region'] = $regions[ $s3object['region'] ];
4311
  }
4312
 
4313
- return $s3object;
4314
  }
4315
 
4316
  /**
@@ -4322,12 +4392,13 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4322
  */
4323
  public function get_media_action_strings( $string = null ) {
4324
  $strings = apply_filters( 'as3cf_media_action_strings', array(
4325
- 'amazon_s3' => __( 'Amazon S3', 'amazon-s3-and-cloudfront' ),
4326
- 'bucket' => _x( 'Bucket', 'Amazon S3 bucket', 'amazon-s3-and-cloudfront' ),
4327
- 'key' => _x( 'Path', 'Path to file on Amazon S3', 'amazon-s3-and-cloudfront' ),
4328
- 'region' => _x( 'Region', 'Location of Amazon S3 bucket', 'amazon-s3-and-cloudfront' ),
4329
- 'acl' => _x( 'Access', 'Access control list of the file on Amazon S3', 'amazon-s3-and-cloudfront' ),
4330
- 'url' => __( 'URL', 'amazon-s3-and-cloudfront' ),
 
4331
  ) );
4332
 
4333
  if ( ! is_null( $string ) ) {
@@ -4352,7 +4423,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4352
  wp_localize_script( 'as3cf-media-script', 'as3cf_media', array(
4353
  'strings' => $this->get_media_action_strings(),
4354
  'nonces' => array(
4355
- 'get_attachment_s3_details' => wp_create_nonce( 'get-attachment-s3-details' ),
4356
  ),
4357
  ) );
4358
  }
@@ -4360,7 +4431,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4360
  /**
4361
  * Handle retieving the S3 details for attachment modals.
4362
  */
4363
- public function ajax_get_attachment_s3_details() {
4364
  if ( ! isset( $_POST['id'] ) ) {
4365
  return;
4366
  }
@@ -4371,9 +4442,9 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4371
 
4372
  // get the actions available for the attachment
4373
  $data = array(
4374
- 'links' => $this->add_media_row_actions( array(), $id ),
4375
- 's3object' => $this->get_formatted_s3_info( $id ),
4376
- 'acl_toggle' => $this->verify_media_actions(),
4377
  );
4378
 
4379
  wp_send_json_success( $data );
@@ -4496,17 +4567,17 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4496
  * @return string
4497
  */
4498
  public function get_acl_for_intermediate_size( $attachment_id, $size ) {
4499
- $s3_info = $this->get_attachment_s3_info( $attachment_id );
4500
 
4501
  if ( 'original' === $size || empty( $size ) ) {
4502
- return isset( $s3_info['acl'] ) ? $s3_info['acl'] : $this->get_aws()->get_default_acl();
4503
  }
4504
 
4505
- if ( ! empty( $s3_info['sizes'][ $size ]['acl'] ) ) {
4506
- return $s3_info['sizes'][ $size ]['acl'];
4507
  }
4508
 
4509
- return $this->get_aws()->get_default_acl();
4510
  }
4511
 
4512
  /**
@@ -4552,8 +4623,8 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4552
  return array(
4553
  'amazon-s3-and-cloudfront-assets-pull' => array(
4554
  'title' => __( 'Assets Pull', 'amazon-s3-and-cloudfront' ),
4555
- 'sub' => __( 'An addon for WP Offload S3 to serve your site\'s JS, CSS, and other enqueued assets from Amazon CloudFront or another CDN.', 'amazon-s3-and-cloudfront' ),
4556
- 'url' => $this->dbrains_url( '/wp-offload-s3/doc/assets-pull-addon/', array(
4557
  'utm_campaign' => 'addons+install',
4558
  ) ),
4559
  'label' => __( 'Feature', 'amazon-s3-and-cloudfront' ),
@@ -4602,7 +4673,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4602
 
4603
  if ( is_plugin_active( 'amazon-web-services/amazon-web-services.php' ) ) {
4604
  $message = sprintf(
4605
- __( '<strong>Amazon Web Services Plugin No Longer Required</strong> &mdash; As of version 1.6 of WP Offload S3, the <a href="%1$s">Amazon Web Services</a> plugin is no longer required. We have removed the dependency by bundling a small portion of the AWS SDK into WP Offload S3. As long as none of your other active plugins or themes depend on the Amazon Web Services plugin, it should be safe to deactivate and delete it. %2$s', 'amazon-s3-and-cloudfront' ),
4606
  'https://wordpress.org/plugins/amazon-web-services/',
4607
  $this->more_info_link( '/wp-offload-s3-1-6-released/', 'os3+settings+aws+active' )
4608
  );
@@ -4613,14 +4684,14 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4613
  );
4614
  $this->notices->add_notice( $message, $args );
4615
 
4616
- if ( is_a( $this->get_aws(), '\DeliciousBrains\WP_Offload_S3\Providers\AWS_Provider' ) && $this->get_aws()->needs_access_keys() ) {
4617
  // Have access keys been defined in still active AWS plugin's database settings?
4618
  $aws_settings = get_site_option( 'aws_settings' );
4619
 
4620
  // If both AWS keys set and we already have a bucket set, safe to use the AWS keys.
4621
  if ( ! empty( $aws_settings['access_key_id'] ) && ! empty( $aws_settings['secret_access_key'] ) && false !== $this->get_setting( 'bucket' ) ) {
4622
- $this->set_setting( 'aws-access-key-id', $aws_settings['access_key_id'] );
4623
- $this->set_setting( 'aws-secret-access-key', $aws_settings['secret_access_key'] );
4624
  $this->save_settings();
4625
  }
4626
  }
@@ -4634,7 +4705,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4634
  */
4635
  public function handle_aws_access_key_form_header() {
4636
  $notice['message'] = sprintf(
4637
- __( '<strong>WP Offload S3 Settings Moved</strong> &mdash; You now define your AWS keys for WP Offload S3 in the new <a href="%1$s">Settings tab</a>. Saving settings in the form below will have no effect on WP Offload S3. %2$s', 'amazon-s3-and-cloudfront' ),
4638
  $this->get_plugin_page_url( array( 'hash' => 'settings' ) ),
4639
  $this->more_info_link( '/wp-offload-s3-1-6-released/', 'aws+os3+access+keys+setting+moved' )
4640
  );
@@ -4678,7 +4749,7 @@ class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
4678
  }
4679
  }
4680
 
4681
- delete_post_meta( $post_id, 'wpos3_filesize_total' );
4682
 
4683
  return $data;
4684
  }
1
  <?php
2
 
3
+ use DeliciousBrains\WP_Offload_Media\Providers\AWS_Provider;
4
+ use DeliciousBrains\WP_Offload_Media\Providers\DigitalOcean_Provider;
5
+ use DeliciousBrains\WP_Offload_Media\Providers\Null_Provider;
6
+ use DeliciousBrains\WP_Offload_Media\Providers\Provider;
7
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_Content_Replace_URLs;
8
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_EDD_Replace_URLs;
9
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_File_Sizes;
10
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_Filter_Post_Excerpt;
11
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_Meta_WP_Error;
12
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_Region_Meta;
13
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Upgrade_WPOS3_To_AS3CF;
14
 
15
  class Amazon_S3_And_CloudFront extends AS3CF_Plugin_Base {
16
 
17
  /**
18
  * @var Provider
19
  */
20
+ private $provider;
21
 
22
  /**
23
  * @var Provider
24
  */
25
+ private $provider_client;
26
 
27
  /**
28
  * @var string
29
  */
30
+ private $provider_client_region;
31
 
32
  /**
33
  * @var array
62
  /**
63
  * @var AS3CF_S3_To_Local
64
  */
65
+ public $filter_provider;
66
 
67
  /**
68
  * @var AS3CF_Notices
79
  */
80
  protected static $buckets_check = array();
81
 
82
+ /**
83
+ * @var string
84
+ */
85
+ protected static $default_provider = 'aws';
86
+
87
+ /**
88
+ * @var array Known provider classes.
89
+ */
90
+ protected static $provider_classes = array();
91
+
92
  /**
93
  * @var AS3CF_Plugin_Compatibility
94
  */
97
  const DEFAULT_EXPIRES = 900;
98
 
99
  const SETTINGS_KEY = 'tantan_wordpress_s3';
100
+
101
+ /**
102
+ * @var array
103
+ */
104
+ protected static $settings_constants = array(
105
+ 'AS3CF_SETTINGS',
106
+ 'WPOS3_SETTINGS',
107
+ );
108
 
109
  const LATEST_UPGRADE_ROUTINE = 6;
110
 
128
  * Abstract class constructor
129
  *
130
  * @param string $plugin_file_path
131
+ *
132
+ * @throws Exception
133
  */
134
  function init( $plugin_file_path ) {
135
+ $this->plugin_title = __( 'Offload Media', 'amazon-s3-and-cloudfront' );
136
+ $this->plugin_menu_title = __( 'Offload Media', 'amazon-s3-and-cloudfront' );
137
+
138
+ static::$provider_classes = array(
139
+ AWS_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\AWS_Provider',
140
+ DigitalOcean_Provider::get_provider_key_name() => 'DeliciousBrains\WP_Offload_Media\Providers\DigitalOcean_Provider',
141
+ );
142
 
143
+ $this->set_provider();
144
 
145
  // Bundled SDK may require AWS setup before data migrations.
146
  $this->handle_aws_access_key_migration();
151
  new Upgrade_Content_Replace_URLs( $this );
152
  new Upgrade_EDD_Replace_URLs( $this );
153
  new Upgrade_Filter_Post_Excerpt( $this );
154
+ new Upgrade_WPOS3_To_AS3CF( $this );
155
 
156
  // Plugin setup
157
  add_action( 'admin_menu', array( $this, 'admin_menu' ) );
162
  add_filter( 'pre_get_space_used', array( $this, 'multisite_get_space_used' ) );
163
  // display a notice when either lite or pro is automatically deactivated
164
  add_action( 'pre_current_active_plugins', array( $this, 'plugin_deactivated_notice' ) );
165
+ add_action( 'as3cf_plugin_load', array( $this, 'remove_access_keys_if_constants_set' ) );
166
 
167
  // Attachment screens/modals
168
  add_action( 'load-upload.php', array( $this, 'load_media_assets' ), 11 );
169
  add_action( 'admin_enqueue_scripts', array( $this, 'load_attachment_assets' ), 11 );
170
+ add_action( 'add_meta_boxes', array( $this, 'attachment_provider_meta_box' ) );
171
 
172
  // UI AJAX
173
  add_action( 'wp_ajax_as3cf-get-buckets', array( $this, 'ajax_get_buckets' ) );
175
  add_action( 'wp_ajax_as3cf-create-bucket', array( $this, 'ajax_create_bucket' ) );
176
  add_action( 'wp_ajax_as3cf-manual-save-bucket', array( $this, 'ajax_save_bucket' ) );
177
  add_action( 'wp_ajax_as3cf-get-url-preview', array( $this, 'ajax_get_url_preview' ) );
178
+ add_action( 'wp_ajax_as3cf_get_attachment_provider_details', array( $this, 'ajax_get_attachment_provider_details' ) );
179
  add_action( 'wp_ajax_as3cf-get-diagnostic-info', array( $this, 'ajax_get_diagnostic_info' ) );
 
 
180
 
181
  // Rewriting URLs, doesn't depend on plugin being setup
182
  add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 99, 2 );
188
  add_filter( 'wp_audio_shortcode', array( $this, 'wp_media_shortcode' ), 100, 5 );
189
  add_filter( 'wp_video_shortcode', array( $this, 'wp_media_shortcode' ), 100, 5 );
190
 
191
+ // Communication with provider, plugin needs to be setup
192
  add_filter( 'wp_handle_upload_prefilter', array( $this, 'wp_handle_upload_prefilter' ), 1 );
193
  add_filter( 'wp_handle_sideload_prefilter', array( $this, 'wp_handle_upload_prefilter' ), 1 );
194
  add_filter( 'wp_update_attachment_metadata', array( $this, 'wp_update_attachment_metadata' ), 110, 2 );
196
  add_filter( 'update_attached_file', array( $this, 'update_attached_file' ), 100, 2 );
197
 
198
  // Listen for settings changes
199
+ if ( false !== static::settings_constant() ) {
200
+ add_action( 'as3cf_constant_' . static::settings_constant() . '_changed_bucket', array( $this, 'bucket_changed' ) );
201
+ }
202
 
203
  // Content filtering
204
+ $this->filter_local = new AS3CF_Local_To_S3( $this );
205
+ $this->filter_provider = new AS3CF_S3_To_Local( $this );
206
 
207
  // include compatibility code for other plugins
208
  $this->plugin_compat = new AS3CF_Plugin_Compatibility( $this );
211
 
212
  // Register modal scripts and styles
213
  $this->register_modal_assets();
214
+
215
+ // Register storage provider scripts and styles
216
+ $this->register_storage_provider_assets();
217
  }
218
 
219
  /**
220
  * @return Provider
221
  */
222
+ public function get_provider() {
223
+ return $this->provider;
224
+ }
225
+
226
+ /**
227
+ * @param Provider|string|null $provider
228
+ *
229
+ * @throws Exception
230
+ */
231
+ public function set_provider( $provider = null ) {
232
+ if ( empty( $provider ) ) {
233
+ $provider = $this->get_core_setting( 'provider', static::$default_provider );
234
+ }
235
+
236
+ if ( empty( $provider ) ) {
237
+ $wibble = $provider;
238
+ }
239
+ if ( is_string( $provider ) ) {
240
+ $provider = new self::$provider_classes[ $provider ]( $this );
241
+ }
242
+
243
+ $this->provider = $provider;
244
+ }
245
+
246
+ /**
247
+ * Returns the currently supported Providers.
248
+ *
249
+ * @return array
250
+ */
251
+ public function get_provider_classes() {
252
+ return self::$provider_classes;
253
+ }
254
+
255
+ /**
256
+ * Returns provider class name for given key.
257
+ *
258
+ * @param string $key_name
259
+ *
260
+ * @return mixed|null
261
+ */
262
+ public function get_provider_class( $key_name ) {
263
+ $classes = $this->get_provider_classes();
264
+
265
+ return empty( $classes[ $key_name ] ) ? null : $classes[ $key_name ];
266
  }
267
 
268
  /**
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
+ /** @var Provider $class */
277
+ $class = $this->get_provider_class( $key_name );
278
+
279
+ return empty( $class ) ? __( 'Unknown', 'amazon-s3-and-cloudfront' ) : $class::get_provider_name();
280
+ }
281
+
282
+ /**
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
+ /** @var Provider $class */
291
+ $class = $this->get_provider_class( $key_name );
292
+
293
+ return empty( $class ) ? __( 'Unknown', 'amazon-s3-and-cloudfront' ) : $class::get_provider_service_name();
294
  }
295
 
296
  /**
362
  // use settings from $_POST when generating URL preview via AJAX
363
  if ( isset( $_POST['action'] ) && 'as3cf-get-url-preview' == sanitize_key( $_POST['action'] ) ) { // input var okay
364
  $this->verify_ajax_request();
365
+ $value = empty( $default ) ? 0 : $default;
366
  if ( isset( $_POST[ $key ] ) ) { // input var okay
367
  $value = $_POST[ $key ]; // input var okay
368
  if ( is_array( $value ) ) {
480
  return $force_https;
481
  }
482
 
483
+ // Access Key ID since 2.0.
484
+ if ( 'access-key-id' === $key && ! isset( $settings['access-key-id'] ) ) {
485
+ $aws_access_key_id = $this->get_setting( 'aws-access-key-id' );
486
+
487
+ $this->set_setting( 'access-key-id', $aws_access_key_id );
488
+ $this->remove_setting( 'aws-access-key-id' );
489
+ $this->save_settings();
490
+
491
+ return $aws_access_key_id;
492
+ }
493
+
494
+ // Secret Access Key since 2.0.
495
+ if ( 'secret-access-key' === $key && ! isset( $settings['secret-access-key'] ) ) {
496
+ $aws_secret_access_key = $this->get_setting( 'aws-secret-access-key' );
497
+
498
+ $this->set_setting( 'secret-access-key', $aws_secret_access_key );
499
+ $this->remove_setting( 'aws-secret-access-key' );
500
+ $this->save_settings();
501
+
502
+ return $aws_secret_access_key;
503
+ }
504
+
505
  $value = parent::get_setting( $key, $default );
506
 
507
+ // Provider
508
+ if ( false !== ( $provider = $this->get_setting_provider( $key, $value ) ) ) {
509
+ return $provider;
510
+ }
511
+
512
  // Bucket
513
  if ( false !== ( $bucket = $this->get_setting_bucket( $key, $value ) ) ) {
514
  return $bucket;
517
  return apply_filters( 'as3cf_setting_' . $key, $value );
518
  }
519
 
520
+ /**
521
+ * Get the provider and if a constant save to database
522
+ *
523
+ * @param string $key
524
+ * @param string $value
525
+ * @param string $constant
526
+ *
527
+ * @return string|false
528
+ */
529
+ public function get_setting_provider( $key, $value, $constant = 'AS3CF_PROVIDER' ) {
530
+ if ( 'provider' === $key && defined( $constant ) ) {
531
+ $provider = constant( $constant );
532
+
533
+ if ( ! empty( $value ) ) {
534
+ // Clear bucket
535
+ $this->remove_setting( 'provider' );
536
+ $this->save_settings();
537
+ }
538
+
539
+ return $provider;
540
+ }
541
+
542
+ return false;
543
+ }
544
+
545
  /**
546
  * Get the region setting
547
  *
571
 
572
  // Region of bucket translation
573
  if ( 'region' === $key && isset( $settings['region'] ) ) {
574
+ return $this->get_provider()->sanitize_region( $settings['region'] );
575
  }
576
 
577
  return false;
580
  /**
581
  * Get the bucket and if a constant save to database and clear region
582
  *
583
+ * @param string $key
584
+ * @param string $value
585
+ * @param string $constant
586
  *
587
  * @return string|false
588
  */
698
 
699
  // Remove disallowed characters from custom domain
700
  if ( 'cloudfront' === $key ) {
701
+ $value = AS3CF_Utils::sanitize_custom_domain( $value );
702
  }
703
 
704
  parent::set_setting( $key, $value );
705
  }
706
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
707
  /**
708
  * Disables the save button if all settings have been defined.
709
  *
710
+ * @param array $defined_settings
711
  *
712
  * @return string
713
  */
766
  }
767
 
768
  /**
769
+ * Allowed mime types array that can be edited for specific provider uploading
770
  *
771
  * @return array
772
  */
841
  }
842
 
843
  /**
844
+ * Generate a preview of the URL of files uploaded to provider
845
  *
846
  * @param bool $escape
847
  * @param string $suffix
849
  * @return string
850
  */
851
  function get_url_preview( $escape = true, $suffix = 'photo.jpg' ) {
852
+ $scheme = $this->get_url_scheme();
853
  $bucket = $this->get_setting( 'bucket' );
854
  $path = $this->maybe_update_cloudfront_path( $this->get_file_prefix() );
855
  $region = $this->get_setting( 'region' );
857
  $region = '';
858
  }
859
 
860
+ $domain = $this->get_provider()->get_url_domain( $bucket, $region, null, array(), true );
861
 
862
  $url = $scheme . '://' . $domain . '/' . $path . $suffix;
863
 
878
  $url = $this->get_url_preview();
879
 
880
  $out = array(
881
+ 'success' => '1',
882
+ 'url' => $url,
883
+ 'seo_friendly' => AS3CF_Utils::seo_friendly_url( $this->get_url_preview( false ) ),
884
  );
885
 
886
  $this->end_ajax( $out );
901
  }
902
 
903
  /**
904
+ * Remove access keys from saved settings if a key constant is defined.
905
  */
906
+ public function remove_access_keys_if_constants_set() {
 
 
 
 
 
 
 
 
907
  if ( AWS_Provider::is_any_access_key_constant_defined() ) {
908
+ $this->remove_access_keys();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
909
  }
 
 
 
 
910
  }
911
 
912
  /**
913
+ * Remove access keys from settings.
914
  */
915
+ protected function remove_access_keys() {
916
+ $this->remove_setting( 'access-key-id' );
917
+ $this->remove_setting( 'secret-access-key' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
918
  $this->save_settings();
919
  }
920
 
921
  /**
922
+ * Delete bulk objects from an provider bucket
923
  *
924
  * @param string $region
925
  * @param string $bucket
926
  * @param array $objects
927
  * @param bool $log_error
928
  * @param bool $return_on_error
929
+ * @param bool $force_new_provider_client if we are deleting in bulk, force new provider client
930
+ * to cope with possible different regions
931
  *
932
  * @return bool
933
  */
934
+ function delete_objects( $region, $bucket, $objects, $log_error = false, $return_on_error = false, $force_new_provider_client = false ) {
935
  $chunks = array_chunk( $objects, 1000 );
936
 
937
  try {
938
  foreach ( $chunks as $chunk ) {
939
+ $this->get_provider_client( $region, $force_new_provider_client )->delete_objects( array(
940
  'Bucket' => $bucket,
941
  'Objects' => $chunk,
942
  ) );
943
  }
944
  } catch ( Exception $e ) {
945
  if ( $log_error ) {
946
+ AS3CF_Error::log( 'Error removing files from bucket: ' . $e->getMessage() );
947
  }
948
 
949
  return false;
953
  }
954
 
955
  /**
956
+ * Removes an attachment's files from provider.
957
  *
958
  * @param int $post_id
959
+ * @param array $provider_object
960
  * @param bool $remove_backup_sizes remove previous edited image versions
961
  * @param bool $log_error
962
  * @param bool $return_on_error
963
+ * @param bool $force_new_provider_client if we are deleting in bulk, force new provider client
964
  * to cope with possible different regions
965
  */
966
+ function remove_attachment_files_from_provider( $post_id, $provider_object, $remove_backup_sizes = true, $log_error = false, $return_on_error = false, $force_new_provider_client = false ) {
967
+ $prefix = $this->normalize_object_prefix( $provider_object['key'] );
968
+ $bucket = $provider_object['bucket'];
969
+ $region = $this->get_provider_object_region( $provider_object );
970
  $paths = AS3CF_Utils::get_attachment_file_paths( $post_id, false, false, $remove_backup_sizes );
971
+ $paths = apply_filters( 'as3cf_remove_attachment_paths', $paths, $post_id, $provider_object, $remove_backup_sizes );
972
 
973
  if ( is_wp_error( $region ) ) {
974
  $region = '';
982
  );
983
  }
984
 
985
+ // finally delete the objects from provider
986
+ $this->delete_objects( $region, $bucket, $objects_to_remove, $log_error, $return_on_error, $force_new_provider_client );
987
  }
988
 
989
  /**
990
+ * Removes an attachment and intermediate image size files from provider
991
  *
992
  * @param int $post_id
993
+ * @param bool $force_new_provider_client if we are deleting in bulk, force new provider client
994
+ * to cope with possible different regions
995
  */
996
+ function delete_attachment( $post_id, $force_new_provider_client = false ) {
997
  if ( ! $this->is_plugin_setup( true ) ) {
998
  return;
999
  }
1000
 
1001
+ if ( ! ( $provider_object = $this->get_attachment_provider_info( $post_id ) ) ) {
1002
+ return;
1003
+ }
1004
+
1005
+ if ( ! $this->is_attachment_served_by_provider( $post_id, true ) ) {
1006
  return;
1007
  }
1008
 
1009
+ $this->remove_attachment_files_from_provider( $post_id, $provider_object, true, true, true, $force_new_provider_client );
1010
 
1011
  delete_post_meta( $post_id, 'amazonS3_info' );
1012
  }
1013
 
1014
  /**
1015
+ * Handles the upload of the attachment to provider when an attachment is updated using
1016
  * the 'wp_update_attachment_metadata' filter
1017
  *
1018
  * @param array $data meta data for attachment
1019
  * @param int $post_id
1020
  *
1021
  * @return array
1022
+ * @throws Exception
1023
  */
1024
  function wp_update_attachment_metadata( $data, $post_id ) {
1025
  if ( ! $this->is_plugin_setup( true ) ) {
1026
  return $data;
1027
  }
1028
 
1029
+ if ( ! ( $old_provider_object = $this->get_attachment_provider_info( $post_id ) ) && ! $this->get_setting( 'copy-to-s3' ) ) {
1030
+ // abort if not already uploaded to provider and the copy setting is off
1031
  return $data;
1032
  }
1033
 
1034
+ // allow provider upload to be cancelled for any reason
1035
+ $pre = apply_filters( 'as3cf_pre_update_attachment_metadata', false, $data, $post_id, $old_provider_object );
1036
  if ( false !== $pre ) {
1037
  return $data;
1038
  }
1039
 
1040
+ // upload attachment to provider
1041
+ $provider_meta = $this->upload_attachment( $post_id, $data );
1042
 
1043
+ if ( is_wp_error( $provider_meta ) ) {
1044
  return $data;
1045
  }
1046
 
1047
+ return $provider_meta;
1048
  }
1049
 
1050
  /**
1051
+ * Upload attachment to provider
1052
  *
1053
  * @param int $post_id
1054
  * @param array|null $data
1055
  * @param string|null $file_path
1056
+ * @param bool $force_new_provider_client if we are uploading in bulk, force new provider client
1057
+ * to cope with possible different regions
1058
  * @param bool $remove_local_files
1059
  *
1060
+ * @return array|WP_Error $provider_object|$meta If meta is supplied, return it. Else return provider meta
1061
+ * @throws Exception
1062
  */
1063
+ public function upload_attachment( $post_id, $data = null, $file_path = null, $force_new_provider_client = false, $remove_local_files = true ) {
1064
  $return_metadata = null;
1065
  if ( is_null( $data ) ) {
1066
  $data = wp_get_attachment_metadata( $post_id, true );
1073
  return $data;
1074
  }
1075
 
1076
+ // Allow provider upload to be hijacked / cancelled for any reason
1077
  try {
1078
  $pre = apply_filters( 'as3cf_pre_upload_attachment', false, $post_id, $data );
1079
+ } catch ( Exception $e ) {
1080
  return $this->return_upload_error( $e->getMessage() );
1081
  }
1082
 
1101
  $type = get_post_mime_type( $post_id );
1102
  $allowed_types = $this->get_allowed_mime_types();
1103
 
1104
+ // check mime type of file is in allowed provider mime types
1105
  if ( ! in_array( $type, $allowed_types ) ) {
1106
  $error_msg = sprintf( __( 'Mime type %s is not allowed', 'amazon-s3-and-cloudfront' ), $type );
1107
 
1108
  return $this->return_upload_error( $error_msg, $return_metadata );
1109
  }
1110
 
1111
+ $acl = $this->get_provider()->get_default_acl();
1112
+
1113
+ // check the attachment already exists in provider, eg. edit or restore image
1114
+ if ( ( $old_provider_object = $this->get_attachment_provider_info( $post_id ) ) ) {
1115
+ // Must be offloaded to same provider as currently configured.
1116
+ if ( ! $this->is_attachment_served_by_provider( $post_id, true ) ) {
1117
+ return $this->return_upload_error( __( 'Already offloaded to a different provider', 'amazon-s3-and-cloudfront' ), $return_metadata );
1118
+ }
1119
 
 
 
1120
  // use existing non default ACL if attachment already exists
1121
+ if ( isset( $old_provider_object['acl'] ) ) {
1122
+ $acl = $old_provider_object['acl'];
1123
  }
1124
+
1125
  // use existing prefix
1126
+ $prefix = $this->normalize_object_prefix( $old_provider_object['key'] );
1127
  // use existing bucket
1128
+ $bucket = $old_provider_object['bucket'];
1129
  // get existing region
1130
+ $region = isset( $old_provider_object['region'] ) ? $old_provider_object['region'] : '';
1131
  } else {
1132
  // derive prefix from various settings
1133
  if ( isset( $data['file'] ) ) {
1168
  $args['ContentEncoding'] = 'gzip';
1169
  }
1170
 
1171
+ $image_size = wp_attachment_is_image( $post_id ) ? 'full' : '';
1172
+ $args = apply_filters( 'as3cf_object_meta', $args, $post_id, $image_size, false );
1173
+ $provider_object = array(
1174
+ 'provider' => $this->get_provider()->get_provider_key_name(),
1175
+ 'region' => $bucket !== $args['Bucket'] ? $this->get_bucket_region( $args['Bucket'], true ) : $region,
1176
+ 'bucket' => $args['Bucket'],
1177
+ 'key' => $args['Key'],
1178
+ 'acl' => $args['ACL'],
1179
  );
1180
 
1181
  // Do not store object ACL if set to the default value.
1182
+ if ( $provider_object['acl'] === $this->get_provider()->get_default_acl() ) {
1183
+ unset( $provider_object['acl'] );
1184
  }
1185
 
1186
+ do_action( 'as3cf_upload_attachment_pre_remove', $post_id, $provider_object, $prefix, $args );
1187
 
1188
  $files_to_remove = array();
1189
 
1190
+ $provider_client = $this->get_provider_client( $provider_object['region'], $force_new_provider_client );
1191
 
1192
  try {
1193
+ $provider_client->upload_object( $args );
1194
  $files_to_remove[] = $file_path;
1195
  } catch ( Exception $e ) {
1196
+ $error_msg = sprintf( __( 'Error offloading %s to provider: %s', 'amazon-s3-and-cloudfront' ), $file_path, $e->getMessage() );
1197
 
1198
  return $this->return_upload_error( $error_msg, $return_metadata );
1199
  }
1200
 
1201
  delete_post_meta( $post_id, 'amazonS3_info' );
1202
 
1203
+ add_post_meta( $post_id, 'amazonS3_info', $provider_object );
1204
 
1205
+ $file_paths = AS3CF_Utils::get_attachment_file_paths( $post_id, false, $data );
1206
+ $additional_images = array();
1207
+ $provider_object_sizes = array();
1208
 
1209
  foreach ( $file_paths as $size => $file_path ) {
1210
  if ( ! in_array( $file_path, $files_to_remove ) ) {
1211
+ $acl = apply_filters( 'as3cf_upload_acl_sizes', $this->get_provider()->get_default_acl(), $size, $post_id, $data );
1212
 
1213
  $additional_images[ $size ] = array(
1214
  'Key' => $prefix . wp_basename( $file_path ),
1217
  'ContentType' => $this->get_mime_type( $file_path ),
1218
  );
1219
 
1220
+ if ( $this->get_provider()->get_default_acl() !== $acl ) {
1221
+ $provider_object_sizes[ $size ]['acl'] = $acl;
1222
  }
1223
  }
1224
  }
1234
  }
1235
 
1236
  try {
1237
+ $provider_client->upload_object( $args );
1238
  $files_to_remove[] = $image['SourceFile'];
1239
  } catch ( Exception $e ) {
1240
+ $upload_errors[] = $this->return_upload_error( sprintf( __( 'Error offloading %s to provider: %s', 'amazon-s3-and-cloudfront' ), $args['SourceFile'], $e->getMessage() ) );
1241
  }
1242
  }
1243
 
1267
  }
1268
 
1269
  // Make sure we don't have cached file sizes in the meta if we previously added it.
1270
+ if ( ! $remove_local_files_setting && isset( $data['filesize'] ) && ! empty( get_post_meta( $post_id, 'as3cf_filesize_total', true ) ) ) {
1271
  $data = $this->maybe_cleanup_filesize_metadata( $post_id, $data, empty( $return_metadata ) );
1272
  }
1273
 
1274
+ if ( ! empty( $provider_object_sizes ) ) {
1275
  // Additional image sizes have custom ACLs, update meta
1276
+ $provider_object['sizes'] = $provider_object_sizes;
1277
+ update_post_meta( $post_id, 'amazonS3_info', $provider_object );
1278
  }
1279
 
1280
  // Keep track of attachments uploaded by this instance.
1281
  $this->uploaded_post_ids[] = $post_id;
1282
 
1283
+ do_action( 'as3cf_post_upload_attachment', $post_id, $provider_object );
1284
 
1285
  if ( $upload_errors ) {
1286
  return $this->consolidate_upload_errors( $upload_errors );
1291
  return $data;
1292
  }
1293
 
1294
+ return $provider_object;
1295
  }
1296
 
1297
  /**
1407
 
1408
  // If we were able to sum up file sizes for an attachment, record it.
1409
  if ( $filesize_total > 0 ) {
1410
+ update_post_meta( $attachment_id, 'as3cf_filesize_total', $filesize_total );
1411
  }
1412
  }
1413
 
1527
  $name = '';
1528
  }
1529
 
1530
+ // Rebuild filename with lowercase extension as provider will have converted extension on upload.
1531
  $ext = strtolower( $ext );
1532
  $filename = $name . $ext;
1533
  $time = current_time( 'mysql' );
1538
  }
1539
 
1540
  if ( ! $this->does_file_exist( $filename, $time ) ) {
1541
+ // File doesn't exist locally or on provider, return it.
1542
  return $filename;
1543
  }
1544
 
1581
  return true;
1582
  }
1583
 
1584
+ if ( ! $this->get_setting( 'object-versioning' ) && $this->does_file_exist_provider( $filename, $time ) ) {
1585
  return true;
1586
  }
1587
 
1618
  }
1619
 
1620
  /**
1621
+ * Does file exist provider
1622
  *
1623
  * @param string $filename
1624
  * @param string $time
1625
  *
1626
  * @return bool
1627
+ * @throws Exception
1628
  */
1629
+ function does_file_exist_provider( $filename, $time ) {
1630
  $bucket = $this->get_setting( 'bucket' );
1631
  $region = $this->get_setting( 'region' );
1632
 
1634
  return false;
1635
  }
1636
 
1637
+ $provider_client = $this->get_provider_client( $region );
1638
+ $prefix = AS3CF_Utils::trailingslash_prefix( $this->get_object_prefix() );
1639
+ $prefix .= AS3CF_Utils::trailingslash_prefix( $this->get_dynamic_prefix( $time ) );
1640
 
1641
+ return $provider_client->does_object_exist( $bucket, $prefix . $filename );
1642
  }
1643
 
1644
  /**
1663
  }
1664
 
1665
  /**
1666
+ * Get attachment provider info
1667
  *
1668
  * @param int $post_id
1669
  *
1670
  * @return mixed
1671
  */
1672
+ public function get_attachment_provider_info( $post_id ) {
1673
+ $provider_object = get_post_meta( $post_id, 'amazonS3_info', true );
1674
 
1675
+ if ( is_array( $provider_object ) ) {
1676
+ $provider_object = array_merge( array(
1677
+ 'provider' => static::$default_provider,
1678
+ 'region' => null,
1679
+ ), $provider_object );
1680
  }
1681
 
1682
+ $provider_object = apply_filters( 'as3cf_get_attachment_s3_info', $provider_object, $post_id ); // Backwards compatibility
1683
+
1684
+ return apply_filters( 'as3cf_get_attachment_provider_info', $provider_object, $post_id );
1685
  }
1686
 
1687
  /**
1688
  * Check the plugin is correctly setup
1689
  *
1690
+ * @param bool $with_credentials Do provider credentials need to be set up too? Defaults to false.
1691
  *
1692
  * @return bool
1693
  */
1694
  function is_plugin_setup( $with_credentials = false ) {
1695
+ if ( $with_credentials && $this->get_provider()->needs_access_keys() ) {
1696
  // AWS not configured
1697
  return false;
1698
  }
1712
  }
1713
 
1714
  /**
1715
+ * Generate a link to download a file from Amazon provider using query string
1716
  * authentication. This link is only valid for a limited amount of time.
1717
  *
1718
  * @param int $post_id Post ID of the attachment
1738
  *
1739
  * @return string
1740
  */
1741
+ function get_url_scheme( $use_ssl = null ) {
1742
  if ( $this->use_ssl( $use_ssl ) ) {
1743
  $scheme = 'https';
1744
  } else {
1755
  *
1756
  * @return bool
1757
  */
1758
+ public function use_ssl( $use_ssl = null ) {
1759
  if ( is_ssl() ) {
1760
  $use_ssl = true;
1761
  }
1805
  }
1806
 
1807
  /**
1808
+ * Get the url of the file from Amazon provider
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1809
  *
1810
  * @param int $post_id Post ID of the attachment
1811
  * @param int|null $expires Seconds for the link to live
1816
  * Useful for the EDD and Woo addons to not break download URLs when the
1817
  * option is disabled.
1818
  *
1819
+ * @return bool|mixed|WP_Error
1820
  */
1821
  public function get_attachment_url( $post_id, $expires = null, $size = null, $meta = null, $headers = array(), $skip_rewrite_check = false ) {
1822
+ if ( ! ( $provider_object = $this->is_attachment_served_by_provider( $post_id, $skip_rewrite_check ) ) ) {
1823
  return false;
1824
  }
1825
 
1826
+ $url = $this->get_attachment_provider_url( $post_id, $provider_object, $expires, $size, $meta, $headers );
1827
 
1828
  return apply_filters( 'as3cf_wp_get_attachment_url', $url, $post_id );
1829
  }
1894
  }
1895
 
1896
  /**
1897
+ * Get the provider URL for an attachment
1898
  *
1899
  * @param int $post_id
1900
+ * @param array $provider_object
1901
  * @param null|int $expires
1902
  * @param null|string|array $size
1903
  * @param null|array $meta
1905
  *
1906
  * @return mixed|WP_Error
1907
  */
1908
+ public function get_attachment_provider_url( $post_id, $provider_object, $expires = null, $size = null, $meta = null, $headers = array() ) {
1909
+ $scheme = $this->get_url_scheme();
1910
 
1911
+ // We don't use $this->get_provider_object_region() here because we don't want
1912
  // to make an AWS API call and slow down page loading
1913
+ if ( isset( $provider_object['region'] ) && ( $this->get_provider()->region_required() || $this->get_provider()->get_default_region() !== $provider_object['region'] ) ) {
1914
+ $region = $this->get_provider()->sanitize_region( $provider_object['region'] );
1915
  } else {
1916
  $region = '';
1917
  }
1920
 
1921
  // Force use of secured URL when ACL has been set to private
1922
  if ( is_null( $expires ) ) {
1923
+ if ( is_null( $size ) && isset( $provider_object['acl'] ) && $this->get_provider()->get_private_acl() === $provider_object['acl'] ) {
1924
  // Full size URL private
1925
  $expires = self::DEFAULT_EXPIRES;
1926
  }
1927
 
1928
+ if ( ! is_null( $size ) && isset( $provider_object['sizes'][ $size ]['acl'] ) && $this->get_provider()->get_private_acl() === $provider_object['sizes'][ $size ]['acl'] ) {
1929
  // Alternative size URL private
1930
  $expires = self::DEFAULT_EXPIRES;
1931
  }
1941
  }
1942
 
1943
  if ( ! empty( $meta ) && isset( $meta['sizes'][ $size ]['file'] ) ) {
1944
+ $size_prefix = dirname( $provider_object['key'] );
1945
  $size_file_prefix = ( '.' === $size_prefix ) ? '' : $size_prefix . '/';
1946
 
1947
+ $provider_object['key'] = $size_file_prefix . $meta['sizes'][ $size ]['file'];
1948
  }
1949
  }
1950
 
1951
  if ( ! is_null( $expires ) && $this->is_plugin_setup( true ) ) {
1952
  try {
1953
  $expires = time() + apply_filters( 'as3cf_expires', $expires );
1954
+ $secure_url = $this->get_provider_client( $region )
1955
+ ->get_object_url( $provider_object['bucket'], $provider_object['key'], $expires, $headers );
1956
 
1957
+ return apply_filters( 'as3cf_get_attachment_secure_url', $secure_url, $provider_object, $post_id, $expires, $headers );
1958
  } catch ( Exception $e ) {
1959
  return new WP_Error( 'exception', $e->getMessage() );
1960
  }
1961
  }
1962
 
1963
+ $provider_object['key'] = $this->maybe_update_cloudfront_path( $provider_object['key'] );
1964
 
1965
+ $domain_bucket = $this->get_provider()->get_url_domain( $provider_object['bucket'], $region, $expires );
1966
+ $file = $this->encode_filename_in_path( $provider_object['key'] );
1967
  $url = $scheme . '://' . $domain_bucket . '/' . $file;
1968
 
1969
+ return apply_filters( 'as3cf_get_attachment_url', $url, $provider_object, $post_id, $expires, $headers );
1970
  }
1971
 
1972
  /**
1975
  * @param string $url
1976
  * @param int $post_id
1977
  *
1978
+ * @return bool|mixed|WP_Error
1979
  */
1980
  public function wp_get_attachment_url( $url, $post_id ) {
1981
  $new_url = $this->get_attachment_url( $post_id );
2003
  * @return string
2004
  */
2005
  public function maybe_encode_get_image_tag( $html, $id, $alt, $title, $align, $size ) {
2006
+ if ( ! ( $provider_object = $this->is_attachment_served_by_provider( $id ) ) ) {
2007
+ // Not served by provider, return
2008
  return $html;
2009
  }
2010
 
2020
  }
2021
 
2022
  $img_src = $matches[1];
2023
+ $new_img_src = $this->maybe_sign_intermediate_size( $img_src, $id, $size, $provider_object );
2024
  $new_img_src = $this->encode_filename_in_path( $new_img_src );
2025
 
2026
  return str_replace( $img_src, $new_img_src, $html );
2037
  * @return array
2038
  */
2039
  public function maybe_encode_wp_get_attachment_image_src( $image, $attachment_id, $size, $icon ) {
2040
+ if ( ! ( $provider_object = $this->is_attachment_served_by_provider( $attachment_id ) ) ) {
2041
+ // Not served by provider, return
2042
  return $image;
2043
  }
2044
 
2045
  if ( isset( $image[0] ) ) {
2046
+ $url = $this->maybe_sign_intermediate_size( $image[0], $attachment_id, $size, $provider_object );
2047
  $url = $this->encode_filename_in_path( $url );
2048
 
2049
  $image[0] = $url;
2062
  * @return array
2063
  */
2064
  public function maybe_encode_wp_prepare_attachment_for_js( $response, $attachment, $meta ) {
2065
+ if ( ! ( $provider_object = $this->is_attachment_served_by_provider( $attachment->ID ) ) ) {
2066
+ // Not served by provider, return
2067
  return $response;
2068
  }
2069
 
2073
 
2074
  if ( isset( $response['sizes'] ) && is_array( $response['sizes'] ) ) {
2075
  foreach ( $response['sizes'] as $size => $value ) {
2076
+ $url = $this->maybe_sign_intermediate_size( $value['url'], $attachment->ID, $size, $provider_object );
2077
  $url = $this->encode_filename_in_path( $url );
2078
 
2079
  $response['sizes'][ $size ]['url'] = $url;
2093
  * @return array
2094
  */
2095
  public function maybe_encode_image_get_intermediate_size( $data, $post_id, $size ) {
2096
+ if ( ! ( $provider_object = $this->is_attachment_served_by_provider( $post_id ) ) ) {
2097
+ // Not served by provider, return
2098
  return $data;
2099
  }
2100
 
2101
  if ( isset( $data['url'] ) ) {
2102
+ $url = $this->maybe_sign_intermediate_size( $data['url'], $post_id, $size, $provider_object );
2103
  $url = $this->encode_filename_in_path( $url );
2104
 
2105
  $data['url'] = $url;
2114
  * @param string $url
2115
  * @param int $attachment_id
2116
  * @param string|array $size
2117
+ * @param bool|array $provider_object
2118
  *
2119
  * @return mixed|WP_Error
2120
  */
2121
+ protected function maybe_sign_intermediate_size( $url, $attachment_id, $size, $provider_object = false ) {
2122
+ if ( ! $provider_object ) {
2123
+ $provider_object = $this->get_attachment_provider_info( $attachment_id );
2124
  }
2125
 
2126
  $size = $this->maybe_convert_size_to_string( $attachment_id, $size );
2127
 
2128
+ if ( isset( $provider_object['sizes'][ $size ] ) ) {
2129
  // Private file, add AWS signature if required
2130
+ return $this->get_attachment_provider_url( $attachment_id, $provider_object, null, $size );
2131
  }
2132
 
2133
  return $url;
2198
  }
2199
 
2200
  /**
2201
+ * Is attachment served by provider.
2202
  *
2203
+ * @param int $attachment_id
2204
+ * @param bool $skip_rewrite_check Still check if offloaded even if not currently rewriting URLs? Default: false
2205
+ * @param bool $skip_current_provider_check Skip checking if offloaded to current provider. Default: false, negated if $provider supplied
2206
+ * @param Provider|null $provider Provider where attachment expected to be offloaded to. Default: currently configured provider
2207
  *
2208
  * @return bool|array
2209
  */
2210
+ public function is_attachment_served_by_provider( $attachment_id, $skip_rewrite_check = false, $skip_current_provider_check = false, Provider $provider = null ) {
2211
  if ( ! $skip_rewrite_check && ! $this->get_setting( 'serve-from-s3' ) ) {
2212
+ // Not serving provider URLs
2213
+ return false;
2214
+ }
2215
+
2216
+ if ( ! ( $provider_object = $this->get_attachment_provider_info( $attachment_id ) ) ) {
2217
+ // File not uploaded to a provider
2218
  return false;
2219
  }
2220
 
2221
+ if ( ! $skip_current_provider_check && empty( $provider ) ) {
2222
+ $provider = $this->get_provider();
2223
+ }
2224
+
2225
+ if ( ! empty( $provider ) && $provider::get_provider_key_name() !== $provider_object['provider'] ) {
2226
+ // File not uploaded to required provider
2227
  return false;
2228
  }
2229
 
2230
+ return $provider_object;
2231
  }
2232
 
2233
  /**
2296
  }
2297
 
2298
  /**
2299
+ * Allow processes to update the file on provider via update_attached_file()
2300
  *
2301
  * @param string $file
2302
  * @param int $attachment_id
2308
  return $file;
2309
  }
2310
 
2311
+ if ( ! ( $provider_object = $this->get_attachment_provider_info( $attachment_id ) ) ) {
2312
  return $file;
2313
  }
2314
 
2315
+ $file = apply_filters( 'as3cf_update_attached_file', $file, $attachment_id, $provider_object );
2316
 
2317
  return $file;
2318
  }
2319
 
2320
  /**
2321
+ * Return the provider URL when the local file is missing
2322
  * unless we know the calling process is and we are happy
2323
  * to copy the file back to the server to be used
2324
  *
2328
  * @return string
2329
  */
2330
  function get_attached_file( $file, $attachment_id ) {
2331
+ if ( file_exists( $file ) || ! ( $provider_object = $this->is_attachment_served_by_provider( $attachment_id ) ) ) {
2332
  return $file;
2333
  }
2334
 
2335
  $url = $this->get_attachment_url( $attachment_id );
2336
 
2337
  // return the URL by default
2338
+ $file = apply_filters( 'as3cf_get_attached_file', $url, $file, $attachment_id, $provider_object );
2339
 
2340
  return $file;
2341
  }
2381
  return true;
2382
  }
2383
 
2384
+ /**
2385
+ * Returns cleaned up region name or kills ajax request if missing.
2386
+ *
2387
+ * @param bool $region_required
2388
+ *
2389
+ * @return string
2390
+ */
2391
+ function ajax_check_region( $region_required = false ) {
2392
+ $region = '';
2393
+
2394
+ // Are we defining the region or specifying via the form?
2395
+ if ( defined( 'AS3CF_REGION' ) ) {
2396
+ $region = AS3CF_REGION;
2397
+ } elseif ( false !== $this->get_defined_setting( 'region', false ) ) {
2398
+ $region = $this->get_defined_setting( 'region' );
2399
+ } elseif (
2400
+ ( ! isset( $_POST['region'] ) || ! ( $region = sanitize_text_field( $_POST['region'] ) ) ) &&
2401
+ $region_required // It's very important that this test is after the above inline assign!
2402
+ ) { // input var okay
2403
+ $out = array( 'error' => __( 'No region provided.', 'amazon-s3-and-cloudfront' ) );
2404
+
2405
+ $this->end_ajax( $out );
2406
+ }
2407
+
2408
+ return $region;
2409
+ }
2410
+
2411
+ /**
2412
+ * Returns cleaned up bucket name or kills ajax request if missing.
2413
+ *
2414
+ * @return string
2415
+ */
2416
  function ajax_check_bucket() {
2417
  if ( ! isset( $_POST['bucket_name'] ) || ! ( $bucket = sanitize_text_field( $_POST['bucket_name'] ) ) ) { // input var okay
2418
  $out = array( 'error' => __( 'No bucket name provided.', 'amazon-s3-and-cloudfront' ) );
2424
  }
2425
 
2426
  /**
2427
+ * Handler for AJAX callback to create a bucket in provider
2428
+ *
2429
+ * @throws Exception
2430
  */
2431
  function ajax_create_bucket() {
2432
  $this->verify_ajax_request();
2433
 
2434
+ $region = $this->ajax_check_region( true );
2435
  $bucket = $this->ajax_check_bucket();
2436
 
 
 
 
 
 
 
 
 
2437
  $result = $this->create_bucket( $bucket, $region );
2438
+
2439
  if ( is_wp_error( $result ) ) {
2440
  $out = $this->prepare_bucket_error( $result, false );
2441
 
2456
  * Create an S3 bucket
2457
  *
2458
  * @param string $bucket_name
2459
+ * @param bool|string $region option location constraint
2460
  *
2461
  * @return bool|WP_Error
2462
  */
2463
+ function create_bucket( $bucket_name, $region = false ) {
2464
  try {
2465
  $args = array( 'Bucket' => $bucket_name );
2466
 
2469
  $region = AS3CF_REGION;
2470
  }
2471
 
2472
+ if ( ! is_null( $region ) && $this->get_provider()->get_default_region() !== $region ) {
2473
  $args['LocationConstraint'] = $region;
2474
  }
2475
 
2476
+ $this->get_provider_client( $region )->create_bucket( $args );
2477
  } catch ( Exception $e ) {
2478
  return new WP_Error( 'exception', $e->getMessage() );
2479
  }
2483
 
2484
  /**
2485
  * Handler for AJAX callback to save the selection of a bucket
2486
+ *
2487
+ * @throws Exception
2488
  */
2489
  function ajax_save_bucket() {
2490
  $this->verify_ajax_request();
2491
 
2492
+ $region = $this->ajax_check_region( $this->get_provider()->region_required() );
2493
  $bucket = $this->ajax_check_bucket();
2494
 
2495
  $manual = false;
2498
  $manual = true;
2499
  }
2500
 
2501
+ $this->save_bucket_for_ajax( $bucket, $manual, $region );
2502
  }
2503
 
2504
  /**
2508
  * @param bool|false $manual_select
2509
  * @param null|string $region
2510
  * @param array $defaults
2511
+ *
2512
+ * @throws Exception
2513
  */
2514
  function save_bucket_for_ajax( $bucket, $manual_select = false, $region = null, $defaults = array() ) {
2515
  $region = $this->save_bucket( $bucket, $manual_select, $region );
2516
 
2517
  if ( ! is_wp_error( $region ) ) {
2518
  $out = array(
2519
+ 'success' => '1',
2520
+ 'region' => $region,
2521
+ 'region_name' => $this->get_provider()->get_region_name( $region ),
2522
  );
2523
 
2524
  $out = wp_parse_args( $out, $defaults );
2585
 
2586
  $this->set_setting( 'bucket', $bucket_name );
2587
 
2588
+ if ( empty( $region ) ) {
2589
  // retrieve the bucket region if not supplied
2590
  $region = $this->get_bucket_region( $bucket_name );
2591
  if ( is_wp_error( $region ) ) {
2593
  }
2594
  }
2595
 
2596
+ if ( ! $this->get_provider()->region_required() && $this->get_provider()->get_default_region() === $region ) {
2597
  $region = '';
2598
  }
2599
 
2653
  * @return string
2654
  */
2655
  public function get_default_region() {
2656
+ return $this->get_provider()->get_default_region();
2657
  }
2658
 
2659
  /**
2660
  * Get the S3 client
2661
  *
2662
  * @param bool|string $region specify region to client for signature
2663
+ * @param bool $force force return of new provider client when swapping regions
2664
  *
2665
  * @return Provider|Null_Provider
2666
+ * @throws Exception
2667
  */
2668
+ public function get_provider_client( $region = false, $force = false ) {
2669
+ if ( is_null( $this->provider_client ) ||
2670
+ is_null( $this->provider_client_region ) ||
2671
  $force ||
2672
+ ( false !== $region && $this->provider_client_region !== $region ) ) {
2673
  $args = array();
2674
 
2675
  if ( $force ) {
2676
+ $this->set_provider();
2677
  }
2678
 
2679
  if ( $region ) {
2680
+ $args['region'] = $this->get_provider()->sanitize_region( $region );
2681
  }
2682
 
2683
+ $provider_client_region = isset( $args['region'] ) ? $args['region'] : $region;
2684
 
2685
  try {
2686
+ $this->set_client( $this->get_provider()->get_client( $args ), $provider_client_region );
2687
+ } catch ( Exception $e ) {
2688
  AS3CF_Error::log( $e->getMessage() );
2689
  $this->set_client( new Null_Provider );
2690
  }
2691
  }
2692
 
2693
+ return $this->provider_client;
2694
  }
2695
 
2696
  /**
2697
+ * Setter for Provider client
2698
  *
2699
  * @param Provider|Null_Provider $client
2700
  * @param bool|string $region
2701
  */
2702
  public function set_client( $client, $region = false ) {
2703
+ $this->provider_client = $client;
2704
 
2705
  if ( false !== $region ) {
2706
+ $this->provider_client_region = $region;
2707
  }
2708
  }
2709
 
2727
  }
2728
 
2729
  try {
2730
+ $region = $this->get_provider_client( false, true )->get_bucket_location( array( 'Bucket' => $bucket ) );
2731
  } catch ( Exception $e ) {
2732
  $error_msg_title = '<strong>' . __( 'Error Getting Bucket Region', 'amazon-s3-and-cloudfront' ) . '</strong> &mdash;';
2733
  $error_msg = sprintf( __( 'There was an error attempting to get the region of the bucket %s: %s', 'amazon-s3-and-cloudfront' ), $bucket, $e->getMessage() );
2736
  return new WP_Error( 'exception', $error_msg_title . $error_msg );
2737
  }
2738
 
2739
+ $region = $this->get_provider()->sanitize_region( $region );
2740
 
2741
  if ( is_string( $region ) ) {
2742
  $regions[ $bucket ] = $region;
2747
  }
2748
 
2749
  /**
2750
+ * Get the region of the bucket stored in the provider metadata.
2751
  *
2752
  *
2753
+ * @param array $provider_object
2754
+ * @param int $post_id - if supplied will update the provider meta if no region found
2755
  *
2756
  * @return string|WP_Error - region name
2757
  */
2758
+ function get_provider_object_region( $provider_object, $post_id = null ) {
2759
+ if ( ! isset( $provider_object['region'] ) ) {
2760
+ // if region hasn't been stored in the provider metadata retrieve using the bucket
2761
+ $region = $this->get_bucket_region( $provider_object['bucket'], true );
2762
  if ( is_wp_error( $region ) ) {
2763
  return $region;
2764
  }
2765
 
2766
+ $provider_object['region'] = $region;
2767
 
2768
  if ( ! is_null( $post_id ) ) {
2769
+ // retrospectively update provider metadata with region
2770
+ update_post_meta( $post_id, 'amazonS3_info', $provider_object );
2771
  }
2772
  }
2773
 
2774
+ return $provider_object['region'];
2775
  }
2776
 
2777
  /**
2780
  function ajax_get_buckets() {
2781
  $this->verify_ajax_request();
2782
 
2783
+ $region = $this->ajax_check_region( $this->get_provider()->region_required() );
2784
+
2785
+ $result = $this->get_buckets( $region );
2786
+
2787
  if ( is_wp_error( $result ) ) {
2788
  $out = $this->prepare_bucket_error( $result, false );
2789
  } else {
2799
  /**
2800
  * Get a list of buckets from S3
2801
  *
2802
+ * @param bool $region
2803
+ *
2804
  * @return array|WP_Error - list of buckets
2805
  */
2806
+ function get_buckets( $region = false ) {
2807
  try {
2808
+ $result = $this->get_provider_client( $region )->list_buckets();
2809
  } catch ( Exception $e ) {
2810
  return new WP_Error( 'exception', $e->getMessage() );
2811
  }
2820
  * @param string $region
2821
  *
2822
  * @return bool|WP_Error
2823
+ * @throws Exception
2824
  */
2825
  function check_write_permission( $bucket = null, $region = null ) {
2826
+ if ( $this->get_provider()->needs_access_keys() ) {
2827
  // If no access keys set then no need check.
2828
  return false;
2829
  }
2851
  $key = $this->get_file_prefix() . 'as3cf-permission-check.txt';
2852
  $file_contents = __( 'This is a test file to check if the user has write permission to S3. Delete me if found.', 'amazon-s3-and-cloudfront' );
2853
 
2854
+ $can_write = $this->get_provider_client( $region, true )->can_write( $bucket, $key, $file_contents );
2855
 
2856
  // If we get back an unexpected error message, throw an error.
2857
  if ( is_string( $can_write ) ) {
2894
  wp_register_script( 'as3cf-modal', $src, array( 'jquery' ), $version, true );
2895
  }
2896
 
2897
+ /**
2898
+ * Register storage provider scripts and styles so they can be enqueued later
2899
+ */
2900
+ function register_storage_provider_assets() {
2901
+ $version = $this->get_asset_version();
2902
+ $suffix = $this->get_asset_suffix();
2903
+
2904
+ $src = plugins_url( 'assets/css/storage-provider.css', $this->plugin_file_path );
2905
+ wp_register_style( 'as3cf-storage-provider', $src, array(), $version );
2906
+
2907
+ $src = plugins_url( 'assets/js/storage-provider' . $suffix . '.js', $this->plugin_file_path );
2908
+ wp_register_script( 'as3cf-storage-provider', $src, array( 'jquery' ), $version, true );
2909
+ }
2910
+
2911
  /**
2912
  * On plugin load.
2913
  */
2924
 
2925
  add_action( 'network_admin_notices', array( $this, 'settings_saved_notice' ) );
2926
 
2927
+ $this->enqueue_style( 'as3cf-styles', 'assets/css/styles', array( 'as3cf-modal', 'as3cf-storage-provider' ) );
2928
+ $this->enqueue_script( 'as3cf-script', 'assets/js/script', array( 'jquery', 'underscore', 'as3cf-modal', 'as3cf-storage-provider' ) );
2929
 
2930
  wp_localize_script( 'as3cf-script',
2931
  'as3cf',
2932
  array(
2933
+ 'strings' => array(
2934
  'create_bucket_error' => __( 'Error creating bucket', 'amazon-s3-and-cloudfront' ),
2935
  'create_bucket_name_short' => __( 'Bucket name too short.', 'amazon-s3-and-cloudfront' ),
2936
  'create_bucket_name_long' => __( 'Bucket name too long.', 'amazon-s3-and-cloudfront' ),
2945
  // Mimic WP Core's notice text, therefore no translation needed here.
2946
  'settings_saved' => __( 'Settings saved.' ),
2947
  ),
2948
+ 'nonces' => array(
2949
  'create_bucket' => wp_create_nonce( 'as3cf-create-bucket' ),
2950
  'manual_bucket' => wp_create_nonce( 'as3cf-manual-save-bucket' ),
2951
  'get_buckets' => wp_create_nonce( 'as3cf-get-buckets' ),
2955
  'aws_keys_set' => wp_create_nonce( 'as3cf-aws-keys-set' ),
2956
  'aws_keys_remove' => wp_create_nonce( 'as3cf-aws-keys-remove' ),
2957
  ),
2958
+ 'is_pro' => $this->is_pro(),
2959
+ 'provider_console_url' => $this->get_provider()->get_console_url(),
2960
+ 'provider_console_url_param' => $this->get_provider()->get_console_url_param(),
2961
  )
2962
  );
2963
 
2975
  */
2976
  function get_settings_whitelist() {
2977
  return array(
2978
+ 'provider',
2979
+ 'access-key-id',
2980
+ 'secret-access-key',
2981
  'bucket',
2982
  'region',
2983
  'domain',
3025
  $post_vars = $this->get_settings_whitelist();
3026
 
3027
  foreach ( $post_vars as $var ) {
3028
+ // Special case for when Secret Access Key is not changed.
3029
+ if ( 'secret-access-key' === $var && ! empty( $_POST['secret-access-key'] ) && _x( '-- not shown --', 'placeholder for hidden secret access key, 39 char max', 'amazon-s3-and-cloudfront' ) === $_POST['secret-access-key'] ) {
3030
+ continue;
3031
+ }
3032
+
3033
  $this->remove_setting( $var );
3034
 
3035
  if ( ! isset( $_POST[ $var ] ) ) { // input var okay
3071
  */
3072
  function get_settings_tabs() {
3073
  $tabs = array(
3074
+ 'media' => _x( 'Media Library', 'Show the media library tab', 'amazon-s3-and-cloudfront' ),
3075
+ 'addons' => _x( 'Addons', 'Show the addons tab', 'amazon-s3-and-cloudfront' ),
3076
+ 'support' => _x( 'Support', 'Show the support tab', 'amazon-s3-and-cloudfront' ),
 
3077
  );
3078
 
3079
  return apply_filters( 'as3cf_settings_tabs', $tabs );
3239
  return true;
3240
  }
3241
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3242
  /**
3243
  * Apply ACL to an attachment and associated files
3244
  *
3245
  * @param int $post_id
3246
+ * @param array $provider_object
3247
  * @param string $acl
3248
  *
3249
  * @return array|bool|WP_Error
3250
  */
3251
+ public function set_attachment_acl_on_provider( $post_id, $provider_object, $acl ) {
3252
  // Return early if already set to the desired ACL
3253
+ if ( isset( $provider_object['acl'] ) && $acl === $provider_object['acl'] ) {
3254
  return false;
3255
  }
3256
 
3257
  $args = array(
3258
  'ACL' => $acl,
3259
+ 'Bucket' => $provider_object['bucket'],
3260
+ 'Key' => $provider_object['key'],
3261
  );
3262
 
3263
+ $region = ( isset( $provider_object['region'] ) ) ? $provider_object['region'] : false;
3264
+ $provider_client = $this->get_provider_client( $region, true );
3265
 
3266
  try {
3267
+ $provider_client->update_object_acl( $args );
3268
+ $provider_object['acl'] = $acl;
3269
 
3270
  // update S3 meta data
3271
+ if ( $acl == $this->get_provider()->get_default_acl() ) {
3272
+ unset( $provider_object['acl'] );
3273
  }
3274
 
3275
+ update_post_meta( $post_id, 'amazonS3_info', $provider_object );
3276
  } catch ( Exception $e ) {
3277
+ $msg = 'Error setting ACL to ' . $acl . ' for ' . $provider_object['key'] . ': ' . $e->getMessage();
3278
  AS3CF_Error::log( $msg );
3279
 
3280
  return new WP_Error( 'acl_exception', $msg );
3281
  }
3282
 
3283
+ return $provider_object;
3284
  }
3285
 
3286
  /**
3287
  * Make admin notice for when object ACL has changed
3288
  *
3289
+ * @param array $provider_object
3290
  */
3291
+ function make_acl_admin_notice( $provider_object ) {
3292
+ $filename = wp_basename( $provider_object['key'] );
3293
+ $acl = ( isset( $provider_object['acl'] ) ) ? $provider_object['acl'] : $this->get_provider()->get_default_acl();
3294
  $acl_name = $this->get_acl_display_name( $acl );
3295
+ $text = sprintf( __( '<strong>WP Offload Media</strong> &mdash; The file %s has been given %s permissions in the bucket.', 'amazon-s3-and-cloudfront' ), "<strong>{$filename}</strong>", "<strong>{$acl_name}</strong>" );
3296
 
3297
  $this->notices->add_notice( $text );
3298
  }
3311
 
3312
  if ( ! $gd_enabled && ! $imagick_enabled ) {
3313
  $this->notices->add_notice(
3314
+ __( '<strong>WP Offload Media Requirement Missing</strong> &mdash; Looks like you don\'t have an image manipulation library installed on this server and configured with PHP. You may run into trouble if you try to edit images. Please setup GD or ImageMagick.', 'amazon-s3-and-cloudfront' ),
3315
  array( 'flash' => false, 'only_show_to_user' => false, 'only_show_in_settings' => true )
3316
  );
3317
  }
3436
  $output .= esc_html( get_locale() );
3437
  $output .= "\r\n";
3438
 
3439
+ $output .= 'Organize offloads by month/year: ';
3440
  $output .= esc_html( get_option( 'uploads_use_yearmonth_folders' ) ? 'Enabled' : 'Disabled' );
3441
  $output .= "\r\n";
3442
 
3557
  $output .= number_format_i18n( $media_counts['all'] );
3558
  $output .= "\r\n";
3559
 
3560
+ $output .= 'Offloaded Media Files: ';
3561
  $output .= number_format_i18n( $media_counts['s3'] );
3562
  $output .= "\r\n";
3563
 
3596
  $output .= esc_html( ( defined( 'AWS_USE_EC2_IAM_ROLE' ) ) ? AWS_USE_EC2_IAM_ROLE : 'Not defined' );
3597
  $output .= "\r\n";
3598
 
3599
+ $output .= 'AS3CF_PROVIDER: ';
3600
+ $output .= esc_html( ( defined( 'AS3CF_PROVIDER' ) ) ? AS3CF_PROVIDER : 'Not defined' );
3601
+ $output .= "\r\n";
3602
+
3603
  $output .= 'AS3CF_BUCKET: ';
3604
  $output .= esc_html( ( defined( 'AS3CF_BUCKET' ) ) ? AS3CF_BUCKET : 'Not defined' );
3605
  $output .= "\r\n";
3617
  $output .= $region;
3618
  }
3619
  $output .= "\r\n";
3620
+ $output .= 'Copy Files to Bucket: ';
3621
  $output .= $this->on_off( 'copy-to-s3' );
3622
  $output .= "\r\n";
3623
  $output .= 'Rewrite File URLs: ';
3628
  $output .= "Local URL:\r\n";
3629
  $output .= $this->get_local_url_preview( $escape );
3630
  $output .= "\r\n";
3631
+ $output .= "Offload URL:\r\n";
3632
  $output .= $this->get_url_preview( $escape );
3633
  $output .= "\r\n";
3634
  $output .= "\r\n";
3938
  * @return string
3939
  */
3940
  function get_access_denied_notice_message( $single = true ) {
3941
+ if ( $this->get_provider()->needs_access_keys() ) {
3942
+ return sprintf( __( '<a href="%s">Define your access keys</a> to enable write access to the bucket', 'amazon-s3-and-cloudfront' ), '#settings' );
3943
  }
3944
 
3945
+ $url = $this->dbrains_url( '/wp-offload-media/doc/quick-start-guide/', array(
3946
  'utm_campaign' => 'error+messages',
3947
  ), 'bucket-restrictions' );
3948
 
3970
  // Sum the total file size (including image sizes) for all S3 attachments
3971
  $sql = "SELECT SUM( meta_value ) AS bytes_total
3972
  FROM {$wpdb->postmeta}
3973
+ WHERE meta_key = 'as3cf_filesize_total'";
3974
 
3975
  $space_used = $wpdb->get_var( $sql );
3976
 
4036
  * Count attachments on a site
4037
  *
4038
  * @param string $prefix
4039
+ * @param null|bool $uploaded_to_provider
4040
  * null - All attachments
4041
  * true - Attachments only uploaded to S3
4042
  * false - Attachments not uploaded to S3
4043
  *
4044
  * @return int
4045
  */
4046
+ public function count_attachments( $prefix, $uploaded_to_provider = null ) {
4047
  global $wpdb;
4048
 
4049
  $sql = "SELECT COUNT(DISTINCT p.ID)
4051
 
4052
  $where = "WHERE p.post_type = 'attachment'";
4053
 
4054
+ if ( ! is_null( $uploaded_to_provider ) && is_bool( $uploaded_to_provider ) ) {
4055
  $sql .= " LEFT OUTER JOIN `{$prefix}postmeta` pm
4056
  ON p.`ID` = pm.`post_id`
4057
  AND pm.`meta_key` = 'amazonS3_info'";
4058
 
4059
+ $operator = $uploaded_to_provider ? 'not ' : '';
4060
  $where .= " AND pm.`post_id` is {$operator}null";
4061
  }
4062
 
4071
  * @return array
4072
  */
4073
  protected function diagnostic_media_counts() {
4074
+ if ( false === ( $attachment_counts = get_site_transient( 'as3cf_attachment_counts' ) ) ) {
4075
+ $table_prefixes = $this->get_all_blog_table_prefixes();
4076
+ $all_media = 0;
4077
+ $all_media_provider = 0;
4078
 
4079
  foreach ( $table_prefixes as $blog_id => $table_prefix ) {
4080
+ $count = $this->count_attachments( $table_prefix );
4081
+ $all_media += $count;
4082
+ $provider_count = $this->count_attachments( $table_prefix, true );
4083
+ $all_media_provider += $provider_count;
4084
  }
4085
 
4086
  $attachment_counts = array(
4087
  'all' => $all_media,
4088
+ 's3' => $all_media_provider,
4089
  );
4090
 
4091
+ set_site_transient( 'as3cf_attachment_counts', $attachment_counts, 2 * MINUTE_IN_SECONDS );
4092
  }
4093
 
4094
  return $attachment_counts;
4100
  function plugin_deactivated_notice() {
4101
  if ( false !== ( $deactivated_notice_id = get_transient( 'as3cf_deactivated_notice_id' ) ) ) {
4102
  if ( '1' === $deactivated_notice_id ) {
4103
+ $title = __( 'WP Offload Media Activation', 'amazon-s3-and-cloudfront' );
4104
+ $message = __( "WP Offload Media Lite and WP Offload Media cannot both be active. We've automatically deactivated WP Offload Media Lite.", 'amazon-s3-and-cloudfront' );
4105
  } else {
4106
+ $title = __( 'WP Offload Media Lite Activation', 'amazon-s3-and-cloudfront' );
4107
+ $message = __( "WP Offload Media Lite and WP Offload Media cannot both be active. We've automatically deactivated WP Offload Media.", 'amazon-s3-and-cloudfront' );
4108
  }
4109
 
4110
  $message = sprintf( '<strong>%s</strong> &mdash; %s', esc_html( $title ), esc_html( $message ) );
4171
  * @return string
4172
  */
4173
  public function settings_more_info_link( $hash, $utm_content = '' ) {
4174
+ return $this->more_info_link( '/wp-offload-media/doc/settings/', $utm_content, $hash );
4175
  }
4176
 
4177
  /**
4248
  'flash' => false,
4249
  );
4250
 
4251
+ $doc_url = $this->dbrains_url( '/wp-offload-media/doc/force-http-setting/', array(
4252
  'utm_campaign' => 'support+docs',
4253
  ) );
4254
  $doc_link = AS3CF_Utils::dbrains_link( $doc_url, __( 'this doc' ) );
4255
 
4256
+ $message = sprintf( '<strong>%s</strong> &mdash; ', __( 'WP Offload Media Feature Removed', 'amazon-s3-and-cloudfront' ) );
4257
  $message .= sprintf( __( 'You had the "Always non-SSL" option selected in your settings, but we\'ve removed this option in version 1.3. We\'ll now use HTTPS when the request is HTTPS and regular HTTP when the request is HTTP. This should work fine for your site, but please take a poke around and make sure things are working ok. See %s for more details on why we did this and how you can revert back to the old behavior.', 'amazon-s3-and-cloudfront' ), $doc_link );
4258
 
4259
  $this->notices->add_notice( $message, $notice_args );
4281
  /**
4282
  * Add the S3 meta box to the attachment screen
4283
  */
4284
+ public function attachment_provider_meta_box() {
4285
  add_meta_box(
4286
  's3-actions',
4287
+ __( 'Offload', 'amazon-s3-and-cloudfront' ),
4288
+ array( $this, 'attachment_provider_actions_meta_box' ),
4289
  'attachment',
4290
  'side',
4291
  'core'
4315
  /**
4316
  * Render the S3 attachment meta box
4317
  */
4318
+ public function attachment_provider_actions_meta_box() {
4319
  global $post;
4320
  $file = get_attached_file( $post->ID, true );
4321
 
4322
  $args = array(
4323
+ 'provider_object' => $this->get_formatted_provider_info( $post->ID ),
4324
  'post' => $post,
4325
  'local_file_exists' => file_exists( $file ),
4326
  'available_actions' => $this->get_available_media_actions( 'singular' ),
4334
  * Get ACL value string.
4335
  *
4336
  * @param array $acl
4337
+ * @param int $post_id
4338
  *
4339
  * @return string
4340
  */
4341
+ protected function get_acl_value_string( $acl, $post_id ) {
4342
  return $acl['name'];
4343
  }
4344
 
4346
  * Return a formatted S3 info with display friendly defaults
4347
  *
4348
  * @param int $id
4349
+ * @param array|null $provider_object
4350
  *
4351
  * @return array
4352
  */
4353
+ public function get_formatted_provider_info( $id, $provider_object = null ) {
4354
+ if ( is_null( $provider_object ) ) {
4355
+ if ( ! ( $provider_object = $this->get_attachment_provider_info( $id ) ) ) {
4356
  return false;
4357
  }
4358
  }
4359
 
4360
+ $provider_object['url'] = $this->get_attachment_provider_url( $id, $provider_object );
4361
 
4362
+ $acl = ( isset( $provider_object['acl'] ) ) ? $provider_object['acl'] : $this->get_provider()->get_default_acl();
4363
  $acl_info = array(
4364
  'acl' => $acl,
4365
  'name' => $this->get_acl_display_name( $acl ),
4366
  'title' => $this->get_media_action_strings( 'change_to_private' ),
4367
  );
4368
 
4369
+ if ( $this->get_provider()->get_private_acl() === $acl ) {
4370
  $acl_info['title'] = $this->get_media_action_strings( 'change_to_public' );
4371
  }
4372
 
4373
+ $provider_object['acl'] = $acl_info;
 
 
4374
 
4375
+ if ( isset( $provider_object['region'] ) ) {
4376
+ $provider_object['region'] = $this->get_provider()->get_region_name( $provider_object['region'] );
4377
  }
4378
 
4379
+ if ( ! empty( $provider_object['provider'] ) ) {
4380
+ $provider_object['provider_name'] = $this->get_provider_service_name( $provider_object['provider'] );
4381
  }
4382
 
4383
+ return $provider_object;
4384
  }
4385
 
4386
  /**
4392
  */
4393
  public function get_media_action_strings( $string = null ) {
4394
  $strings = apply_filters( 'as3cf_media_action_strings', array(
4395
+ 'provider' => _x( 'Storage Provider', 'Storage provider key name', 'amazon-s3-and-cloudfront' ),
4396
+ 'provider_name' => _x( 'Storage Provider', 'Storage provider name', 'amazon-s3-and-cloudfront' ),
4397
+ 'bucket' => _x( 'Bucket', 'Bucket name', 'amazon-s3-and-cloudfront' ),
4398
+ 'key' => _x( 'Path', 'Path to file in bucket', 'amazon-s3-and-cloudfront' ),
4399
+ 'region' => _x( 'Region', 'Location of bucket', 'amazon-s3-and-cloudfront' ),
4400
+ 'acl' => _x( 'Access', 'Access control list of the file in bucket', 'amazon-s3-and-cloudfront' ),
4401
+ 'url' => __( 'URL', 'amazon-s3-and-cloudfront' ),
4402
  ) );
4403
 
4404
  if ( ! is_null( $string ) ) {
4423
  wp_localize_script( 'as3cf-media-script', 'as3cf_media', array(
4424
  'strings' => $this->get_media_action_strings(),
4425
  'nonces' => array(
4426
+ 'get_attachment_provider_details' => wp_create_nonce( 'get-attachment-s3-details' ),
4427
  ),
4428
  ) );
4429
  }
4431
  /**
4432
  * Handle retieving the S3 details for attachment modals.
4433
  */
4434
+ public function ajax_get_attachment_provider_details() {
4435
  if ( ! isset( $_POST['id'] ) ) {
4436
  return;
4437
  }
4442
 
4443
  // get the actions available for the attachment
4444
  $data = array(
4445
+ 'links' => $this->add_media_row_actions( array(), $id ),
4446
+ 'provider_object' => $this->get_formatted_provider_info( $id ),
4447
+ 'acl_toggle' => $this->verify_media_actions() && $this->is_attachment_served_by_provider( $id, true ),
4448
  );
4449
 
4450
  wp_send_json_success( $data );
4567
  * @return string
4568
  */
4569
  public function get_acl_for_intermediate_size( $attachment_id, $size ) {
4570
+ $provider_info = $this->get_attachment_provider_info( $attachment_id );
4571
 
4572
  if ( 'original' === $size || empty( $size ) ) {
4573
+ return isset( $provider_info['acl'] ) ? $provider_info['acl'] : $this->get_provider()->get_default_acl();
4574
  }
4575
 
4576
+ if ( ! empty( $provider_info['sizes'][ $size ]['acl'] ) ) {
4577
+ return $provider_info['sizes'][ $size ]['acl'];
4578
  }
4579
 
4580
+ return $this->get_provider()->get_default_acl();
4581
  }
4582
 
4583
  /**
4623
  return array(
4624
  'amazon-s3-and-cloudfront-assets-pull' => array(
4625
  'title' => __( 'Assets Pull', 'amazon-s3-and-cloudfront' ),
4626
+ 'sub' => __( 'An addon for WP Offload Media to serve your site\'s JS, CSS, and other enqueued assets from Amazon CloudFront or another CDN.', 'amazon-s3-and-cloudfront' ),
4627
+ 'url' => $this->dbrains_url( '/wp-offload-media/doc/assets-pull-addon/', array(
4628
  'utm_campaign' => 'addons+install',
4629
  ) ),
4630
  'label' => __( 'Feature', 'amazon-s3-and-cloudfront' ),
4673
 
4674
  if ( is_plugin_active( 'amazon-web-services/amazon-web-services.php' ) ) {
4675
  $message = sprintf(
4676
+ __( '<strong>Amazon Web Services Plugin No Longer Required</strong> &mdash; As of version 1.6 of WP Offload Media, the <a href="%1$s">Amazon Web Services</a> plugin is no longer required. We have removed the dependency by bundling a small portion of the AWS SDK into WP Offload Media. As long as none of your other active plugins or themes depend on the Amazon Web Services plugin, it should be safe to deactivate and delete it. %2$s', 'amazon-s3-and-cloudfront' ),
4677
  'https://wordpress.org/plugins/amazon-web-services/',
4678
  $this->more_info_link( '/wp-offload-s3-1-6-released/', 'os3+settings+aws+active' )
4679
  );
4684
  );
4685
  $this->notices->add_notice( $message, $args );
4686
 
4687
+ if ( is_a( $this->get_provider(), '\DeliciousBrains\WP_Offload_Media\Providers\AWS_Provider' ) && $this->get_provider()->needs_access_keys() ) {
4688
  // Have access keys been defined in still active AWS plugin's database settings?
4689
  $aws_settings = get_site_option( 'aws_settings' );
4690
 
4691
  // If both AWS keys set and we already have a bucket set, safe to use the AWS keys.
4692
  if ( ! empty( $aws_settings['access_key_id'] ) && ! empty( $aws_settings['secret_access_key'] ) && false !== $this->get_setting( 'bucket' ) ) {
4693
+ $this->set_setting( 'access-key-id', $aws_settings['access_key_id'] );
4694
+ $this->set_setting( 'secret-access-key', $aws_settings['secret_access_key'] );
4695
  $this->save_settings();
4696
  }
4697
  }
4705
  */
4706
  public function handle_aws_access_key_form_header() {
4707
  $notice['message'] = sprintf(
4708
+ __( '<strong>WP Offload Media Settings Moved</strong> &mdash; You now define your AWS keys for WP Offload Media in the new <a href="%1$s">Settings tab</a>. Saving settings in the form below will have no effect on WP Offload Media. %2$s', 'amazon-s3-and-cloudfront' ),
4709
  $this->get_plugin_page_url( array( 'hash' => 'settings' ) ),
4710
  $this->more_info_link( '/wp-offload-s3-1-6-released/', 'aws+os3+access+keys+setting+moved' )
4711
  );
4749
  }
4750
  }
4751
 
4752
+ delete_post_meta( $post_id, 'as3cf_filesize_total' );
4753
 
4754
  return $data;
4755
  }
classes/as3cf-compatibility-check.php CHANGED
@@ -31,7 +31,7 @@ if ( ! class_exists( 'AS3CF_Compatibility_Check' ) ) {
31
  protected $plugin_slug;
32
 
33
  /**
34
- * @var string The name of the plugin, e.g. WP Offload S3
35
  */
36
  protected $plugin_name;
37
 
@@ -321,6 +321,7 @@ if ( ! class_exists( 'AS3CF_Compatibility_Check' ) ) {
321
  $sdk_errors = $this->get_sdk_requirements_errors();
322
  if ( ! empty( $sdk_errors ) ) {
323
  $sdk_errors = $this->get_sdk_error_msg() . $hide_notice_msg;
 
324
  return $this->set_error_msg( $sdk_errors );
325
  }
326
 
@@ -531,7 +532,7 @@ if ( ! class_exists( 'AS3CF_Compatibility_Check' ) ) {
531
  }
532
 
533
  /**
534
- * Checks if another version of WP Offload S3 (Lite) is active and deactivates it.
535
  * To be hooked on `activated_plugin` so other plugin is deactivated when current plugin is activated.
536
  *
537
  * @param string $plugin
31
  protected $plugin_slug;
32
 
33
  /**
34
+ * @var string The name of the plugin, e.g. WP Offload Media
35
  */
36
  protected $plugin_name;
37
 
321
  $sdk_errors = $this->get_sdk_requirements_errors();
322
  if ( ! empty( $sdk_errors ) ) {
323
  $sdk_errors = $this->get_sdk_error_msg() . $hide_notice_msg;
324
+
325
  return $this->set_error_msg( $sdk_errors );
326
  }
327
 
532
  }
533
 
534
  /**
535
+ * Checks if another version of WP Offload Media (Lite) is active and deactivates it.
536
  * To be hooked on `activated_plugin` so other plugin is deactivated when current plugin is activated.
537
  *
538
  * @param string $plugin
classes/as3cf-error.php CHANGED
@@ -30,7 +30,7 @@ class AS3CF_Error {
30
  * @param string $plugin_prefix
31
  */
32
  public static function log( $message, $plugin_prefix = '' ) {
33
- $prefix = 'WPOS3';
34
  if ( '' !== $plugin_prefix ) {
35
  $prefix .= '_' . $plugin_prefix;
36
  }
30
  * @param string $plugin_prefix
31
  */
32
  public static function log( $message, $plugin_prefix = '' ) {
33
+ $prefix = 'AS3CF';
34
  if ( '' !== $plugin_prefix ) {
35
  $prefix .= '_' . $plugin_prefix;
36
  }
classes/as3cf-notices.php CHANGED
@@ -68,7 +68,7 @@ class AS3CF_Notices {
68
  'only_show_to_user' => true, // The user who has initiated an action resulting in notice. Otherwise show to all users.
69
  'user_capabilities' => array( 'as3cf_compat_check', 'check_capabilities' ), // A user with these capabilities can see the notice. Can be a callback with the first array item the name of global class instance.
70
  'only_show_in_settings' => false,
71
- 'only_show_on_tab' => false, // Only show on a specific WP Offload S3 tab.
72
  'custom_id' => '',
73
  'auto_p' => true, // Automatically wrap the message in a <p>
74
  'class' => '', // Extra classes for the notice
68
  'only_show_to_user' => true, // The user who has initiated an action resulting in notice. Otherwise show to all users.
69
  'user_capabilities' => array( 'as3cf_compat_check', 'check_capabilities' ), // A user with these capabilities can see the notice. Can be a callback with the first array item the name of global class instance.
70
  'only_show_in_settings' => false,
71
+ 'only_show_on_tab' => false, // Only show on a specific WP Offload Media tab.
72
  'custom_id' => '',
73
  'auto_p' => true, // Automatically wrap the message in a <p>
74
  'class' => '', // Extra classes for the notice
classes/as3cf-plugin-base.php CHANGED
@@ -5,7 +5,11 @@ abstract class AS3CF_Plugin_Base {
5
  const DBRAINS_URL = 'https://deliciousbrains.com';
6
 
7
  const SETTINGS_KEY = '';
8
- const SETTINGS_CONSTANT = '';
 
 
 
 
9
 
10
  protected static $plugin_page = 'amazon-s3-and-cloudfront';
11
  protected $default_tab = '';
@@ -116,6 +120,15 @@ abstract class AS3CF_Plugin_Base {
116
  return $this->settings;
117
  }
118
 
 
 
 
 
 
 
 
 
 
119
  /**
120
  * Get all settings that have been defined via constant for the plugin
121
  *
@@ -124,7 +137,7 @@ abstract class AS3CF_Plugin_Base {
124
  * @return array
125
  */
126
  function get_defined_settings( $force = false ) {
127
- if ( ! defined( static::SETTINGS_CONSTANT ) ) {
128
  $this->defined_settings = array();
129
 
130
  return $this->defined_settings;
@@ -132,7 +145,7 @@ abstract class AS3CF_Plugin_Base {
132
 
133
  if ( is_null( $this->defined_settings ) || $force ) {
134
  $this->defined_settings = array();
135
- $unserialized = maybe_unserialize( constant( static::SETTINGS_CONSTANT ) );
136
  $unserialized = is_array( $unserialized ) ? $unserialized : array();
137
 
138
  foreach ( $unserialized as $key => $value ) {
@@ -157,7 +170,7 @@ abstract class AS3CF_Plugin_Base {
157
 
158
  // Normalize the defined settings before saving, so we can detect when a real change happens.
159
  ksort( $this->defined_settings );
160
- update_site_option( 'as3cf_constant_' . static::SETTINGS_CONSTANT, $this->defined_settings );
161
  }
162
 
163
  return $this->defined_settings;
@@ -167,15 +180,15 @@ abstract class AS3CF_Plugin_Base {
167
  * Subscribe to changes of the site option used to store the constant-defined settings.
168
  */
169
  protected function listen_for_settings_constant_changes() {
170
- if ( ! has_action( 'update_site_option_' . 'as3cf_constant_' . static::SETTINGS_CONSTANT, array(
171
- $this,
172
- 'settings_constant_changed',
173
- ) ) ) {
174
- add_action( 'add_site_option_' . 'as3cf_constant_' . static::SETTINGS_CONSTANT, array(
175
  $this,
176
  'settings_constant_added',
177
  ), 10, 3 );
178
- add_action( 'update_site_option_' . 'as3cf_constant_' . static::SETTINGS_CONSTANT, array(
179
  $this,
180
  'settings_constant_changed',
181
  ), 10, 4 );
@@ -203,6 +216,10 @@ abstract class AS3CF_Plugin_Base {
203
  * @param int $network_id ID of the network.
204
  */
205
  public function settings_constant_changed( $option, $new_settings, $old_settings, $network_id ) {
 
 
 
 
206
  $old_settings = $old_settings ?: array();
207
 
208
  foreach ( $this->get_settings_whitelist() as $setting ) {
@@ -217,7 +234,7 @@ abstract class AS3CF_Plugin_Base {
217
  * @param mixed $old_value
218
  * @param string $setting
219
  */
220
- do_action( 'as3cf_constant_' . static::SETTINGS_CONSTANT . '_changed_' . $setting, $new_value, $old_value, $setting );
221
 
222
  /**
223
  * Generic hook for setting change.
@@ -226,7 +243,7 @@ abstract class AS3CF_Plugin_Base {
226
  * @param mixed $old_value
227
  * @param string $setting
228
  */
229
- do_action( 'as3cf_constant_' . static::SETTINGS_CONSTANT . '_changed', $new_value, $old_value, $setting );
230
  }
231
  }
232
  }
5
  const DBRAINS_URL = 'https://deliciousbrains.com';
6
 
7
  const SETTINGS_KEY = '';
8
+
9
+ /**
10
+ * @var array
11
+ */
12
+ protected static $settings_constants = array();
13
 
14
  protected static $plugin_page = 'amazon-s3-and-cloudfront';
15
  protected $default_tab = '';
120
  return $this->settings;
121
  }
122
 
123
+ /**
124
+ * Get the constant used to define the settings.
125
+ *
126
+ * @return string|false Constant name if defined, otherwise false
127
+ */
128
+ public static function settings_constant() {
129
+ return AS3CF_Utils::get_first_defined_constant( static::$settings_constants );
130
+ }
131
+
132
  /**
133
  * Get all settings that have been defined via constant for the plugin
134
  *
137
  * @return array
138
  */
139
  function get_defined_settings( $force = false ) {
140
+ if ( ! static::settings_constant() ) {
141
  $this->defined_settings = array();
142
 
143
  return $this->defined_settings;
145
 
146
  if ( is_null( $this->defined_settings ) || $force ) {
147
  $this->defined_settings = array();
148
+ $unserialized = maybe_unserialize( constant( static::settings_constant() ) );
149
  $unserialized = is_array( $unserialized ) ? $unserialized : array();
150
 
151
  foreach ( $unserialized as $key => $value ) {
170
 
171
  // Normalize the defined settings before saving, so we can detect when a real change happens.
172
  ksort( $this->defined_settings );
173
+ update_site_option( 'as3cf_constant_' . static::settings_constant(), $this->defined_settings );
174
  }
175
 
176
  return $this->defined_settings;
180
  * Subscribe to changes of the site option used to store the constant-defined settings.
181
  */
182
  protected function listen_for_settings_constant_changes() {
183
+ if ( false !== static::settings_constant() && ! has_action( 'update_site_option_' . 'as3cf_constant_' . static::settings_constant(), array(
184
+ $this,
185
+ 'settings_constant_changed',
186
+ ) ) ) {
187
+ add_action( 'add_site_option_' . 'as3cf_constant_' . static::settings_constant(), array(
188
  $this,
189
  'settings_constant_added',
190
  ), 10, 3 );
191
+ add_action( 'update_site_option_' . 'as3cf_constant_' . static::settings_constant(), array(
192
  $this,
193
  'settings_constant_changed',
194
  ), 10, 4 );
216
  * @param int $network_id ID of the network.
217
  */
218
  public function settings_constant_changed( $option, $new_settings, $old_settings, $network_id ) {
219
+ if ( ! static::settings_constant() ) {
220
+ return;
221
+ }
222
+
223
  $old_settings = $old_settings ?: array();
224
 
225
  foreach ( $this->get_settings_whitelist() as $setting ) {
234
  * @param mixed $old_value
235
  * @param string $setting
236
  */
237
+ do_action( 'as3cf_constant_' . static::settings_constant() . '_changed_' . $setting, $new_value, $old_value, $setting );
238
 
239
  /**
240
  * Generic hook for setting change.
243
  * @param mixed $old_value
244
  * @param string $setting
245
  */
246
+ do_action( 'as3cf_constant_' . static::settings_constant() . '_changed', $new_value, $old_value, $setting );
247
  }
248
  }
249
  }
classes/as3cf-plugin-compatibility.php CHANGED
@@ -9,7 +9,7 @@
9
  * @since 0.8.3
10
  */
11
 
12
- use DeliciousBrains\WP_Offload_S3\Providers\Provider;
13
 
14
  // Exit if accessed directly
15
  if ( ! defined( 'ABSPATH' ) ) {
@@ -128,18 +128,18 @@ class AS3CF_Plugin_Compatibility {
128
  * @param string $url
129
  * @param string $file
130
  * @param int $attachment_id
131
- * @param array $s3_object
132
  *
133
  * @return string
134
  */
135
- function legacy_copy_back_to_local( $url, $file, $attachment_id, $s3_object ) {
136
- $copy_back_to_local = apply_filters( 'as3cf_get_attached_file_copy_back_to_local', false, $file, $attachment_id, $s3_object );
137
  if ( false === $copy_back_to_local ) {
138
  // Not copying back file
139
  return $url;
140
  }
141
 
142
- if ( ( $file = $this->copy_s3_file_to_server( $s3_object, $file ) ) ) {
143
  // Return the file if successfully downloaded from S3
144
  return $file;
145
  };
@@ -188,11 +188,11 @@ class AS3CF_Plugin_Compatibility {
188
  * @param bool $copy_back_to_local
189
  * @param string $file
190
  * @param integer $attachment_id
191
- * @param array $s3_object
192
  *
193
  * @return bool
194
  */
195
- public function prevent_copy_back_to_local_after_remove( $copy_back_to_local, $file, $attachment_id, $s3_object ) {
196
  if ( $copy_back_to_local && in_array( $file, $this->removed_files ) ) {
197
  $copy_back_to_local = false;
198
  }
@@ -257,20 +257,20 @@ class AS3CF_Plugin_Compatibility {
257
  /**
258
  * Generic method for copying back an S3 file to the server on a specific AJAX action
259
  *
260
- * @param string $action_key Action that must be in process
261
- * @param bool $ajax Must the process be an AJAX one?
262
- * @param string $url S3 URL
263
- * @param string $file Local file path of image
264
- * @param array $s3_object S3 meta data
265
  *
266
  * @return string
267
  */
268
- function copy_image_to_server_on_action( $action_key, $ajax, $url, $file, $s3_object ) {
269
  if ( false === $this->maybe_process_on_action( $action_key, $ajax ) ) {
270
  return $url;
271
  }
272
 
273
- if ( ( $file = $this->copy_s3_file_to_server( $s3_object, $file ) ) ) {
274
  // Return the file if successfully downloaded from S3
275
  return $file;
276
  };
@@ -316,14 +316,14 @@ class AS3CF_Plugin_Compatibility {
316
  return $pre;
317
  }
318
 
319
- $s3object = $this->as3cf->get_attachment_s3_info( $post_id );
320
- $this->remove_edited_image_files( $post_id, $s3object );
321
 
322
  // Update object key with original filename
323
- $restored_filename = wp_basename( $data['file'] );
324
- $old_filename = wp_basename( $s3object['key'] );
325
- $s3object['key'] = str_replace( $old_filename, $restored_filename, $s3object['key'] );
326
- update_post_meta( $post_id, 'amazonS3_info', $s3object );
327
 
328
  return true;
329
  }
@@ -332,18 +332,18 @@ class AS3CF_Plugin_Compatibility {
332
  * Remove edited image files from S3.
333
  *
334
  * @param int $attachment_id
335
- * @param array $s3object
336
  */
337
- protected function remove_edited_image_files( $attachment_id, $s3object ) {
338
- $bucket = $s3object['bucket'];
339
- $region = $this->as3cf->get_s3object_region( $s3object );
340
- $keys = AS3CF_Utils::get_attachment_edited_keys( $attachment_id, $s3object );
341
 
342
  if ( empty( $keys ) ) {
343
  return;
344
  }
345
 
346
- $this->as3cf->delete_s3_objects( $region, $bucket, $keys );
347
  }
348
 
349
  /**
@@ -353,11 +353,11 @@ class AS3CF_Plugin_Compatibility {
353
  * @param string $url
354
  * @param string $file
355
  * @param int $attachment_id
356
- * @param array $s3_object
357
  *
358
  * @return string
359
  */
360
- function image_editor_download_file( $url, $file, $attachment_id, $s3_object ) {
361
  if ( ! $this->is_ajax() ) {
362
  return $url;
363
  }
@@ -370,17 +370,17 @@ class AS3CF_Plugin_Compatibility {
370
  $backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true );
371
  $original_filename = $backup_sizes['full-orig']['file'];
372
 
373
- $orig_s3 = $s3_object;
374
- $orig_s3['key'] = dirname( $s3_object['key'] ) . '/' . $original_filename;
375
- $orig_file = dirname( $file ) . '/' . $original_filename;
376
 
377
  // Copy the original file back to the server for the restore process
378
- $this->copy_s3_file_to_server( $orig_s3, $orig_file );
379
 
380
  // Copy the edited file back to the server as well, it will be cleaned up later
381
- if ( $s3_file = $this->copy_s3_file_to_server( $s3_object, $file ) ) {
382
  // Return the file if successfully downloaded from S3
383
- return $s3_file;
384
  };
385
  }
386
 
@@ -390,9 +390,9 @@ class AS3CF_Plugin_Compatibility {
390
  foreach ( debug_backtrace() as $caller ) {
391
  if ( isset( $caller['function'] ) && '_load_image_to_edit_path' == $caller['function'] ) {
392
  // check this has been called by '_load_image_to_edit_path' so as only to copy back once
393
- if ( $s3_file = $this->copy_s3_file_to_server( $s3_object, $file ) ) {
394
  // Return the file if successfully downloaded from S3
395
- return $s3_file;
396
  };
397
  }
398
  }
@@ -452,11 +452,11 @@ class AS3CF_Plugin_Compatibility {
452
  * @param string $url
453
  * @param string $file
454
  * @param int $attachment_id
455
- * @param array $s3_object
456
  *
457
  * @return string
458
  */
459
- public function customizer_crop_download_file( $url, $file, $attachment_id, $s3_object ) {
460
  if ( false === $this->is_customizer_crop_action() ) {
461
  return $url;
462
  }
@@ -465,7 +465,7 @@ class AS3CF_Plugin_Compatibility {
465
  return $url;
466
  }
467
 
468
- if ( ( $file = $this->copy_s3_file_to_server( $s3_object, $file ) ) ) {
469
  // Return the file if successfully downloaded from S3
470
  return $file;
471
  };
@@ -551,41 +551,41 @@ class AS3CF_Plugin_Compatibility {
551
  * @param string $url
552
  * @param string $file
553
  * @param int $attachment_id
554
- * @param array $s3_object
555
  *
556
  * @return string
557
  */
558
- function regenerate_thumbnails_download_file( $url, $file, $attachment_id, $s3_object ) {
559
- return $this->copy_image_to_server_on_action( 'regeneratethumbnail', true, $url, $file, $s3_object );
560
  }
561
 
562
  /**
563
  * Download a file from S3 if the file does not exist locally and places it where
564
  * the attachment's file should be.
565
  *
566
- * @param array $s3_object
567
  * @param string $file
568
  *
569
  * @return string|bool File if downloaded, false on failure
570
  */
571
- public function copy_s3_file_to_server( $s3_object, $file ) {
572
  // Make sure the directory exists
573
  $dir = dirname( $file );
574
  if ( ! wp_mkdir_p( $dir ) ) {
575
  $error_message = sprintf( __( 'The local directory %s does not exist and could not be created.', 'amazon-s3-and-cloudfront' ), $dir );
576
- AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from S3: %s', 'amazon-s3-and-cloudfront' ), $s3_object['key'], $error_message ) );
577
 
578
  return false;
579
  }
580
 
581
  try {
582
- $this->as3cf->get_s3client( $s3_object['region'], true )->get_object( array(
583
- 'Bucket' => $s3_object['bucket'],
584
- 'Key' => $s3_object['key'],
585
  'SaveAs' => $file,
586
  ) );
587
  } catch ( Exception $e ) {
588
- AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from S3: %s', 'amazon-s3-and-cloudfront' ), $s3_object['key'], $e->getMessage() ) );
589
 
590
  return false;
591
  }
@@ -599,6 +599,7 @@ class AS3CF_Plugin_Compatibility {
599
  * @param string $region
600
  *
601
  * @return Provider|null
 
602
  */
603
  protected function register_stream_wrapper( $region ) {
604
  $stored_region = ( '' === $region ) ? $this->as3cf->get_default_region() : $region;
@@ -607,7 +608,7 @@ class AS3CF_Plugin_Compatibility {
607
  return self::$stream_wrappers[ $stored_region ];
608
  }
609
 
610
- $client = $this->as3cf->get_s3client( $region, true );
611
 
612
 
613
  if ( ! empty( $client ) && $client->register_stream_wrapper( $region ) ) {
@@ -626,21 +627,22 @@ class AS3CF_Plugin_Compatibility {
626
  * @param string $url
627
  * @param string $file
628
  * @param int $attachment_id
629
- * @param array $s3_object
630
  *
631
  * @return string
 
632
  */
633
- public function get_stream_wrapper_file( $url, $file, $attachment_id, $s3_object ) {
634
  if ( $url === $file ) {
635
  // Abort if an earlier hook to get the file has been called and it has been copied back.
636
  return $file;
637
  }
638
 
639
  // Make sure the region stream wrapper is registered.
640
- $client = $this->register_stream_wrapper( $s3_object['region'] );
641
 
642
  if ( ! empty( $client ) ) {
643
- return $client->prepare_stream_wrapper_file( $s3_object['region'], $s3_object['bucket'], $s3_object['key'] );
644
  }
645
 
646
  return $url;
@@ -756,14 +758,14 @@ class AS3CF_Plugin_Compatibility {
756
  return $image_meta;
757
  }
758
 
759
- if ( ! ( $s3object = $this->as3cf->is_attachment_served_by_s3( $attachment_id ) ) ) {
760
  // Attachment not uploaded to S3, abort
761
  return $image_meta;
762
  }
763
 
764
  $image_basename = wp_basename( $image_meta['file'] );
765
 
766
- if ( false === strpos( $s3object['key'], $image_basename ) ) {
767
  // Not the correct attachment, abort
768
  return $image_meta;
769
  }
@@ -802,22 +804,22 @@ class AS3CF_Plugin_Compatibility {
802
  return $sources;
803
  }
804
 
805
- if ( ! ( $s3object = $this->as3cf->is_attachment_served_by_s3( $attachment_id ) ) ) {
806
  // Attachment not uploaded to S3, abort
807
  return $sources;
808
  }
809
 
810
  foreach ( $sources as $width => $source ) {
811
- $filename = wp_basename( $source['url'] );
812
- $size = $this->find_image_size_from_width( $image_meta['sizes'], $width, $filename );
813
- $s3_url = $this->as3cf->get_attachment_s3_url( $attachment_id, $s3object, null, $size, $image_meta );
814
 
815
- if ( false === $s3_url || is_wp_error( $s3_url ) ) {
816
  // Skip URLs not offloaded to S3
817
  continue;
818
  }
819
 
820
- $sources[ $width ]['url'] = $s3_url;
821
  }
822
 
823
  return $sources;
@@ -875,10 +877,10 @@ class AS3CF_Plugin_Compatibility {
875
 
876
  if ( version_compare( PHP_VERSION, '5.5', '<' ) ) {
877
  $message = sprintf(
878
- __( '<strong>Warning:</strong> This site is using PHP %1$s, in a future update WP Offload S3 will require PHP %2$s or later. %3$s', 'amazon-s3-and-cloudfront' ),
879
  PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION,
880
  '5.5',
881
- $this->as3cf->more_info_link( '/wp-offload-s3/doc/php-version-requirements/', 'upgrade-php-version' )
882
  );
883
 
884
  // Show notice to user if not already dismissed.
9
  * @since 0.8.3
10
  */
11
 
12
+ use DeliciousBrains\WP_Offload_Media\Providers\Provider;
13
 
14
  // Exit if accessed directly
15
  if ( ! defined( 'ABSPATH' ) ) {
128
  * @param string $url
129
  * @param string $file
130
  * @param int $attachment_id
131
+ * @param array $provider_object
132
  *
133
  * @return string
134
  */
135
+ function legacy_copy_back_to_local( $url, $file, $attachment_id, $provider_object ) {
136
+ $copy_back_to_local = apply_filters( 'as3cf_get_attached_file_copy_back_to_local', false, $file, $attachment_id, $provider_object );
137
  if ( false === $copy_back_to_local ) {
138
  // Not copying back file
139
  return $url;
140
  }
141
 
142
+ if ( ( $file = $this->copy_provider_file_to_server( $provider_object, $file ) ) ) {
143
  // Return the file if successfully downloaded from S3
144
  return $file;
145
  };
188
  * @param bool $copy_back_to_local
189
  * @param string $file
190
  * @param integer $attachment_id
191
+ * @param array $provider_object
192
  *
193
  * @return bool
194
  */
195
+ public function prevent_copy_back_to_local_after_remove( $copy_back_to_local, $file, $attachment_id, $provider_object ) {
196
  if ( $copy_back_to_local && in_array( $file, $this->removed_files ) ) {
197
  $copy_back_to_local = false;
198
  }
257
  /**
258
  * Generic method for copying back an S3 file to the server on a specific AJAX action
259
  *
260
+ * @param string $action_key Action that must be in process
261
+ * @param bool $ajax Must the process be an AJAX one?
262
+ * @param string $url S3 URL
263
+ * @param string $file Local file path of image
264
+ * @param array $provider_object S3 meta data
265
  *
266
  * @return string
267
  */
268
+ function copy_image_to_server_on_action( $action_key, $ajax, $url, $file, $provider_object ) {
269
  if ( false === $this->maybe_process_on_action( $action_key, $ajax ) ) {
270
  return $url;
271
  }
272
 
273
+ if ( ( $file = $this->copy_provider_file_to_server( $provider_object, $file ) ) ) {
274
  // Return the file if successfully downloaded from S3
275
  return $file;
276
  };
316
  return $pre;
317
  }
318
 
319
+ $provider_object = $this->as3cf->get_attachment_provider_info( $post_id );
320
+ $this->remove_edited_image_files( $post_id, $provider_object );
321
 
322
  // Update object key with original filename
323
+ $restored_filename = wp_basename( $data['file'] );
324
+ $old_filename = wp_basename( $provider_object['key'] );
325
+ $provider_object['key'] = str_replace( $old_filename, $restored_filename, $provider_object['key'] );
326
+ update_post_meta( $post_id, 'amazonS3_info', $provider_object );
327
 
328
  return true;
329
  }
332
  * Remove edited image files from S3.
333
  *
334
  * @param int $attachment_id
335
+ * @param array $provider_object
336
  */
337
+ protected function remove_edited_image_files( $attachment_id, $provider_object ) {
338
+ $bucket = $provider_object['bucket'];
339
+ $region = $this->as3cf->get_provider_object_region( $provider_object );
340
+ $keys = AS3CF_Utils::get_attachment_edited_keys( $attachment_id, $provider_object );
341
 
342
  if ( empty( $keys ) ) {
343
  return;
344
  }
345
 
346
+ $this->as3cf->delete_objects( $region, $bucket, $keys );
347
  }
348
 
349
  /**
353
  * @param string $url
354
  * @param string $file
355
  * @param int $attachment_id
356
+ * @param array $provider_object
357
  *
358
  * @return string
359
  */
360
+ function image_editor_download_file( $url, $file, $attachment_id, $provider_object ) {
361
  if ( ! $this->is_ajax() ) {
362
  return $url;
363
  }
370
  $backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true );
371
  $original_filename = $backup_sizes['full-orig']['file'];
372
 
373
+ $orig_provider = $provider_object;
374
+ $orig_provider['key'] = dirname( $provider_object['key'] ) . '/' . $original_filename;
375
+ $orig_file = dirname( $file ) . '/' . $original_filename;
376
 
377
  // Copy the original file back to the server for the restore process
378
+ $this->copy_provider_file_to_server( $orig_provider, $orig_file );
379
 
380
  // Copy the edited file back to the server as well, it will be cleaned up later
381
+ if ( $provider_file = $this->copy_provider_file_to_server( $provider_object, $file ) ) {
382
  // Return the file if successfully downloaded from S3
383
+ return $provider_file;
384
  };
385
  }
386
 
390
  foreach ( debug_backtrace() as $caller ) {
391
  if ( isset( $caller['function'] ) && '_load_image_to_edit_path' == $caller['function'] ) {
392
  // check this has been called by '_load_image_to_edit_path' so as only to copy back once
393
+ if ( $provider_file = $this->copy_provider_file_to_server( $provider_object, $file ) ) {
394
  // Return the file if successfully downloaded from S3
395
+ return $provider_file;
396
  };
397
  }
398
  }
452
  * @param string $url
453
  * @param string $file
454
  * @param int $attachment_id
455
+ * @param array $provider_object
456
  *
457
  * @return string
458
  */
459
+ public function customizer_crop_download_file( $url, $file, $attachment_id, $provider_object ) {
460
  if ( false === $this->is_customizer_crop_action() ) {
461
  return $url;
462
  }
465
  return $url;
466
  }
467
 
468
+ if ( ( $file = $this->copy_provider_file_to_server( $provider_object, $file ) ) ) {
469
  // Return the file if successfully downloaded from S3
470
  return $file;
471
  };
551
  * @param string $url
552
  * @param string $file
553
  * @param int $attachment_id
554
+ * @param array $provider_object
555
  *
556
  * @return string
557
  */
558
+ function regenerate_thumbnails_download_file( $url, $file, $attachment_id, $provider_object ) {
559
+ return $this->copy_image_to_server_on_action( 'regeneratethumbnail', true, $url, $file, $provider_object );
560
  }
561
 
562
  /**
563
  * Download a file from S3 if the file does not exist locally and places it where
564
  * the attachment's file should be.
565
  *
566
+ * @param array $provider_object
567
  * @param string $file
568
  *
569
  * @return string|bool File if downloaded, false on failure
570
  */
571
+ public function copy_provider_file_to_server( $provider_object, $file ) {
572
  // Make sure the directory exists
573
  $dir = dirname( $file );
574
  if ( ! wp_mkdir_p( $dir ) ) {
575
  $error_message = sprintf( __( 'The local directory %s does not exist and could not be created.', 'amazon-s3-and-cloudfront' ), $dir );
576
+ AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from the bucket: %s', 'amazon-s3-and-cloudfront' ), $provider_object['key'], $error_message ) );
577
 
578
  return false;
579
  }
580
 
581
  try {
582
+ $this->as3cf->get_provider_client( $provider_object['region'], true )->get_object( array(
583
+ 'Bucket' => $provider_object['bucket'],
584
+ 'Key' => $provider_object['key'],
585
  'SaveAs' => $file,
586
  ) );
587
  } catch ( Exception $e ) {
588
+ AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from the bucket: %s', 'amazon-s3-and-cloudfront' ), $provider_object['key'], $e->getMessage() ) );
589
 
590
  return false;
591
  }
599
  * @param string $region
600
  *
601
  * @return Provider|null
602
+ * @throws Exception
603
  */
604
  protected function register_stream_wrapper( $region ) {
605
  $stored_region = ( '' === $region ) ? $this->as3cf->get_default_region() : $region;
608
  return self::$stream_wrappers[ $stored_region ];
609
  }
610
 
611
+ $client = $this->as3cf->get_provider_client( $region, true );
612
 
613
 
614
  if ( ! empty( $client ) && $client->register_stream_wrapper( $region ) ) {
627
  * @param string $url
628
  * @param string $file
629
  * @param int $attachment_id
630
+ * @param array $provider_object
631
  *
632
  * @return string
633
+ * @throws Exception
634
  */
635
+ public function get_stream_wrapper_file( $url, $file, $attachment_id, $provider_object ) {
636
  if ( $url === $file ) {
637
  // Abort if an earlier hook to get the file has been called and it has been copied back.
638
  return $file;
639
  }
640
 
641
  // Make sure the region stream wrapper is registered.
642
+ $client = $this->register_stream_wrapper( $provider_object['region'] );
643
 
644
  if ( ! empty( $client ) ) {
645
+ return $client->prepare_stream_wrapper_file( $provider_object['region'], $provider_object['bucket'], $provider_object['key'] );
646
  }
647
 
648
  return $url;
758
  return $image_meta;
759
  }
760
 
761
+ if ( ! ( $provider_object = $this->as3cf->is_attachment_served_by_provider( $attachment_id ) ) ) {
762
  // Attachment not uploaded to S3, abort
763
  return $image_meta;
764
  }
765
 
766
  $image_basename = wp_basename( $image_meta['file'] );
767
 
768
+ if ( false === strpos( $provider_object['key'], $image_basename ) ) {
769
  // Not the correct attachment, abort
770
  return $image_meta;
771
  }
804
  return $sources;
805
  }
806
 
807
+ if ( ! ( $provider_object = $this->as3cf->is_attachment_served_by_provider( $attachment_id ) ) ) {
808
  // Attachment not uploaded to S3, abort
809
  return $sources;
810
  }
811
 
812
  foreach ( $sources as $width => $source ) {
813
+ $filename = wp_basename( $source['url'] );
814
+ $size = $this->find_image_size_from_width( $image_meta['sizes'], $width, $filename );
815
+ $provider_url = $this->as3cf->get_attachment_provider_url( $attachment_id, $provider_object, null, $size, $image_meta );
816
 
817
+ if ( false === $provider_url || is_wp_error( $provider_url ) ) {
818
  // Skip URLs not offloaded to S3
819
  continue;
820
  }
821
 
822
+ $sources[ $width ]['url'] = $provider_url;
823
  }
824
 
825
  return $sources;
877
 
878
  if ( version_compare( PHP_VERSION, '5.5', '<' ) ) {
879
  $message = sprintf(
880
+ __( '<strong>Warning:</strong> This site is using PHP %1$s, in a future update WP Offload Media will require PHP %2$s or later. %3$s', 'amazon-s3-and-cloudfront' ),
881
  PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION,
882
  '5.5',
883
+ $this->as3cf->more_info_link( '/wp-offload-media/doc/php-version-requirements/', 'upgrade-php-version' )
884
  );
885
 
886
  // Show notice to user if not already dismissed.
classes/as3cf-utils.php CHANGED
@@ -23,10 +23,11 @@ if ( ! class_exists( 'AS3CF_Utils' ) ) {
23
  *
24
  */
25
  class AS3CF_Utils {
 
26
  /**
27
  * Get post ID.
28
  *
29
- * @param null|int|WP_Post $post Optional. Post ID or post object. Defaults to current post.
30
  *
31
  * @return int
32
  */
@@ -97,9 +98,9 @@ if ( ! class_exists( 'AS3CF_Utils' ) ) {
97
  /**
98
  * Parses a URL into its components. Compatible with PHP < 5.4.7.
99
  *
100
- * @param $url string The URL to parse.
101
  *
102
- * @param int $component PHP_URL_ constant for URL component to return.
103
  *
104
  * @return mixed An array of the parsed components, mixed for a requested component, or false on error.
105
  */
@@ -254,12 +255,12 @@ if ( ! class_exists( 'AS3CF_Utils' ) ) {
254
  * Get an attachment's edited S3 keys.
255
  *
256
  * @param int $attachment_id
257
- * @param array $s3object
258
  *
259
  * @return array
260
  */
261
- public static function get_attachment_edited_keys( $attachment_id, $s3object ) {
262
- $prefix = trailingslashit( pathinfo( $s3object['key'], PATHINFO_DIRNAME ) );
263
  $paths = self::get_attachment_edited_file_paths( $attachment_id );
264
  $paths = array_map( function ( $path ) use ( $prefix ) {
265
  return array( 'Key' => $prefix . wp_basename( $path ) );
@@ -345,14 +346,86 @@ if ( ! class_exists( 'AS3CF_Utils' ) ) {
345
  * @return string
346
  */
347
  public static function current_base_domain() {
348
- $domain = static::current_domain();
349
- $parts = explode( '.', $domain, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
350
 
351
- if ( isset( $parts[1] ) && in_array( $parts[0], array( 'www' ) ) ) {
352
- return $parts[1];
 
 
 
353
  }
354
 
355
- return $domain;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
356
  }
357
 
358
  /**
@@ -374,9 +447,11 @@ if ( ! class_exists( 'AS3CF_Utils' ) ) {
374
  * @return string|false string constant name if defined, otherwise false if none are defined
375
  */
376
  public static function get_first_defined_constant( $constants ) {
377
- foreach ( (array) $constants as $constant ) {
378
- if ( defined( $constant ) ) {
379
- return $constant;
 
 
380
  }
381
  }
382
 
@@ -404,5 +479,19 @@ if ( ! class_exists( 'AS3CF_Utils' ) ) {
404
 
405
  return $keys;
406
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
  }
408
  }
23
  *
24
  */
25
  class AS3CF_Utils {
26
+
27
  /**
28
  * Get post ID.
29
  *
30
+ * @param null|int|WP_Post $post Optional. Post ID or post object. Defaults to current post.
31
  *
32
  * @return int
33
  */
98
  /**
99
  * Parses a URL into its components. Compatible with PHP < 5.4.7.
100
  *
101
+ * @param string $url The URL to parse.
102
  *
103
+ * @param int $component PHP_URL_ constant for URL component to return.
104
  *
105
  * @return mixed An array of the parsed components, mixed for a requested component, or false on error.
106
  */
255
  * Get an attachment's edited S3 keys.
256
  *
257
  * @param int $attachment_id
258
+ * @param array $provider_object
259
  *
260
  * @return array
261
  */
262
+ public static function get_attachment_edited_keys( $attachment_id, $provider_object ) {
263
+ $prefix = trailingslashit( pathinfo( $provider_object['key'], PATHINFO_DIRNAME ) );
264
  $paths = self::get_attachment_edited_file_paths( $attachment_id );
265
  $paths = array_map( function ( $path ) use ( $prefix ) {
266
  return array( 'Key' => $prefix . wp_basename( $path ) );
346
  * @return string
347
  */
348
  public static function current_base_domain() {
349
+ return static::base_domain( static::current_domain() );
350
+ }
351
+
352
+ /**
353
+ * Get the base domain of the supplied domain.
354
+ *
355
+ * @param string $domain
356
+ *
357
+ * @return string
358
+ */
359
+ public static function base_domain( $domain ) {
360
+ if ( WP_Http::is_ip_address( $domain ) ) {
361
+ return $domain;
362
+ }
363
 
364
+ $parts = explode( '.', $domain );
365
+
366
+ // localhost etc.
367
+ if ( is_string( $parts ) ) {
368
+ return $domain;
369
  }
370
 
371
+ if ( count( $parts ) < 3 ) {
372
+ return $domain;
373
+ }
374
+
375
+ // Just knock off the first segment.
376
+ unset( $parts[0] );
377
+
378
+ return implode( '.', $parts );
379
+ }
380
+
381
+ /**
382
+ * Very basic check of whether domain is real.
383
+ *
384
+ * @param string $domain
385
+ *
386
+ * @return bool
387
+ *
388
+ * Note: Very early version, may extend with further "local" domain checks if relevant.
389
+ */
390
+ public static function is_public_domain( $domain ) {
391
+ // We're not going to test SEO etc. for ip addresses.
392
+ if ( WP_Http::is_ip_address( $domain ) ) {
393
+ return false;
394
+ }
395
+
396
+ $parts = explode( '.', $domain );
397
+
398
+ // localhost etc.
399
+ if ( is_string( $parts ) ) {
400
+ return false;
401
+ }
402
+
403
+ // TODO: Maybe check domain TLD.
404
+
405
+ return true;
406
+ }
407
+
408
+ /**
409
+ * Is given URL considered SEO friendly?
410
+ *
411
+ * @param string $url
412
+ *
413
+ * @return bool
414
+ */
415
+ public static function seo_friendly_url( $url ) {
416
+ $domain = static::base_domain( parse_url( $url, PHP_URL_HOST ) );
417
+ $base_domain = static::current_base_domain();
418
+
419
+ // If either domain is not a public domain then skip checks.
420
+ if ( ! static::is_public_domain( $domain ) || ! static::is_public_domain( $base_domain ) ) {
421
+ return true;
422
+ }
423
+
424
+ if ( substr( $domain, -strlen( $base_domain ) ) === $base_domain ) {
425
+ return true;
426
+ }
427
+
428
+ return false;
429
  }
430
 
431
  /**
447
  * @return string|false string constant name if defined, otherwise false if none are defined
448
  */
449
  public static function get_first_defined_constant( $constants ) {
450
+ if ( ! empty( $constants ) ) {
451
+ foreach ( (array) $constants as $constant ) {
452
+ if ( defined( $constant ) ) {
453
+ return $constant;
454
+ }
455
  }
456
  }
457
 
479
 
480
  return $keys;
481
  }
482
+
483
+ /**
484
+ * Sanitize custom domain
485
+ *
486
+ * @param string $domain
487
+ *
488
+ * @return string
489
+ */
490
+ public static function sanitize_custom_domain( $domain ) {
491
+ $domain = preg_replace( '@^[a-zA-Z]*:\/\/@', '', $domain );
492
+ $domain = preg_replace( '@[^a-zA-Z0-9\.\-]@', '', $domain );
493
+
494
+ return $domain;
495
+ }
496
  }
497
  }
classes/filters/as3cf-local-to-s3.php CHANGED
@@ -20,7 +20,8 @@ class AS3CF_Local_To_S3 extends AS3CF_Filter {
20
  add_filter( 'the_excerpt', array( $this, 'filter_post' ), 100 );
21
  add_filter( 'content_edit_pre', array( $this, 'filter_post' ) );
22
  add_filter( 'excerpt_edit_pre', array( $this, 'filter_post' ) );
23
- add_filter( 'as3cf_filter_post_local_to_s3', array( $this, 'filter_post' ) );
 
24
  // Widgets
25
  add_filter( 'widget_form_callback', array( $this, 'filter_widget_display' ), 10, 2 );
26
  add_filter( 'widget_display_callback', array( $this, 'filter_widget_display' ), 10, 2 );
20
  add_filter( 'the_excerpt', array( $this, 'filter_post' ), 100 );
21
  add_filter( 'content_edit_pre', array( $this, 'filter_post' ) );
22
  add_filter( 'excerpt_edit_pre', array( $this, 'filter_post' ) );
23
+ add_filter( 'as3cf_filter_post_local_to_s3', array( $this, 'filter_post' ) ); // Backwards compatibility
24
+ add_filter( 'as3cf_filter_post_local_to_provider', array( $this, 'filter_post' ) );
25
  // Widgets
26
  add_filter( 'widget_form_callback', array( $this, 'filter_widget_display' ), 10, 2 );
27
  add_filter( 'widget_display_callback', array( $this, 'filter_widget_display' ), 10, 2 );
classes/filters/as3cf-s3-to-local.php CHANGED
@@ -16,7 +16,8 @@ class AS3CF_S3_To_Local extends AS3CF_Filter {
16
  // Posts
17
  add_filter( 'content_save_pre', array( $this, 'filter_post' ) );
18
  add_filter( 'excerpt_save_pre', array( $this, 'filter_post' ) );
19
- add_filter( 'as3cf_filter_post_s3_to_local', array( $this, 'filter_post' ) );
 
20
  // Widgets
21
  add_filter( 'widget_update_callback', array( $this, 'filter_widget_save' ), 10, 4 );
22
  }
16
  // Posts
17
  add_filter( 'content_save_pre', array( $this, 'filter_post' ) );
18
  add_filter( 'excerpt_save_pre', array( $this, 'filter_post' ) );
19
+ add_filter( 'as3cf_filter_post_s3_to_local', array( $this, 'filter_post' ) ); // Backwards compatibility
20
+ add_filter( 'as3cf_filter_post_provider_to_local', array( $this, 'filter_post' ) );
21
  // Widgets
22
  add_filter( 'widget_update_callback', array( $this, 'filter_widget_save' ), 10, 4 );
23
  }
classes/providers/aws-provider.php CHANGED
@@ -1,13 +1,14 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Providers;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandPool;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\ResultInterface;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\S3\Exception\S3Exception;
8
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\S3\S3Client;
9
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Sdk;
10
- use DeliciousBrains\WP_Offload_S3\Providers\Streams\AWS_S3_Stream_Wrapper;
 
11
 
12
  class AWS_Provider extends Provider {
13
 
@@ -24,22 +25,43 @@ class AWS_Provider extends Provider {
24
  /**
25
  * @var string
26
  */
27
- protected $provider_short_name = 'aws';
28
 
29
  /**
30
  * @var string
31
  */
32
- protected $service_short_name = 's3';
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  /**
35
  * @var string
36
  */
37
- protected $access_key_id_setting_name = 'aws-access-key-id';
38
 
39
  /**
 
 
40
  * @var string
41
  */
42
- protected $secret_access_key_setting_name = 'aws-secret-access-key';
 
 
 
 
 
 
 
43
 
44
  /**
45
  * @var array
@@ -97,6 +119,21 @@ class AWS_Provider extends Provider {
97
  */
98
  protected $default_region = 'us-east-1';
99
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  const API_VERSION = '2006-03-01';
101
  const SIGNATURE_VERSION = 'v4';
102
 
@@ -122,12 +159,23 @@ class AWS_Provider extends Provider {
122
  */
123
  protected function default_client_args() {
124
  return array(
125
- 'signature_version' => self::SIGNATURE_VERSION,
126
- 'version' => self::API_VERSION,
127
  'region' => $this->default_region,
128
  );
129
  }
130
 
 
 
 
 
 
 
 
 
 
 
 
131
  /**
132
  * Instantiate a new client for the provider's SDK.
133
  *
@@ -137,6 +185,17 @@ class AWS_Provider extends Provider {
137
  $this->aws_client = new Sdk( $args );
138
  }
139
 
 
 
 
 
 
 
 
 
 
 
 
140
  /**
141
  * Instantiate a new service specific client.
142
  *
@@ -251,7 +310,7 @@ class AWS_Provider extends Provider {
251
  * @return string
252
  */
253
  public function get_default_acl() {
254
- return self::DEFAULT_ACL;
255
  }
256
 
257
  /**
@@ -260,7 +319,7 @@ class AWS_Provider extends Provider {
260
  * @return string
261
  */
262
  public function get_private_acl() {
263
- return self::PRIVATE_ACL;
264
  }
265
 
266
  /**
@@ -294,7 +353,7 @@ class AWS_Provider extends Provider {
294
  $command = $this->s3_client->getCommand( 'GetObject', $commandArgs );
295
 
296
  if ( empty( $expires ) ) {
297
- return (string) \DeliciousBrains\WP_Offload_S3\Aws3\Aws\serialize( $command )->getUri();
298
  } else {
299
  return (string) $this->s3_client->createPresignedRequest( $command, $expires )->getUri();
300
  }
@@ -399,7 +458,7 @@ class AWS_Provider extends Provider {
399
  if ( ! empty( $results ) ) {
400
  foreach ( $results as $result ) {
401
  /* @var S3Exception $result */
402
- if ( is_a( $result, 'DeliciousBrains\WP_Offload_S3\Aws3\Aws\S3\Exception\S3Exception' ) ) {
403
  $command = $result->getCommand()->toArray();
404
  $failures[] = array(
405
  'Key' => $command['Key'],
@@ -477,4 +536,60 @@ class AWS_Provider extends Provider {
477
 
478
  return false;
479
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers;
4
 
5
+ use AS3CF_Utils;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandPool;
7
+ 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 Provider {
14
 
25
  /**
26
  * @var string
27
  */
28
+ protected static $provider_name = 'Amazon Web Services';
29
 
30
  /**
31
  * @var string
32
  */
33
+ protected static $provider_short_name = 'AWS';
34
+
35
+ /**
36
+ * Used in filters and settings.
37
+ *
38
+ * @var string
39
+ */
40
+ protected static $provider_key_name = 'aws';
41
+
42
+ /**
43
+ * @var string
44
+ */
45
+ protected static $service_name = 'Simple Storage Solution';
46
 
47
  /**
48
  * @var string
49
  */
50
+ protected static $service_short_name = 'S3';
51
 
52
  /**
53
+ * Used in filters and settings.
54
+ *
55
  * @var string
56
  */
57
+ protected static $service_key_name = 's3';
58
+
59
+ /**
60
+ * Optional override of "Provider Name" + "Service Name" for friendly name for service.
61
+ *
62
+ * @var string
63
+ */
64
+ protected static $provider_service_name = 'Amazon S3';
65
 
66
  /**
67
  * @var array
119
  */
120
  protected $default_region = 'us-east-1';
121
 
122
+ /**
123
+ * @var string
124
+ */
125
+ protected $default_domain = 'amazonaws.com';
126
+
127
+ /**
128
+ * @var string
129
+ */
130
+ protected $console_url = 'https://console.aws.amazon.com/s3/home?bucket=';
131
+
132
+ /**
133
+ * @var string
134
+ */
135
+ protected $console_url_param = '&prefix=';
136
+
137
  const API_VERSION = '2006-03-01';
138
  const SIGNATURE_VERSION = 'v4';
139
 
159
  */
160
  protected function default_client_args() {
161
  return array(
162
+ 'signature_version' => static::SIGNATURE_VERSION,
163
+ 'version' => static::API_VERSION,
164
  'region' => $this->default_region,
165
  );
166
  }
167
 
168
+ /**
169
+ * Process the args before instantiating a new client for the provider's SDK.
170
+ *
171
+ * @param array $args
172
+ *
173
+ * @return array
174
+ */
175
+ protected function init_client_args( Array $args ) {
176
+ return $args;
177
+ }
178
+
179
  /**
180
  * Instantiate a new client for the provider's SDK.
181
  *
185
  $this->aws_client = new Sdk( $args );
186
  }
187
 
188
+ /**
189
+ * Process the args before instantiating a new service specific client.
190
+ *
191
+ * @param array $args
192
+ *
193
+ * @return array
194
+ */
195
+ protected function init_service_client_args( Array $args ) {
196
+ return $args;
197
+ }
198
+
199
  /**
200
  * Instantiate a new service specific client.
201
  *
310
  * @return string
311
  */
312
  public function get_default_acl() {
313
+ return static::DEFAULT_ACL;
314
  }
315
 
316
  /**
319
  * @return string
320
  */
321
  public function get_private_acl() {
322
+ return static::PRIVATE_ACL;
323
  }
324
 
325
  /**
353
  $command = $this->s3_client->getCommand( 'GetObject', $commandArgs );
354
 
355
  if ( empty( $expires ) ) {
356
+ return (string) \DeliciousBrains\WP_Offload_Media\Aws3\Aws\serialize( $command )->getUri();
357
  } else {
358
  return (string) $this->s3_client->createPresignedRequest( $command, $expires )->getUri();
359
  }
458
  if ( ! empty( $results ) ) {
459
  foreach ( $results as $result ) {
460
  /* @var S3Exception $result */
461
+ if ( is_a( $result, 'DeliciousBrains\WP_Offload_Media\Aws3\Aws\S3\Exception\S3Exception' ) ) {
462
  $command = $result->getCommand()->toArray();
463
  $failures[] = array(
464
  'Key' => $command['Key'],
536
 
537
  return false;
538
  }
539
+
540
+ /**
541
+ * Get the region specific prefix for raw URL
542
+ *
543
+ * @param string $region
544
+ * @param null|int $expires
545
+ *
546
+ * @return string
547
+ */
548
+ protected function url_prefix( $region = '', $expires = null ) {
549
+ $prefix = 's3';
550
+
551
+ if ( '' !== $region ) {
552
+ $delimiter = '-';
553
+ if ( 'eu-central-1' == $region && ! is_null( $expires ) ) {
554
+ // if we are creating a secure URL for a Frankfurt base file use the alternative delimiter
555
+ // http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
556
+ $delimiter = '.';
557
+ }
558
+
559
+ $prefix .= $delimiter . $region;
560
+ }
561
+
562
+ return $prefix;
563
+ }
564
+
565
+ /**
566
+ * Get the url domain for the files
567
+ *
568
+ * @param string $domain Likely prefixed with region
569
+ * @param string $bucket
570
+ * @param string $region
571
+ * @param int $expires
572
+ * @param array $args Allows you to specify custom URL settings
573
+ * @param bool $preview When generating the URL preview sanitize certain output
574
+ *
575
+ * @return string
576
+ */
577
+ protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array(), $preview = false ) {
578
+ if ( 'cloudfront' === $args['domain'] && is_null( $expires ) && $args['cloudfront'] ) {
579
+ $cloudfront = $args['cloudfront'];
580
+ if ( $preview ) {
581
+ $cloudfront = AS3CF_Utils::sanitize_custom_domain( $cloudfront );
582
+ }
583
+
584
+ $domain = $cloudfront;
585
+ } elseif ( 'virtual-host' === $args['domain'] ) {
586
+ $domain = $bucket;
587
+ } elseif ( 'path' === $args['domain'] || $args['force-https'] ) {
588
+ $domain = $domain . '/' . $bucket;
589
+ } else {
590
+ $domain = $bucket . '.' . $domain;
591
+ }
592
+
593
+ return $domain;
594
+ }
595
  }
classes/providers/digitalocean-provider.php ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers;
4
+
5
+ class DigitalOcean_Provider extends AWS_Provider {
6
+
7
+ /**
8
+ * @var string
9
+ */
10
+ protected static $provider_name = 'DigitalOcean';
11
+
12
+ /**
13
+ * @var string
14
+ */
15
+ protected static $provider_short_name = 'DigitalOcean';
16
+
17
+ /**
18
+ * Used in filters and settings.
19
+ *
20
+ * @var string
21
+ */
22
+ protected static $provider_key_name = 'do';
23
+
24
+ /**
25
+ * @var string
26
+ */
27
+ protected static $service_name = 'Spaces';
28
+
29
+ /**
30
+ * @var string
31
+ */
32
+ protected static $service_short_name = 'Spaces';
33
+
34
+ /**
35
+ * Used in filters and settings.
36
+ *
37
+ * @var string
38
+ */
39
+ protected static $service_key_name = 'spaces';
40
+
41
+ /**
42
+ * Optional override of "Provider Name" + "Service Name" for friendly name for service.
43
+ *
44
+ * @var string
45
+ */
46
+ protected static $provider_service_name = '';
47
+
48
+ /**
49
+ * @var array
50
+ */
51
+ protected static $access_key_id_constants = array(
52
+ 'AS3CF_DO_ACCESS_KEY_ID',
53
+ );
54
+
55
+ /**
56
+ * @var array
57
+ */
58
+ protected static $secret_access_key_constants = array(
59
+ 'AS3CF_DO_SECRET_ACCESS_KEY',
60
+ );
61
+
62
+ /**
63
+ * @var array
64
+ */
65
+ protected static $use_server_roles_constants = array();
66
+
67
+ /**
68
+ * @var array
69
+ */
70
+ protected $regions = array(
71
+ 'nyc3' => 'New York',
72
+ 'ams3' => 'Amsterdam',
73
+ 'sgp1' => 'Singapore',
74
+ 'sfo2' => 'San Francisco',
75
+ );
76
+
77
+ /**
78
+ * @var bool
79
+ */
80
+ protected $region_required = true;
81
+
82
+ /**
83
+ * @var string
84
+ */
85
+ protected $default_region = 'nyc3';
86
+
87
+ /**
88
+ * @var string
89
+ */
90
+ protected $default_domain = 'digitaloceanspaces.com';
91
+
92
+ /**
93
+ * @var string
94
+ */
95
+ protected $console_url = 'https://cloud.digitalocean.com/spaces/';
96
+
97
+ /**
98
+ * @var string
99
+ */
100
+ protected $console_url_param = '?path=';
101
+
102
+ /**
103
+ * @var array
104
+ */
105
+ private $client_args = array();
106
+
107
+ /**
108
+ * Process the args before instantiating a new client for the provider's SDK.
109
+ *
110
+ * @param array $args
111
+ *
112
+ * @return array
113
+ */
114
+ protected function init_client_args( Array $args ) {
115
+ if ( empty( $args['endpoint'] ) ) {
116
+ // DigitalOcean endpoints always require a region.
117
+ $args['region'] = empty( $args['region'] ) ? $this->get_default_region() : $args['region'];
118
+
119
+ $args['endpoint'] = 'https://' . $args['region'] . '.' . $this->get_domain();
120
+ }
121
+
122
+ $this->client_args = $args;
123
+
124
+ return $this->client_args;
125
+ }
126
+
127
+ /**
128
+ * Process the args before instantiating a new service specific client.
129
+ *
130
+ * @param array $args
131
+ *
132
+ * @return array
133
+ */
134
+ protected function init_service_client_args( Array $args ) {
135
+ return $args;
136
+ }
137
+
138
+ /**
139
+ * Create bucket.
140
+ *
141
+ * @param array $args
142
+ *
143
+ * @throws \Exception
144
+ */
145
+ public function create_bucket( Array $args ) {
146
+ // DigitalOcean is happy with the standard V4 signature, unless doing a "CreateBucket"!
147
+ if ( ! empty( $this->client_args['signature_version'] ) && 'v4-unsigned-body' === $this->client_args['signature_version'] ) {
148
+ parent::create_bucket( $args );
149
+ } else {
150
+ $client_args = $this->client_args;
151
+ $client_args['signature_version'] = 'v4-unsigned-body';
152
+ $this->get_client( $client_args, true )->create_bucket( $args );
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Returns region for bucket.
158
+ *
159
+ * @param array $args
160
+ *
161
+ * @return string
162
+ */
163
+ public function get_bucket_location( Array $args ) {
164
+ // For some reason DigitalOcean Spaces returns an XML LocationConstraint segment prepended to the region key.
165
+ return strip_tags( parent::get_bucket_location( $args ) );
166
+ }
167
+
168
+ /**
169
+ * Get the region specific prefix for raw URL
170
+ *
171
+ * @param string $region
172
+ * @param null|int $expires
173
+ *
174
+ * @return string
175
+ */
176
+ protected function url_prefix( $region = '', $expires = null ) {
177
+ return $region;
178
+ }
179
+ }
classes/providers/null-provider.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Providers;
4
 
5
  use AS3CF_Error;
6
 
@@ -16,7 +16,7 @@ class Null_Provider {
16
  */
17
  public function __call( $name, $arguments ) {
18
  AS3CF_Error::log( $arguments, __CLASS__ . "->$name()" );
19
- throw new \Exception( 'Failed to instantiate the AWS S3 client. Check your error log.' );
20
  }
21
 
22
  /**
@@ -29,6 +29,6 @@ class Null_Provider {
29
  */
30
  public static function __callStatic( $name, $arguments ) {
31
  AS3CF_Error::log( $arguments, __CLASS__ . "::$name()" );
32
- throw new \Exception( 'Failed to instantiate the AWS S3 client. Check your error log.' );
33
  }
34
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers;
4
 
5
  use AS3CF_Error;
6
 
16
  */
17
  public function __call( $name, $arguments ) {
18
  AS3CF_Error::log( $arguments, __CLASS__ . "->$name()" );
19
+ throw new \Exception( 'Failed to instantiate the provider client. Check your error log.' );
20
  }
21
 
22
  /**
29
  */
30
  public static function __callStatic( $name, $arguments ) {
31
  AS3CF_Error::log( $arguments, __CLASS__ . "::$name()" );
32
+ throw new \Exception( 'Failed to instantiate the provider client. Check your error log.' );
33
  }
34
  }
classes/providers/provider.php CHANGED
@@ -1,15 +1,16 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Providers;
4
 
5
  use AS3CF_Plugin_Base;
 
6
  use AS3CF_Utils;
7
  use Exception;
8
 
9
  abstract class Provider {
10
 
11
  /**
12
- * @var AS3CF_Plugin_Base
13
  */
14
  private $as3cf;
15
 
@@ -21,22 +22,53 @@ abstract class Provider {
21
  /**
22
  * @var string
23
  */
24
- protected $provider_short_name = '';
25
 
26
  /**
27
  * @var string
28
  */
29
- protected $service_short_name = '';
30
 
31
  /**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  * @var string
33
  */
34
- protected $access_key_id_setting_name = '';
35
 
36
  /**
 
 
37
  * @var string
38
  */
39
- protected $secret_access_key_setting_name = '';
 
 
 
 
 
 
 
 
 
 
40
 
41
  /**
42
  * @var array
@@ -49,6 +81,8 @@ abstract class Provider {
49
  protected static $secret_access_key_constants = array();
50
 
51
  /**
 
 
52
  * @var array
53
  */
54
  protected static $use_server_roles_constants = array();
@@ -58,11 +92,31 @@ abstract class Provider {
58
  */
59
  protected $regions = array();
60
 
 
 
 
 
 
61
  /**
62
  * @var string
63
  */
64
  protected $default_region = '';
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  /**
67
  * Provider constructor.
68
  *
@@ -72,6 +126,46 @@ abstract class Provider {
72
  $this->as3cf = $as3cf;
73
  }
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  /**
76
  * Whether or not access keys are needed.
77
  *
@@ -80,7 +174,7 @@ abstract class Provider {
80
  * @return bool
81
  */
82
  public function needs_access_keys() {
83
- if ( $this->use_server_roles() ) {
84
  return false;
85
  }
86
 
@@ -92,7 +186,7 @@ abstract class Provider {
92
  *
93
  * @return bool
94
  */
95
- function are_access_keys_set() {
96
  return $this->get_access_key_id() && $this->get_secret_access_key();
97
  }
98
 
@@ -104,13 +198,13 @@ abstract class Provider {
104
  * @return string
105
  */
106
  public function get_access_key_id() {
107
- if ( $this->is_any_access_key_constant_defined() ) {
108
- $constant = $this->access_key_id_constant();
109
 
110
  return $constant ? constant( $constant ) : '';
111
  }
112
 
113
- return $this->as3cf->get_core_setting( $this->access_key_id_setting_name );
114
  }
115
 
116
  /**
@@ -121,13 +215,13 @@ abstract class Provider {
121
  * @return string
122
  */
123
  public function get_secret_access_key() {
124
- if ( $this->is_any_access_key_constant_defined() ) {
125
- $constant = $this->secret_access_key_constant();
126
 
127
  return $constant ? constant( $constant ) : '';
128
  }
129
 
130
- return $this->as3cf->get_core_setting( $this->secret_access_key_setting_name );
131
  }
132
 
133
  /**
@@ -145,8 +239,12 @@ abstract class Provider {
145
  *
146
  * @return bool
147
  */
148
- public function use_server_roles() {
149
- $constant = $this->use_server_role_constant();
 
 
 
 
150
 
151
  return $constant && constant( $constant );
152
  }
@@ -169,6 +267,15 @@ abstract class Provider {
169
  return AS3CF_Utils::get_first_defined_constant( static::$secret_access_key_constants );
170
  }
171
 
 
 
 
 
 
 
 
 
 
172
  /**
173
  * Get the constant used to enable the use of EC2 IAM roles.
174
  *
@@ -178,6 +285,15 @@ abstract class Provider {
178
  return AS3CF_Utils::get_first_defined_constant( static::$use_server_roles_constants );
179
  }
180
 
 
 
 
 
 
 
 
 
 
181
  /**
182
  * Returns the Provider's default region slug.
183
  *
@@ -187,6 +303,16 @@ abstract class Provider {
187
  return $this->default_region;
188
  }
189
 
 
 
 
 
 
 
 
 
 
 
190
 
191
  /**
192
  * Returns an array of valid region slugs and names.
@@ -194,9 +320,33 @@ abstract class Provider {
194
  * @return array Keys are region slug, values their name
195
  */
196
  public function get_regions() {
197
- $regions = apply_filters( $this->provider_short_name . '_get_regions', $this->regions ); // Backwards compatibility, e.g. 'aws_get_regions'.
198
 
199
- return apply_filters( 'as3cf_' . $this->provider_short_name . '_get_regions', $regions );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  }
201
 
202
  /**
@@ -212,7 +362,7 @@ abstract class Provider {
212
  }
213
 
214
  if ( is_null( $this->client ) ) {
215
- if ( ! $this->use_server_roles() ) {
216
  $args = array_merge( array(
217
  'credentials' => array(
218
  'key' => $this->get_access_key_id(),
@@ -223,8 +373,8 @@ abstract class Provider {
223
 
224
  // Add credentials and given args to default client args and then let user override.
225
  $args = array_merge( $this->default_client_args(), $args );
226
- $args = apply_filters( $this->provider_short_name . '_get_client_args', $args ); // Backwards compatibility, e.g. 'aws_get_client_args'.
227
- $args = apply_filters( 'as3cf_' . $this->provider_short_name . '_init_client_args', $args );
228
 
229
  $this->client = $this->init_client( $args );
230
  }
@@ -234,14 +384,19 @@ abstract class Provider {
234
  * Get the service client instance.
235
  *
236
  * @param array $args Options for required region/endpoint
 
237
  *
238
  * @return Provider
239
  * @throws Exception
240
  */
241
- public function get_client( Array $args ) {
 
 
 
 
242
  $this->_init_client( $args );
243
 
244
- $args = apply_filters( 'as3cf_' . $this->provider_short_name . '_' . $this->service_short_name . '_client_args', $args );
245
 
246
  $this->client = $this->init_service_client( $args );
247
 
@@ -260,8 +415,9 @@ abstract class Provider {
260
 
261
  foreach ( $regions as $region ) {
262
  try {
263
- // TODO: Rename element when going multi-provider.
264
- $region_keys = $region['s3client']->list_keys( $region['locations'] );
 
265
  } catch ( \Exception $e ) {
266
  AS3CF_Error::log( get_class( $e ) . ' exception caught when executing list_keys: ' . $e->getMessage() );
267
  continue;
@@ -292,6 +448,91 @@ abstract class Provider {
292
  return $protocol . '://' . $bucket . '/' . $key;
293
  }
294
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  /**
296
  * Returns default args array for the client.
297
  *
@@ -299,6 +540,15 @@ abstract class Provider {
299
  */
300
  abstract protected function default_client_args();
301
 
 
 
 
 
 
 
 
 
 
302
  /**
303
  * Instantiate a new client for the provider's SDK.
304
  *
@@ -306,6 +556,15 @@ abstract class Provider {
306
  */
307
  abstract protected function init_client( Array $args );
308
 
 
 
 
 
 
 
 
 
 
309
  /**
310
  * Instantiate a new service specific client.
311
  * Depending on SDK, may simply return client instantiated with `init_client`.
@@ -488,4 +747,28 @@ abstract class Provider {
488
  * @return bool|string Error message on unexpected exception
489
  */
490
  abstract public function can_write( $bucket, $key, $file_contents );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
491
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Providers;
4
 
5
  use AS3CF_Plugin_Base;
6
+ use AS3CF_Error;
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
  private $as3cf;
16
 
22
  /**
23
  * @var string
24
  */
25
+ protected static $provider_name = '';
26
 
27
  /**
28
  * @var string
29
  */
30
+ protected static $provider_short_name = '';
31
 
32
  /**
33
+ * Used in filters and settings.
34
+ *
35
+ * @var string
36
+ */
37
+ protected static $provider_key_name = '';
38
+
39
+ /**
40
+ * @var string
41
+ */
42
+ protected static $service_name = '';
43
+
44
+ /**
45
+ * @var string
46
+ */
47
+ protected static $service_short_name = '';
48
+
49
+ /**
50
+ * Used in filters and settings.
51
+ *
52
  * @var string
53
  */
54
+ protected static $service_key_name = '';
55
 
56
  /**
57
+ * Optional override of "Provider Name" + "Service Name" for friendly name for service.
58
+ *
59
  * @var string
60
  */
61
+ protected static $provider_service_name = '';
62
+
63
+ /**
64
+ * @var string
65
+ */
66
+ protected static $access_key_id_setting_name = 'access-key-id';
67
+
68
+ /**
69
+ * @var string
70
+ */
71
+ protected static $secret_access_key_setting_name = 'secret-access-key';
72
 
73
  /**
74
  * @var array
81
  protected static $secret_access_key_constants = array();
82
 
83
  /**
84
+ * If left empty, server roles not allowed.
85
+ *
86
  * @var array
87
  */
88
  protected static $use_server_roles_constants = array();
92
  */
93
  protected $regions = array();
94
 
95
+ /**
96
+ * @var bool
97
+ */
98
+ protected $region_required = false;
99
+
100
  /**
101
  * @var string
102
  */
103
  protected $default_region = '';
104
 
105
+ /**
106
+ * @var string
107
+ */
108
+ protected $default_domain = '';
109
+
110
+ /**
111
+ * @var string
112
+ */
113
+ protected $console_url = '';
114
+
115
+ /**
116
+ * @var string
117
+ */
118
+ protected $console_url_param = '';
119
+
120
  /**
121
  * Provider constructor.
122
  *
126
  $this->as3cf = $as3cf;
127
  }
128
 
129
+ /**
130
+ * Returns the full name for the provider.
131
+ *
132
+ * @return string
133
+ */
134
+ public static function get_provider_name() {
135
+ return static::$provider_name;
136
+ }
137
+
138
+ /**
139
+ * Returns the key friendly name for the provider.
140
+ *
141
+ * @return string
142
+ */
143
+ public static function get_provider_key_name() {
144
+ return static::$provider_key_name;
145
+ }
146
+
147
+ /**
148
+ * Returns the key friendly name for the service.
149
+ *
150
+ * @return string
151
+ */
152
+ public static function get_service_key_name() {
153
+ return static::$provider_key_name;
154
+ }
155
+
156
+ /**
157
+ * Returns the full name for the provider and service for display.
158
+ *
159
+ * @return string
160
+ */
161
+ public static function get_provider_service_name() {
162
+ if ( ! empty( static::$provider_service_name ) ) {
163
+ return static::$provider_service_name;
164
+ }
165
+
166
+ return static::$provider_name . ' ' . static::$service_name;
167
+ }
168
+
169
  /**
170
  * Whether or not access keys are needed.
171
  *
174
  * @return bool
175
  */
176
  public function needs_access_keys() {
177
+ if ( static::use_server_roles() ) {
178
  return false;
179
  }
180
 
186
  *
187
  * @return bool
188
  */
189
+ public function are_access_keys_set() {
190
  return $this->get_access_key_id() && $this->get_secret_access_key();
191
  }
192
 
198
  * @return string
199
  */
200
  public function get_access_key_id() {
201
+ if ( static::is_any_access_key_constant_defined() ) {
202
+ $constant = static::access_key_id_constant();
203
 
204
  return $constant ? constant( $constant ) : '';
205
  }
206
 
207
+ return $this->as3cf->get_core_setting( static::$access_key_id_setting_name );
208
  }
209
 
210
  /**
215
  * @return string
216
  */
217
  public function get_secret_access_key() {
218
+ if ( static::is_any_access_key_constant_defined() ) {
219
+ $constant = static::secret_access_key_constant();
220
 
221
  return $constant ? constant( $constant ) : '';
222
  }
223
 
224
+ return $this->as3cf->get_core_setting( static::$secret_access_key_setting_name );
225
  }
226
 
227
  /**
239
  *
240
  * @return bool
241
  */
242
+ public static function use_server_roles() {
243
+ if ( ! static::use_server_roles_allowed() ) {
244
+ return false;
245
+ }
246
+
247
+ $constant = static::use_server_role_constant();
248
 
249
  return $constant && constant( $constant );
250
  }
267
  return AS3CF_Utils::get_first_defined_constant( static::$secret_access_key_constants );
268
  }
269
 
270
+ /**
271
+ * Is the provider able to use server roles?
272
+ *
273
+ * @return bool
274
+ */
275
+ public static function use_server_roles_allowed() {
276
+ return ! empty( static::$use_server_roles_constants );
277
+ }
278
+
279
  /**
280
  * Get the constant used to enable the use of EC2 IAM roles.
281
  *
285
  return AS3CF_Utils::get_first_defined_constant( static::$use_server_roles_constants );
286
  }
287
 
288
+ /**
289
+ * Returns the Provider's default region slug.
290
+ *
291
+ * @return string
292
+ */
293
+ public function region_required() {
294
+ return $this->region_required;
295
+ }
296
+
297
  /**
298
  * Returns the Provider's default region slug.
299
  *
303
  return $this->default_region;
304
  }
305
 
306
+ /**
307
+ * Returns the Provider's base domain.
308
+ *
309
+ * Does not include region prefix or bucket path etc.
310
+ *
311
+ * @return string
312
+ */
313
+ public function get_domain() {
314
+ return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_domain', $this->default_domain );
315
+ }
316
 
317
  /**
318
  * Returns an array of valid region slugs and names.
320
  * @return array Keys are region slug, values their name
321
  */
322
  public function get_regions() {
323
+ $regions = apply_filters( static::$provider_key_name . '_get_regions', $this->regions ); // Backwards compatibility, e.g. 'aws_get_regions'.
324
 
325
+ return apply_filters( 'as3cf_' . static::$provider_key_name . '_get_regions', $regions );
326
+ }
327
+
328
+ /**
329
+ * Returns readable region name.
330
+ *
331
+ * @param string $region
332
+ * @param bool $with_key
333
+ *
334
+ * @return string
335
+ */
336
+ public function get_region_name( $region = '', $with_key = false ) {
337
+ if ( empty( $region ) && ! $this->region_required() ) {
338
+ $region = $this->get_default_region();
339
+ }
340
+
341
+ $regions = $this->get_regions();
342
+
343
+ $region_name = empty( $regions[ $region ] ) ? '' : $regions[ $region ];
344
+
345
+ if ( $with_key ) {
346
+ $region_name .= empty( $region_name ) ? $region : ' (' . $region . ')';
347
+ }
348
+
349
+ return $region_name;
350
  }
351
 
352
  /**
362
  }
363
 
364
  if ( is_null( $this->client ) ) {
365
+ if ( ! static::use_server_roles() ) {
366
  $args = array_merge( array(
367
  'credentials' => array(
368
  'key' => $this->get_access_key_id(),
373
 
374
  // Add credentials and given args to default client args and then let user override.
375
  $args = array_merge( $this->default_client_args(), $args );
376
+ $args = apply_filters( 'as3cf_' . static::$provider_key_name . '_init_client_args', $this->init_client_args( $args ) );
377
+ $args = apply_filters( static::$provider_key_name . '_get_client_args', $args ); // Backwards compatibility, e.g. 'aws_get_client_args'.
378
 
379
  $this->client = $this->init_client( $args );
380
  }
384
  * Get the service client instance.
385
  *
386
  * @param array $args Options for required region/endpoint
387
+ * @param bool $force
388
  *
389
  * @return Provider
390
  * @throws Exception
391
  */
392
+ public function get_client( Array $args, $force = false ) {
393
+ if ( true === $force ) {
394
+ $this->client = null;
395
+ }
396
+
397
  $this->_init_client( $args );
398
 
399
+ $args = apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_client_args', $this->init_service_client_args( $args ) );
400
 
401
  $this->client = $this->init_service_client( $args );
402
 
415
 
416
  foreach ( $regions as $region ) {
417
  try {
418
+ /* @var $client Provider */
419
+ $client = $region['provider_client'];
420
+ $region_keys = $client->list_keys( $region['locations'] );
421
  } catch ( \Exception $e ) {
422
  AS3CF_Error::log( get_class( $e ) . ' exception caught when executing list_keys: ' . $e->getMessage() );
423
  continue;
448
  return $protocol . '://' . $bucket . '/' . $key;
449
  }
450
 
451
+ /**
452
+ * Get the region specific prefix for URL
453
+ *
454
+ * @param string $region
455
+ * @param null|int $expires
456
+ *
457
+ * @return string
458
+ */
459
+ public function get_url_prefix( $region = '', $expires = null ) {
460
+ /**
461
+ * Region specific prefix for raw URL
462
+ *
463
+ * @param string $prefix
464
+ * @param string $region
465
+ * @param null|int $expires
466
+ *
467
+ * @return string
468
+ */
469
+ return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_url_prefix', $this->url_prefix( $region, $expires ), $region, $expires );
470
+ }
471
+
472
+ /**
473
+ * Get the url domain for the files
474
+ *
475
+ * @param string $bucket
476
+ * @param string $region
477
+ * @param int $expires
478
+ * @param array $args Allows you to specify custom URL settings
479
+ * @param bool $preview When generating the URL preview sanitize certain output
480
+ *
481
+ * @return string
482
+ */
483
+ public function get_url_domain( $bucket, $region = '', $expires = null, $args = array(), $preview = false ) {
484
+ if ( ! isset( $args['cloudfront'] ) ) {
485
+ $args['cloudfront'] = $this->as3cf->get_setting( 'cloudfront' );
486
+ }
487
+
488
+ if ( ! isset( $args['domain'] ) ) {
489
+ $args['domain'] = $this->as3cf->get_setting( 'domain' );
490
+ }
491
+
492
+ if ( ! isset( $args['force-https'] ) ) {
493
+ $args['force-https'] = $this->as3cf->use_ssl( $this->as3cf->get_setting( 'force-https' ) );
494
+ }
495
+
496
+ $prefix = $this->url_prefix( $region, $expires );
497
+ $domain = $this->get_domain();
498
+ $domain = empty( $prefix ) ? $domain : $prefix . '.' . $domain;
499
+
500
+ return apply_filters(
501
+ 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_url_domain',
502
+ $this->url_domain( $domain, $bucket, $region, $expires, $args, $preview ),
503
+ $bucket,
504
+ $region,
505
+ $expires,
506
+ $args,
507
+ $preview
508
+ );
509
+ }
510
+
511
+ /**
512
+ * Get the link to the bucket on the provider's console.
513
+ *
514
+ * @param string $bucket
515
+ * @param string $prefix
516
+ *
517
+ * @return string
518
+ */
519
+ public function get_console_url( $bucket = '', $prefix = '' ) {
520
+ if ( '' !== $prefix ) {
521
+ $prefix = $this->get_console_url_param() . urlencode( apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_prefix_value', $prefix ) );
522
+ }
523
+
524
+ return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url', $this->console_url ) . $bucket . $prefix;
525
+ }
526
+
527
+ /**
528
+ * Get the prefix param to append to the link to the bucket on the provider's console.
529
+ *
530
+ * @return string
531
+ */
532
+ public function get_console_url_param() {
533
+ return apply_filters( 'as3cf_' . static::$provider_key_name . '_' . static::$service_key_name . '_console_url_prefix_param', $this->console_url_param );
534
+ }
535
+
536
  /**
537
  * Returns default args array for the client.
538
  *
540
  */
541
  abstract protected function default_client_args();
542
 
543
+ /**
544
+ * Process the args before instantiating a new client for the provider's SDK.
545
+ *
546
+ * @param array $args
547
+ *
548
+ * @return array
549
+ */
550
+ abstract protected function init_client_args( Array $args );
551
+
552
  /**
553
  * Instantiate a new client for the provider's SDK.
554
  *
556
  */
557
  abstract protected function init_client( Array $args );
558
 
559
+ /**
560
+ * Process the args before instantiating a new service specific client.
561
+ *
562
+ * @param array $args
563
+ *
564
+ * @return array
565
+ */
566
+ abstract protected function init_service_client_args( Array $args );
567
+
568
  /**
569
  * Instantiate a new service specific client.
570
  * Depending on SDK, may simply return client instantiated with `init_client`.
747
  * @return bool|string Error message on unexpected exception
748
  */
749
  abstract public function can_write( $bucket, $key, $file_contents );
750
+
751
+ /**
752
+ * Get the region specific prefix for raw URL
753
+ *
754
+ * @param string $region
755
+ * @param null|int $expires
756
+ *
757
+ * @return string
758
+ */
759
+ abstract protected function url_prefix( $region = '', $expires = null );
760
+
761
+ /**
762
+ * Get the url domain for the files
763
+ *
764
+ * @param string $domain Likely prefixed with region
765
+ * @param string $bucket
766
+ * @param string $region
767
+ * @param int $expires
768
+ * @param array $args Allows you to specify custom URL settings
769
+ * @param bool $preview When generating the URL preview sanitize certain output
770
+ *
771
+ * @return string
772
+ */
773
+ abstract protected function url_domain( $domain, $bucket, $region = '', $expires = null, $args = array(), $preview = false );
774
  }
classes/providers/streams/aws-s3-stream-wrapper.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Providers\Streams;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\CacheInterface;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\S3\S3ClientInterface;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\S3\StreamWrapper;
8
- use DeliciousBrains\WP_Offload_S3\Providers\AWS_Provider;
9
 
10
  class AWS_S3_Stream_Wrapper extends StreamWrapper {
11
 
@@ -87,7 +87,8 @@ class AWS_S3_Stream_Wrapper extends StreamWrapper {
87
  // Set the ACL as public by default
88
  $options[ static::$wrapper ]['ACL'] = AWS_Provider::DEFAULT_ACL;
89
 
90
- $options = apply_filters( 'wpos3_stream_flush_params', $options );
 
91
 
92
  stream_context_set_option( $context, $options );
93
 
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
 
87
  // Set the ACL as public by default
88
  $options[ static::$wrapper ]['ACL'] = AWS_Provider::DEFAULT_ACL;
89
 
90
+ $options = apply_filters( 'wpos3_stream_flush_params', $options ); // Backwards compatibility
91
+ $options = apply_filters( 'as3cf_stream_flush_params', $options );
92
 
93
  stream_context_set_option( $context, $options );
94
 
classes/upgrades/exceptions/batch-limits-exceeded-exception.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Upgrades\Exceptions;
4
 
5
  class Batch_Limits_Exceeded_Exception extends \Exception {
6
 
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades\Exceptions;
4
 
5
  class Batch_Limits_Exceeded_Exception extends \Exception {
6
 
classes/upgrades/exceptions/no-more-blogs-exception.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Upgrades\Exceptions;
4
 
5
  class No_More_Blogs_Exception extends \Exception {
6
 
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades\Exceptions;
4
 
5
  class No_More_Blogs_Exception extends \Exception {
6
 
classes/upgrades/exceptions/too-many-errors-exception.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Upgrades\Exceptions;
4
 
5
  class Too_Many_Errors_Exception extends \Exception {
6
 
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades\Exceptions;
4
 
5
  class Too_Many_Errors_Exception extends \Exception {
6
 
classes/upgrades/network-upgrade.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Upgrades;
4
 
5
  use Amazon_S3_And_CloudFront;
6
 
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades;
4
 
5
  use Amazon_S3_And_CloudFront;
6
 
classes/upgrades/upgrade-content-replace-urls.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Upgrades;
4
 
5
  /**
6
  * Upgrade_Content_Replace_URLs Class
@@ -20,7 +20,7 @@ class Upgrade_Content_Replace_URLs extends Upgrade_Filter_Post {
20
  /**
21
  * @var string
22
  */
23
- protected $upgrade_name = 'replace_s3_urls';
24
 
25
  /**
26
  * @var string
@@ -68,15 +68,15 @@ class Upgrade_Content_Replace_URLs extends Upgrade_Filter_Post {
68
  $value = maybe_unserialize( $mod->option_value );
69
 
70
  if ( isset( $value['background_image'] ) ) {
71
- $value['background_image'] = $this->as3cf->filter_s3->filter_customizer_image( $value['background_image'] );
72
  }
73
 
74
  if ( isset( $value['header_image'] ) ) {
75
- $value['header_image'] = $this->as3cf->filter_s3->filter_customizer_image( $value['header_image'] );
76
  }
77
 
78
  if ( isset( $value['header_image_data'] ) ) {
79
- $value['header_image_data'] = $this->as3cf->filter_s3->filter_header_image_data( $value['header_image_data'] );
80
  }
81
 
82
  $value = maybe_serialize( $value );
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades;
4
 
5
  /**
6
  * Upgrade_Content_Replace_URLs Class
20
  /**
21
  * @var string
22
  */
23
+ protected $upgrade_name = 'replace_provider_urls';
24
 
25
  /**
26
  * @var string
68
  $value = maybe_unserialize( $mod->option_value );
69
 
70
  if ( isset( $value['background_image'] ) ) {
71
+ $value['background_image'] = $this->as3cf->filter_provider->filter_customizer_image( $value['background_image'] );
72
  }
73
 
74
  if ( isset( $value['header_image'] ) ) {
75
+ $value['header_image'] = $this->as3cf->filter_provider->filter_customizer_image( $value['header_image'] );
76
  }
77
 
78
  if ( isset( $value['header_image_data'] ) ) {
79
+ $value['header_image_data'] = $this->as3cf->filter_provider->filter_header_image_data( $value['header_image_data'] );
80
  }
81
 
82
  $value = maybe_serialize( $value );
classes/upgrades/upgrade-edd-replace-urls.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Upgrades;
4
 
5
  /**
6
  * Upgrade_EDD_Replace_URLs Class
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades;
4
 
5
  /**
6
  * Upgrade_EDD_Replace_URLs Class
classes/upgrades/upgrade-file-sizes.php CHANGED
@@ -9,7 +9,7 @@
9
  * @since 0.9.3
10
  */
11
 
12
- namespace DeliciousBrains\WP_Offload_S3\Upgrades;
13
 
14
  use AS3CF_Error;
15
  use Exception;
@@ -56,15 +56,15 @@ class Upgrade_File_Sizes extends Upgrade {
56
  * @return bool
57
  */
58
  protected function upgrade_item( $attachment ) {
59
- $s3object = unserialize( $attachment->s3object );
60
- if ( false === $s3object ) {
61
- AS3CF_Error::log( 'Failed to unserialize S3 meta for attachment ' . $attachment->ID . ': ' . $attachment->s3object );
62
  $this->error_count++;
63
 
64
  return false;
65
  }
66
 
67
- $region = $this->as3cf->get_s3object_region( $s3object );
68
  if ( is_wp_error( $region ) ) {
69
  AS3CF_Error::log( 'Failed to get the region for the bucket of the attachment ' . $attachment->ID );
70
  $this->error_count++;
@@ -72,25 +72,25 @@ class Upgrade_File_Sizes extends Upgrade {
72
  return false;
73
  }
74
 
75
- $s3client = $this->as3cf->get_s3client( $region, true );
76
- $main_file = $s3object['key'];
77
 
78
  $ext = pathinfo( $main_file, PATHINFO_EXTENSION );
79
- $prefix = trailingslashit( dirname( $s3object['key'] ) );
80
 
81
  // Used to search S3 for all files related to an attachment
82
  $search_prefix = $prefix . wp_basename( $main_file, ".$ext" );
83
 
84
  $args = array(
85
- 'Bucket' => $s3object['bucket'],
86
  'Prefix' => $search_prefix,
87
  );
88
 
89
  try {
90
  // List objects for the attachment
91
- $result = $s3client->list_objects( $args );
92
  } catch ( Exception $e ) {
93
- AS3CF_Error::log( 'Error listing objects of prefix ' . $search_prefix . ' for attachment ' . $attachment->ID . ' from S3: ' . $e->getMessage() );
94
  $this->error_count++;
95
 
96
  return false;
@@ -145,7 +145,7 @@ class Upgrade_File_Sizes extends Upgrade {
145
  * @return array
146
  */
147
  protected function get_items_to_process( $prefix, $limit, $offset = false ) {
148
- $all_attachments = $this->get_s3_attachments( $prefix, $limit );
149
  $attachments = array();
150
 
151
  foreach ( $all_attachments as $attachment ) {
@@ -166,10 +166,10 @@ class Upgrade_File_Sizes extends Upgrade {
166
  *
167
  * @return mixed
168
  */
169
- protected function get_s3_attachments( $prefix, $limit = null ) {
170
  global $wpdb;
171
 
172
- $sql = "SELECT pm1.`post_id` as `ID`, pm1.`meta_value` AS 's3object'
173
  FROM `{$prefix}postmeta` pm1
174
  LEFT OUTER JOIN `{$prefix}postmeta` pm2
175
  ON pm1.`post_id` = pm2.`post_id`
9
  * @since 0.9.3
10
  */
11
 
12
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades;
13
 
14
  use AS3CF_Error;
15
  use Exception;
56
  * @return bool
57
  */
58
  protected function upgrade_item( $attachment ) {
59
+ $provider_object = unserialize( $attachment->provider_object );
60
+ if ( false === $provider_object ) {
61
+ AS3CF_Error::log( 'Failed to unserialize offload meta for attachment ' . $attachment->ID . ': ' . $attachment->provider_object );
62
  $this->error_count++;
63
 
64
  return false;
65
  }
66
 
67
+ $region = $this->as3cf->get_provider_object_region( $provider_object );
68
  if ( is_wp_error( $region ) ) {
69
  AS3CF_Error::log( 'Failed to get the region for the bucket of the attachment ' . $attachment->ID );
70
  $this->error_count++;
72
  return false;
73
  }
74
 
75
+ $provider_client = $this->as3cf->get_provider_client( $region, true );
76
+ $main_file = $provider_object['key'];
77
 
78
  $ext = pathinfo( $main_file, PATHINFO_EXTENSION );
79
+ $prefix = trailingslashit( dirname( $provider_object['key'] ) );
80
 
81
  // Used to search S3 for all files related to an attachment
82
  $search_prefix = $prefix . wp_basename( $main_file, ".$ext" );
83
 
84
  $args = array(
85
+ 'Bucket' => $provider_object['bucket'],
86
  'Prefix' => $search_prefix,
87
  );
88
 
89
  try {
90
  // List objects for the attachment
91
+ $result = $provider_client->list_objects( $args );
92
  } catch ( Exception $e ) {
93
+ AS3CF_Error::log( 'Error listing objects of prefix ' . $search_prefix . ' for attachment ' . $attachment->ID . ' in bucket: ' . $e->getMessage() );
94
  $this->error_count++;
95
 
96
  return false;
145
  * @return array
146
  */
147
  protected function get_items_to_process( $prefix, $limit, $offset = false ) {
148
+ $all_attachments = $this->get_provider_attachments( $prefix, $limit );
149
  $attachments = array();
150
 
151
  foreach ( $all_attachments as $attachment ) {
166
  *
167
  * @return mixed
168
  */
169
+ protected function get_provider_attachments( $prefix, $limit = null ) {
170
  global $wpdb;
171
 
172
+ $sql = "SELECT pm1.`post_id` as `ID`, pm1.`meta_value` AS 'provider_object'
173
  FROM `{$prefix}postmeta` pm1
174
  LEFT OUTER JOIN `{$prefix}postmeta` pm2
175
  ON pm1.`post_id` = pm2.`post_id`
classes/upgrades/upgrade-filter-post-excerpt.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Upgrades;
4
 
5
  /**
6
  * Upgrade_Filter_Post_Excerpt Class
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades;
4
 
5
  /**
6
  * Upgrade_Filter_Post_Excerpt Class
classes/upgrades/upgrade-filter-post.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Upgrades;
4
 
5
  use AS3CF_Utils;
6
- use DeliciousBrains\WP_Offload_S3\Upgrades\Exceptions\Batch_Limits_Exceeded_Exception;
7
- use DeliciousBrains\WP_Offload_S3\Upgrades\Exceptions\Too_Many_Errors_Exception;
8
 
9
  /**
10
  * Upgrade_Filter_Post Class
@@ -395,7 +395,7 @@ abstract class Upgrade_Filter_Post extends Upgrade {
395
  */
396
  protected function get_generic_message() {
397
  $link_text = __( 'See our documentation', 'amazon-s3-and-cloudfront' );
398
- $url = $this->as3cf->dbrains_url( '/wp-offload-s3/doc/content-filtering-upgrade', array(
399
  'utm_campaign' => 'support+docs',
400
  ) );
401
  $link = AS3CF_Utils::dbrains_link( $url, $link_text );
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades;
4
 
5
  use AS3CF_Utils;
6
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Exceptions\Batch_Limits_Exceeded_Exception;
7
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Exceptions\Too_Many_Errors_Exception;
8
 
9
  /**
10
  * Upgrade_Filter_Post Class
395
  */
396
  protected function get_generic_message() {
397
  $link_text = __( 'See our documentation', 'amazon-s3-and-cloudfront' );
398
+ $url = $this->as3cf->dbrains_url( '/wp-offload-media/doc/content-filtering-upgrade', array(
399
  'utm_campaign' => 'support+docs',
400
  ) );
401
  $link = AS3CF_Utils::dbrains_link( $url, $link_text );
classes/upgrades/upgrade-meta-wp-error.php CHANGED
@@ -9,7 +9,7 @@
9
  * @since 0.9.5
10
  */
11
 
12
- namespace DeliciousBrains\WP_Offload_S3\Upgrades;
13
 
14
  use AS3CF_Error;
15
  use Exception;
@@ -57,9 +57,9 @@ class Upgrade_Meta_WP_Error extends Upgrade {
57
  * @return bool
58
  */
59
  protected function upgrade_item( $attachment ) {
60
- $s3object = unserialize( $attachment->s3object );
61
- if ( false === $s3object ) {
62
- AS3CF_Error::log( 'Failed to unserialize S3 meta for attachment ' . $attachment->ID . ': ' . $attachment->s3object );
63
  $this->error_count++;
64
 
65
  return false;
@@ -72,13 +72,13 @@ class Upgrade_Meta_WP_Error extends Upgrade {
72
  // regenerate the attachment metadata
73
  try {
74
  $args = array(
75
- 'Bucket' => $s3object['bucket'],
76
- 'Key' => $s3object['key'],
77
  'SaveAs' => $file,
78
  );
79
- $this->as3cf->get_s3client( $s3object['region'], true )->get_object( $args );
80
  } catch ( Exception $e ) {
81
- AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from S3: %s', 'amazon-s3-and-cloudfront' ), $s3object['key'], $e->getMessage() ) );
82
 
83
  return false;
84
  }
@@ -143,7 +143,7 @@ class Upgrade_Meta_WP_Error extends Upgrade {
143
  return $wpdb->get_var( $sql );
144
  }
145
 
146
- $sql = "SELECT pm1.`post_id` as `ID`, pm1.`meta_value` AS 's3object'" . $sql;
147
 
148
  if ( $limit && $limit > 0 ) {
149
  $sql .= sprintf( ' LIMIT %d', (int) $limit );
9
  * @since 0.9.5
10
  */
11
 
12
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades;
13
 
14
  use AS3CF_Error;
15
  use Exception;
57
  * @return bool
58
  */
59
  protected function upgrade_item( $attachment ) {
60
+ $provider_object = unserialize( $attachment->provider_object );
61
+ if ( false === $provider_object ) {
62
+ AS3CF_Error::log( 'Failed to unserialize offload meta for attachment ' . $attachment->ID . ': ' . $attachment->provider_object );
63
  $this->error_count++;
64
 
65
  return false;
72
  // regenerate the attachment metadata
73
  try {
74
  $args = array(
75
+ 'Bucket' => $provider_object['bucket'],
76
+ 'Key' => $provider_object['key'],
77
  'SaveAs' => $file,
78
  );
79
+ $this->as3cf->get_provider_client( $provider_object['region'], true )->get_object( $args );
80
  } catch ( Exception $e ) {
81
+ AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from the bucket: %s', 'amazon-s3-and-cloudfront' ), $provider_object['key'], $e->getMessage() ) );
82
 
83
  return false;
84
  }
143
  return $wpdb->get_var( $sql );
144
  }
145
 
146
+ $sql = "SELECT pm1.`post_id` as `ID`, pm1.`meta_value` AS 'provider_object'" . $sql;
147
 
148
  if ( $limit && $limit > 0 ) {
149
  $sql .= sprintf( ' LIMIT %d', (int) $limit );
classes/upgrades/upgrade-region-meta.php CHANGED
@@ -9,7 +9,7 @@
9
  * @since 0.6.2
10
  */
11
 
12
- namespace DeliciousBrains\WP_Offload_S3\Upgrades;
13
 
14
  use AS3CF_Error;
15
 
@@ -43,7 +43,7 @@ class Upgrade_Region_Meta extends Upgrade {
43
  * @return string
44
  */
45
  protected function get_running_update_text() {
46
- return __( 'and updating the metadata with the bucket region it is served from. This will allow us to serve your files from the proper S3 region subdomain <span style="white-space:nowrap;">(e.g. s3-us-west-2.amazonaws.com)</span>.', 'amazon-s3-and-cloudfront' );
47
  }
48
 
49
  /**
@@ -54,15 +54,15 @@ class Upgrade_Region_Meta extends Upgrade {
54
  * @return bool
55
  */
56
  protected function upgrade_item( $attachment ) {
57
- $s3object = unserialize( $attachment->s3object );
58
- if ( false === $s3object ) {
59
- AS3CF_Error::log( 'Failed to unserialize S3 meta for attachment ' . $attachment->ID . ': ' . $attachment->s3object );
60
  $this->error_count++;
61
 
62
  return false;
63
  }
64
  // retrieve region and update the attachment metadata
65
- $region = $this->as3cf->get_s3object_region( $s3object, $attachment->ID );
66
  if ( is_wp_error( $region ) ) {
67
  AS3CF_Error::log( 'Error updating region: ' . $region->get_error_message() );
68
  $this->error_count++;
@@ -133,7 +133,7 @@ class Upgrade_Region_Meta extends Upgrade {
133
  return $wpdb->get_var( $sql );
134
  }
135
 
136
- $sql = "SELECT `post_id` as `ID`, `meta_value` AS 's3object'" . $sql;
137
 
138
  if ( $limit && $limit > 0 ) {
139
  $sql .= sprintf( ' LIMIT %d', (int) $limit );
9
  * @since 0.6.2
10
  */
11
 
12
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades;
13
 
14
  use AS3CF_Error;
15
 
43
  * @return string
44
  */
45
  protected function get_running_update_text() {
46
+ return __( 'and updating the metadata with the bucket region it is served from. This will allow us to serve your files from the proper region subdomain <span style="white-space:nowrap;">(e.g. s3-us-west-2.amazonaws.com)</span>.', 'amazon-s3-and-cloudfront' );
47
  }
48
 
49
  /**
54
  * @return bool
55
  */
56
  protected function upgrade_item( $attachment ) {
57
+ $provider_object = unserialize( $attachment->provider_object );
58
+ if ( false === $provider_object ) {
59
+ AS3CF_Error::log( 'Failed to unserialize offload meta for attachment ' . $attachment->ID . ': ' . $attachment->provider_object );
60
  $this->error_count++;
61
 
62
  return false;
63
  }
64
  // retrieve region and update the attachment metadata
65
+ $region = $this->as3cf->get_provider_object_region( $provider_object, $attachment->ID );
66
  if ( is_wp_error( $region ) ) {
67
  AS3CF_Error::log( 'Error updating region: ' . $region->get_error_message() );
68
  $this->error_count++;
133
  return $wpdb->get_var( $sql );
134
  }
135
 
136
+ $sql = "SELECT `post_id` as `ID`, `meta_value` AS 'provider_object'" . $sql;
137
 
138
  if ( $limit && $limit > 0 ) {
139
  $sql .= sprintf( ' LIMIT %d', (int) $limit );
classes/upgrades/upgrade-wpos3-to-as3cf.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades;
4
+
5
+ use AS3CF_Error;
6
+ use Exception;
7
+
8
+ /**
9
+ * Upgrade_WPOS3_To_AS3CF Class
10
+ *
11
+ * This class handles updating records to use as3cf prefixed keys instead of wpos3 prefixed keys.
12
+ */
13
+ class Upgrade_WPOS3_To_AS3CF extends Upgrade {
14
+
15
+ /**
16
+ * @var int
17
+ */
18
+ protected $upgrade_id = 7;
19
+
20
+ /**
21
+ * @var string
22
+ */
23
+ protected $upgrade_name = 'wpos3_to_as3cf';
24
+
25
+ /**
26
+ * @var string 'metadata', 'attachment'
27
+ */
28
+ protected $upgrade_type = 'metadata';
29
+
30
+ /**
31
+ * Get running update text.
32
+ *
33
+ * @return string
34
+ */
35
+ protected function get_running_update_text() {
36
+ return __( 'and updating the metadata to use key names compatible with the current version.', 'amazon-s3-and-cloudfront' );
37
+ }
38
+
39
+ /**
40
+ * update record key to use as3cf prefix instead of wpos3.
41
+ *
42
+ * @param mixed $item
43
+ *
44
+ * @return bool
45
+ */
46
+ protected function upgrade_item( $item ) {
47
+ global $wpdb;
48
+
49
+ $old = $item->the_value;
50
+ $new = substr_replace( $old, 'as3cf_', 0, strlen( 'wpos3_' ) );
51
+
52
+ try {
53
+ $result = $wpdb->update( $wpdb->{$item->the_table}, array( $item->the_field => $new ), array( $item->the_field => $old ) );
54
+ } catch ( Exception $e ) {
55
+ AS3CF_Error::log( 'Error updating ' . $item->the_table . ' records with key ' . $old . ' to use key ' . $new . ': ' . $e->getMessage() );
56
+ $this->error_count++;
57
+
58
+ return false;
59
+ }
60
+
61
+ if ( false === $result || 1 > $result ) {
62
+ AS3CF_Error::log( 'Incorrect number of ' . $item->the_table . ' records with key ' . $old . ' updated to use key ' . $new . '.' );
63
+ $this->error_count++;
64
+
65
+ return false;
66
+ }
67
+
68
+ return true;
69
+ }
70
+
71
+ /**
72
+ * Get all record keys that need changing.
73
+ *
74
+ * @param string $prefix
75
+ * @param int $limit
76
+ * @param bool|mixed $offset
77
+ *
78
+ * @return array
79
+ */
80
+ protected function get_items_to_process( $prefix, $limit, $offset = false ) {
81
+ global $wpdb;
82
+
83
+ $sql = "SELECT DISTINCT 'postmeta' AS the_table, 'meta_key' AS the_field, pm.`meta_key` AS the_value
84
+ FROM `{$prefix}postmeta` pm
85
+ WHERE pm.`meta_key` LIKE 'wpos3_%'
86
+ UNION
87
+ SELECT DISTINCT 'options' AS the_table, 'option_name' AS the_field, o.`option_name` AS the_value
88
+ FROM `{$prefix}options` o
89
+ WHERE o.`option_name` LIKE 'wpos3_%'
90
+ ";
91
+
92
+ if ( is_multisite() ) {
93
+ $sql .= "
94
+ UNION
95
+ SELECT DISTINCT 'sitemeta' AS the_table, 'meta_key' AS the_field, sm.`meta_key` AS the_value
96
+ FROM `{$wpdb->sitemeta}` sm
97
+ WHERE sm.`meta_key` LIKE 'wpos3_%'
98
+ ";
99
+ }
100
+
101
+ if ( $limit && $limit > 0 ) {
102
+ $sql .= sprintf( ' LIMIT %d', (int) $limit );
103
+ }
104
+
105
+ return $wpdb->get_results( $sql, OBJECT );
106
+ }
107
+ }
classes/upgrades/upgrade.php CHANGED
@@ -9,12 +9,12 @@
9
  * @since 0.6.2
10
  */
11
 
12
- namespace DeliciousBrains\WP_Offload_S3\Upgrades;
13
 
14
  use Amazon_S3_And_CloudFront;
15
- use DeliciousBrains\WP_Offload_S3\Upgrades\Exceptions\No_More_Blogs_Exception;
16
- use DeliciousBrains\WP_Offload_S3\Upgrades\Exceptions\Batch_Limits_Exceeded_Exception;
17
- use DeliciousBrains\WP_Offload_S3\Upgrades\Exceptions\Too_Many_Errors_Exception;
18
  use WP_Error;
19
 
20
  /**
@@ -437,7 +437,7 @@ abstract class Upgrade {
437
  * @return string
438
  */
439
  protected function get_running_message() {
440
- return sprintf( __( '<strong>Running %1$s Update%2$s</strong> &mdash; We&#8217;re going through all the Media Library items uploaded to S3 %3$s This will be done quietly in the background, processing a small batch of Media Library items every %4$d minutes. There should be no noticeable impact on your server&#8217;s performance.', 'amazon-s3-and-cloudfront' ),
441
  ucwords( $this->upgrade_type ),
442
  $this->get_progress_text(),
443
  $this->running_update_text,
@@ -464,7 +464,7 @@ abstract class Upgrade {
464
  * @return string
465
  */
466
  protected function get_error_message() {
467
- return sprintf( __( '<strong>Error Updating %1$s</strong> &mdash; We ran into some errors attempting to update the %2$s for all your Media Library items that have been uploaded to S3. Please check your error log for details. (#%3$d)', 'amazon-s3-and-cloudfront' ),
468
  ucwords( $this->upgrade_type ),
469
  $this->upgrade_type,
470
  $this->upgrade_id
9
  * @since 0.6.2
10
  */
11
 
12
+ namespace DeliciousBrains\WP_Offload_Media\Upgrades;
13
 
14
  use Amazon_S3_And_CloudFront;
15
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Exceptions\No_More_Blogs_Exception;
16
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Exceptions\Batch_Limits_Exceeded_Exception;
17
+ use DeliciousBrains\WP_Offload_Media\Upgrades\Exceptions\Too_Many_Errors_Exception;
18
  use WP_Error;
19
 
20
  /**
437
  * @return string
438
  */
439
  protected function get_running_message() {
440
+ return sprintf( __( '<strong>Running %1$s Update%2$s</strong> &mdash; We&#8217;re going through all the offloaded Media Library items %3$s This will be done quietly in the background, processing a small batch of Media Library items every %4$d minutes. There should be no noticeable impact on your server&#8217;s performance.', 'amazon-s3-and-cloudfront' ),
441
  ucwords( $this->upgrade_type ),
442
  $this->get_progress_text(),
443
  $this->running_update_text,
464
  * @return string
465
  */
466
  protected function get_error_message() {
467
+ return sprintf( __( '<strong>Error Updating %1$s</strong> &mdash; We ran into some errors attempting to update the %2$s for all your Media Library items that have been offloaded. Please check your error log for details. (#%3$d)', 'amazon-s3-and-cloudfront' ),
468
  ucwords( $this->upgrade_type ),
469
  $this->upgrade_type,
470
  $this->upgrade_id
composer.json CHANGED
@@ -3,8 +3,8 @@
3
  "type": "wordpress-plugin",
4
  "homepage": "https://github.com/deliciousbrains/wp-amazon-s3-and-cloudfront",
5
  "license": "GPL-3.0-only",
6
- "description": "Automatically copies media uploads to Amazon S3 for delivery. Optionally configure Amazon CloudFront for even faster delivery.",
7
- "keywords": ["plugin","amazon-web-services","s3","cloudfront","cdn"],
8
  "require": {
9
  "composer/installers": "^1.0"
10
  }
3
  "type": "wordpress-plugin",
4
  "homepage": "https://github.com/deliciousbrains/wp-amazon-s3-and-cloudfront",
5
  "license": "GPL-3.0-only",
6
+ "description": "Automatically copies media uploads to a storage provider's bucket for delivery. Optionally configure a CDN for even faster delivery.",
7
+ "keywords": ["plugin","amazon-web-services","s3","cloudfront","cdn","digitalocean","spaces"],
8
  "require": {
9
  "composer/installers": "^1.0"
10
  }
languages/amazon-s3-and-cloudfront-en.pot CHANGED
@@ -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: 2018-08-02 10:25+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,198 +17,188 @@ msgstr ""
17
  "Content-Type: text/plain; charset=UTF-8\n"
18
  "Content-Transfer-Encoding: 8bit\n"
19
 
20
- #: classes/amazon-s3-and-cloudfront.php:114
21
- #: classes/amazon-s3-and-cloudfront.php:115
22
- msgid "Offload S3"
23
  msgstr ""
24
 
25
- #: classes/amazon-s3-and-cloudfront.php:256
26
- #: view/bucket-setting.php:17
27
- #: view/settings/settings.php:76
28
- #: view/settings/settings.php:93
29
- msgid "defined in wp-config.php"
30
- msgstr ""
31
-
32
- #: classes/amazon-s3-and-cloudfront.php:782
33
- msgid "Access keys updated successfully."
34
- msgstr ""
35
-
36
- #: classes/amazon-s3-and-cloudfront.php:787
37
- msgid ""
38
- "All access key constants must be removed before keys can be set in the "
39
- "database."
40
  msgstr ""
41
 
42
- #: classes/amazon-s3-and-cloudfront.php:795
43
- msgid "The Access Key ID must be set."
44
- msgstr ""
45
-
46
- #: classes/amazon-s3-and-cloudfront.php:800
47
- #: classes/amazon-s3-and-cloudfront.php:2859
48
- #: view/settings/settings.php:88
49
- msgctxt "placeholder for hidden access key, 39 char max"
50
- msgid "-- not shown --"
51
- msgstr ""
52
-
53
- #: classes/amazon-s3-and-cloudfront.php:804
54
- msgid "The Secret Access Key must be at least 40 characters long."
55
- msgstr ""
56
-
57
- #: classes/amazon-s3-and-cloudfront.php:825
58
- msgid "Access keys removed from the database successfully."
59
  msgstr ""
60
 
61
- #: classes/amazon-s3-and-cloudfront.php:1013
62
- #: classes/amazon-s3-and-cloudfront.php:1145
63
  #, php-format
64
  msgid "File %s does not exist"
65
  msgstr ""
66
 
67
- #: classes/amazon-s3-and-cloudfront.php:1026
68
  #, php-format
69
  msgid "Mime type %s is not allowed"
70
  msgstr ""
71
 
72
- #: classes/amazon-s3-and-cloudfront.php:1109
73
- #: classes/amazon-s3-and-cloudfront.php:1153
 
 
 
 
74
  #, php-format
75
- msgid "Error uploading %s to S3: %s"
76
  msgstr ""
77
 
78
- #: classes/amazon-s3-and-cloudfront.php:2334
79
  msgid "This action can only be performed through an admin screen."
80
  msgstr ""
81
 
82
- #: classes/amazon-s3-and-cloudfront.php:2336
83
  msgid "Cheatin&#8217; eh?"
84
  msgstr ""
85
 
86
- #: classes/amazon-s3-and-cloudfront.php:2338
87
  msgid "You do not have sufficient permissions to access this page."
88
  msgstr ""
89
 
90
- #: classes/amazon-s3-and-cloudfront.php:2356
 
 
 
 
91
  msgid "No bucket name provided."
92
  msgstr ""
93
 
94
- #: classes/amazon-s3-and-cloudfront.php:2667
95
  msgid "Error Getting Bucket Region"
96
  msgstr ""
97
 
98
- #: classes/amazon-s3-and-cloudfront.php:2668
99
  #, php-format
100
  msgid "There was an error attempting to get the region of the bucket %s: %s"
101
  msgstr ""
102
 
103
- #: classes/amazon-s3-and-cloudfront.php:2781
104
  msgid ""
105
  "This is a test file to check if the user has write permission to S3. Delete "
106
  "me if found."
107
  msgstr ""
108
 
109
- #: classes/amazon-s3-and-cloudfront.php:2787
110
  #, php-format
111
  msgid ""
112
  "There was an error attempting to check the permissions of the bucket %s: %s"
113
  msgstr ""
114
 
115
- #: classes/amazon-s3-and-cloudfront.php:2849
116
  msgid "Error creating bucket"
117
  msgstr ""
118
 
119
- #: classes/amazon-s3-and-cloudfront.php:2850
120
  msgid "Bucket name too short."
121
  msgstr ""
122
 
123
- #: classes/amazon-s3-and-cloudfront.php:2851
124
  msgid "Bucket name too long."
125
  msgstr ""
126
 
127
- #: classes/amazon-s3-and-cloudfront.php:2852
128
  msgid ""
129
  "Invalid character. Bucket names can contain lowercase letters, numbers, "
130
  "periods and hyphens."
131
  msgstr ""
132
 
133
- #: classes/amazon-s3-and-cloudfront.php:2853
134
  msgid "Error saving bucket"
135
  msgstr ""
136
 
137
- #: classes/amazon-s3-and-cloudfront.php:2854
138
  msgid "Error fetching buckets"
139
  msgstr ""
140
 
141
- #: classes/amazon-s3-and-cloudfront.php:2855
142
  msgid "Error getting URL preview: "
143
  msgstr ""
144
 
145
- #: classes/amazon-s3-and-cloudfront.php:2856
146
  msgid "The changes you made will be lost if you navigate away from this page"
147
  msgstr ""
148
 
149
- #: classes/amazon-s3-and-cloudfront.php:2857
150
  msgid "Getting diagnostic info..."
151
  msgstr ""
152
 
153
- #: classes/amazon-s3-and-cloudfront.php:2858
154
  msgid "Error getting diagnostic info: "
155
  msgstr ""
156
 
157
- #: classes/amazon-s3-and-cloudfront.php:2861
158
- #: classes/amazon-s3-and-cloudfront.php:4591
 
 
 
 
 
159
  msgid "Settings saved."
160
  msgstr ""
161
 
162
- #: classes/amazon-s3-and-cloudfront.php:2932
163
  msgid "Cheatin' eh?"
164
  msgstr ""
165
 
166
- #: classes/amazon-s3-and-cloudfront.php:2981
 
 
 
 
 
 
167
  msgctxt "Show the media library tab"
168
  msgid "Media Library"
169
  msgstr ""
170
 
171
- #: classes/amazon-s3-and-cloudfront.php:2982
172
  msgctxt "Show the addons tab"
173
  msgid "Addons"
174
  msgstr ""
175
 
176
- #: classes/amazon-s3-and-cloudfront.php:2983
177
- msgctxt "Show the settings tab"
178
- msgid "Settings"
179
- msgstr ""
180
-
181
- #: classes/amazon-s3-and-cloudfront.php:2984
182
  msgctxt "Show the support tab"
183
  msgid "Support"
184
  msgstr ""
185
 
186
- #: classes/amazon-s3-and-cloudfront.php:3228
187
  #, php-format
188
  msgid ""
189
- "<strong>WP Offload S3</strong> &mdash; The file %s has been given %s "
190
- "permissions on Amazon S3."
191
  msgstr ""
192
 
193
- #: classes/amazon-s3-and-cloudfront.php:3247
194
  msgid ""
195
- "<strong>WP Offload S3 Requirement Missing</strong> &mdash; Looks like you "
196
  "don't have an image manipulation library installed on this server and "
197
  "configured with PHP. You may run into trouble if you try to edit images. "
198
  "Please setup GD or ImageMagick."
199
  msgstr ""
200
 
201
- #: classes/amazon-s3-and-cloudfront.php:3871
202
  #, php-format
203
  msgid ""
204
- "<a href=\"%s\">Define your AWS keys</a> to enable write access to the bucket"
 
205
  msgstr ""
206
 
207
- #: classes/amazon-s3-and-cloudfront.php:3878
208
  msgid "Quick Start Guide"
209
  msgstr ""
210
 
211
- #: classes/amazon-s3-and-cloudfront.php:3880
212
  #, php-format
213
  msgid ""
214
  "Looks like we don't have write access to this bucket. It's likely that the "
@@ -217,7 +207,7 @@ msgid ""
217
  "correctly."
218
  msgstr ""
219
 
220
- #: classes/amazon-s3-and-cloudfront.php:3882
221
  #, php-format
222
  msgid ""
223
  "Looks like we don't have access to the buckets. It's likely that the user "
@@ -225,39 +215,39 @@ msgid ""
225
  "Please see our %s for instructions on setting up permissions correctly."
226
  msgstr ""
227
 
228
- #: classes/amazon-s3-and-cloudfront.php:4032
229
- msgid "WP Offload S3 Activation"
230
  msgstr ""
231
 
232
- #: classes/amazon-s3-and-cloudfront.php:4033
233
  msgid ""
234
- "WP Offload S3 Lite and WP Offload S3 cannot both be active. We've "
235
- "automatically deactivated WP Offload S3 Lite."
236
  msgstr ""
237
 
238
- #: classes/amazon-s3-and-cloudfront.php:4035
239
- msgid "WP Offload S3 Lite Activation"
240
  msgstr ""
241
 
242
- #: classes/amazon-s3-and-cloudfront.php:4036
243
  msgid ""
244
- "WP Offload S3 Lite and WP Offload S3 cannot both be active. We've "
245
- "automatically deactivated WP Offload S3."
246
  msgstr ""
247
 
248
- #: classes/amazon-s3-and-cloudfront.php:4088
249
  msgid "More&nbsp;info&nbsp;&raquo;"
250
  msgstr ""
251
 
252
- #: classes/amazon-s3-and-cloudfront.php:4183
253
  msgid "this doc"
254
  msgstr ""
255
 
256
- #: classes/amazon-s3-and-cloudfront.php:4185
257
- msgid "WP Offload S3 Feature Removed"
258
  msgstr ""
259
 
260
- #: classes/amazon-s3-and-cloudfront.php:4186
261
  #, php-format
262
  msgid ""
263
  "You had the \"Always non-SSL\" option selected in your settings, but we've "
@@ -268,66 +258,76 @@ msgid ""
268
  "to the old behavior."
269
  msgstr ""
270
 
271
- #: classes/amazon-s3-and-cloudfront.php:4216
272
- #: classes/amazon-s3-and-cloudfront.php:4325
273
- msgid "Amazon S3"
 
 
 
 
274
  msgstr ""
275
 
276
- #: classes/amazon-s3-and-cloudfront.php:4326
277
- msgctxt "Amazon S3 bucket"
 
 
 
 
 
278
  msgid "Bucket"
279
  msgstr ""
280
 
281
- #: classes/amazon-s3-and-cloudfront.php:4327
282
- msgctxt "Path to file on Amazon S3"
283
  msgid "Path"
284
  msgstr ""
285
 
286
- #: classes/amazon-s3-and-cloudfront.php:4328
287
- msgctxt "Location of Amazon S3 bucket"
288
  msgid "Region"
289
  msgstr ""
290
 
291
- #: classes/amazon-s3-and-cloudfront.php:4329
292
- msgctxt "Access control list of the file on Amazon S3"
293
  msgid "Access"
294
  msgstr ""
295
 
296
- #: classes/amazon-s3-and-cloudfront.php:4330
297
  msgid "URL"
298
  msgstr ""
299
 
300
- #: classes/amazon-s3-and-cloudfront.php:4554
301
  msgid "Assets Pull"
302
  msgstr ""
303
 
304
- #: classes/amazon-s3-and-cloudfront.php:4555
305
  msgid ""
306
- "An addon for WP Offload S3 to serve your site's JS, CSS, and other enqueued "
307
- "assets from Amazon CloudFront or another CDN."
308
  msgstr ""
309
 
310
- #: classes/amazon-s3-and-cloudfront.php:4559
311
  msgid "Feature"
312
  msgstr ""
313
 
314
- #: classes/amazon-s3-and-cloudfront.php:4605
315
  #, php-format
316
  msgid ""
317
  "<strong>Amazon Web Services Plugin No Longer Required</strong> &mdash; As of "
318
- "version 1.6 of WP Offload S3, the <a href=\"%1$s\">Amazon Web Services</a> "
319
- "plugin is no longer required. We have removed the dependency by bundling a "
320
- "small portion of the AWS SDK into WP Offload S3. As long as none of your "
321
- "other active plugins or themes depend on the Amazon Web Services plugin, it "
322
- "should be safe to deactivate and delete it. %2$s"
323
  msgstr ""
324
 
325
- #: classes/amazon-s3-and-cloudfront.php:4637
326
  #, php-format
327
  msgid ""
328
- "<strong>WP Offload S3 Settings Moved</strong> &mdash; You now define your "
329
- "AWS keys for WP Offload S3 in the new <a href=\"%1$s\">Settings tab</a>. "
330
- "Saving settings in the form below will have no effect on WP Offload S3. %2$s"
 
331
  msgstr ""
332
 
333
  #: classes/as3cf-compatibility-check.php:317
@@ -339,95 +339,95 @@ msgstr ""
339
  msgid "You can %s the %s plugin to get rid of this notice."
340
  msgstr ""
341
 
342
- #: classes/as3cf-compatibility-check.php:336
343
  #, php-format
344
  msgid "%s has been disabled as it requires the %s plugin."
345
  msgstr ""
346
 
347
- #: classes/as3cf-compatibility-check.php:340
348
  msgid "which is currently disabled."
349
  msgstr ""
350
 
351
- #: classes/as3cf-compatibility-check.php:342
352
  msgid "It appears to be installed already."
353
  msgstr ""
354
 
355
- #: classes/as3cf-compatibility-check.php:344
356
  msgctxt "Activate plugin"
357
  msgid "Activate it now."
358
  msgstr ""
359
 
360
- #: classes/as3cf-compatibility-check.php:351
361
  #, php-format
362
  msgid "<a href=\"%s\">Install</a> and activate it."
363
  msgstr ""
364
 
365
- #: classes/as3cf-compatibility-check.php:362
366
  #, php-format
367
  msgid ""
368
  "%s has been disabled as it requires version %s or later of the %s plugin."
369
  msgstr ""
370
 
371
- #: classes/as3cf-compatibility-check.php:365
372
  #, php-format
373
  msgid "You currently have version %s installed."
374
  msgstr ""
375
 
376
- #: classes/as3cf-compatibility-check.php:372
377
- #: classes/as3cf-compatibility-check.php:410
378
  #, php-format
379
  msgid "A valid license for %s is required to update."
380
  msgstr ""
381
 
382
- #: classes/as3cf-compatibility-check.php:381
383
  msgid "Update to the latest version"
384
  msgstr ""
385
 
386
- #: classes/as3cf-compatibility-check.php:392
387
  #, php-format
388
  msgid ""
389
  "%1$s has been disabled because it is not a supported addon of the %2$s "
390
  "plugin."
391
  msgstr ""
392
 
393
- #: classes/as3cf-compatibility-check.php:401
394
  #, php-format
395
  msgid ""
396
  "%1$s has been disabled because it will not work with the version of the %2$s "
397
  "plugin installed. %1$s %3$s or later is required."
398
  msgstr ""
399
 
400
- #: classes/as3cf-compatibility-check.php:404
401
  #, php-format
402
  msgid "Update %s to the latest version"
403
  msgstr ""
404
 
405
- #: classes/as3cf-compatibility-check.php:473
406
  #, php-format
407
  msgid "The %s plugin has been deactivated."
408
  msgstr ""
409
 
410
- #: classes/as3cf-compatibility-check.php:619
411
  msgid "a PHP version less than 5.5"
412
  msgstr ""
413
 
414
- #: classes/as3cf-compatibility-check.php:623
415
  msgid "no PHP cURL library activated"
416
  msgstr ""
417
 
418
- #: classes/as3cf-compatibility-check.php:629
419
  msgid "a cURL version less than 7.16.2"
420
  msgstr ""
421
 
422
- #: classes/as3cf-compatibility-check.php:644
423
  msgid "cURL compiled without"
424
  msgstr ""
425
 
426
- #: classes/as3cf-compatibility-check.php:649
427
  msgid "the function curl_multi_exec disabled"
428
  msgstr ""
429
 
430
- #: classes/as3cf-compatibility-check.php:667
431
  msgid ""
432
  "The official Amazon&nbsp;Web&nbsp;Services SDK requires PHP 5.5+ and cURL "
433
  "7.16.2+ compiled with OpenSSL and zlib. Your server currently has"
@@ -441,7 +441,7 @@ msgstr ""
441
  msgid "Invalid notice ID."
442
  msgstr ""
443
 
444
- #: classes/as3cf-plugin-base.php:482
445
  msgid "Settings"
446
  msgstr ""
447
 
@@ -454,17 +454,18 @@ msgstr ""
454
  #: classes/as3cf-plugin-compatibility.php:588
455
  #: classes/upgrades/upgrade-meta-wp-error.php:81
456
  #, php-format
457
- msgid "There was an error attempting to download the file %s from S3: %s"
 
458
  msgstr ""
459
 
460
- #: classes/as3cf-plugin-compatibility.php:878
461
  #, php-format
462
  msgid ""
463
  "<strong>Warning:</strong> This site is using PHP %1$s, in a future update WP "
464
- "Offload S3 will require PHP %2$s or later. %3$s"
465
  msgstr ""
466
 
467
- #: classes/providers/provider.php:211
468
  #, php-format
469
  msgid "You must first <a href=\"%s\">set your access keys</a>."
470
  msgstr ""
@@ -528,10 +529,16 @@ msgstr ""
528
  #: classes/upgrades/upgrade-region-meta.php:46
529
  msgid ""
530
  "and updating the metadata with the bucket region it is served from. This "
531
- "will allow us to serve your files from the proper S3 region subdomain <span "
532
  "style=\"white-space:nowrap;\">(e.g. s3-us-west-2.amazonaws.com)</span>."
533
  msgstr ""
534
 
 
 
 
 
 
 
535
  #: classes/upgrades/upgrade.php:405
536
  msgid "Pause Update"
537
  msgstr ""
@@ -548,8 +555,8 @@ msgstr ""
548
  #, php-format
549
  msgid ""
550
  "<strong>Running %1$s Update%2$s</strong> &mdash; We&#8217;re going through "
551
- "all the Media Library items uploaded to S3 %3$s This will be done quietly in "
552
- "the background, processing a small batch of Media Library items every %4$d "
553
  "minutes. There should be no noticeable impact on your server&#8217;s "
554
  "performance."
555
  msgstr ""
@@ -566,7 +573,7 @@ msgstr ""
566
  msgid ""
567
  "<strong>Error Updating %1$s</strong> &mdash; We ran into some errors "
568
  "attempting to update the %2$s for all your Media Library items that have "
569
- "been uploaded to S3. Please check your error log for details. (#%3$d)"
570
  msgstr ""
571
 
572
  #: classes/upgrades/upgrade.php:491
@@ -603,117 +610,131 @@ msgctxt "Install plugin now"
603
  msgid "Install Now"
604
  msgstr ""
605
 
606
- #: view/attachment-metabox.php:14
607
- msgid "This item has not been copied to S3 yet."
608
  msgstr ""
609
 
610
- #: view/attachment-metabox.php:39
611
  msgid "File does not exist on server"
612
  msgstr ""
613
 
614
- #: view/bucket-select.php:3
615
  msgid "Change bucket"
616
  msgstr ""
617
 
618
- #: view/bucket-select.php:3
619
  msgid "What bucket would you like to use?"
620
  msgstr ""
621
 
622
- #: view/bucket-select.php:5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
623
  msgid "Existing bucket name"
624
  msgstr ""
625
 
626
- #: view/bucket-select.php:7
627
- #: view/bucket-select.php:12
628
  msgid "Saving..."
629
  msgstr ""
630
 
631
- #: view/bucket-select.php:7
632
- #: view/bucket-select.php:12
633
  msgid "Save Bucket"
634
  msgstr ""
635
 
636
- #: view/bucket-select.php:8
637
  msgid "Browse existing buckets"
638
  msgstr ""
639
 
640
- #: view/bucket-select.php:9
641
- #: view/bucket-select.php:26
642
- #: view/bucket-select.php:31
643
  msgid "Create new bucket"
644
  msgstr ""
645
 
646
- #: view/bucket-select.php:13
647
- #: view/bucket-select.php:21
648
- #: view/bucket-select.php:69
649
  msgid "Cancel"
650
  msgstr ""
651
 
652
- #: view/bucket-select.php:18
653
  msgid "Select bucket"
654
  msgstr ""
655
 
656
- #: view/bucket-select.php:19
 
657
  msgid "Loading..."
658
  msgstr ""
659
 
660
- #: view/bucket-select.php:22
661
- #: view/bucket-select.php:27
662
- msgid "Refresh"
663
  msgstr ""
664
 
665
- #: view/bucket-select.php:25
666
- msgid "Enter bucket name"
667
- msgstr ""
668
-
669
- #: view/bucket-select.php:37
670
- msgid "Bucket Name:"
671
- msgstr ""
672
-
673
- #: view/bucket-select.php:40
674
- msgid "Bucket Name"
675
  msgstr ""
676
 
677
- #: view/bucket-select.php:46
678
- msgid "Region:"
679
  msgstr ""
680
 
681
- #: view/bucket-select.php:62
682
- #, php-format
683
- msgid "%s (defined in wp-config.php)"
684
  msgstr ""
685
 
686
- #: view/bucket-select.php:68
687
  msgid "Creating..."
688
  msgstr ""
689
 
690
- #: view/bucket-select.php:68
691
  msgid "Create New Bucket"
692
  msgstr ""
693
 
694
- #: view/bucket-setting.php:8
695
- msgid "Bucket"
696
- msgstr ""
697
-
698
  #: view/bucket-setting.php:13
699
- msgid "View in S3 console"
700
  msgstr ""
701
 
702
  #: view/bucket-setting.php:19
 
703
  msgid "Change"
704
  msgstr ""
705
 
706
- #: view/bucket-setting.php:37
 
 
 
 
707
  #, php-format
708
  msgid ""
709
  "<strong>Bucket Select Disabled</strong> &mdash; <a href=\"%s\">Define your "
710
- "AWS keys</a> to configure the bucket"
711
  msgstr ""
712
 
713
- #: view/bucket-setting.php:46
714
  msgid ""
715
- "<strong>Bucket Select Disabled</strong> &mdash; Bucket selection has been "
716
- "disabled while files are copied between buckets."
717
  msgstr ""
718
 
719
  #: view/cloudfront-setting.php:7
@@ -751,13 +772,16 @@ msgid "CloudFront or custom domain"
751
  msgstr ""
752
 
753
  #: view/domain-setting.php:19
754
- msgid "CloudFront or Custom Domain"
755
  msgstr ""
756
 
757
  #: view/domain-setting.php:21
 
758
  msgid ""
759
- "Replace the default S3 domain and path with your CloudFront domain or any "
760
- "domain."
 
 
761
  msgstr ""
762
 
763
  #: view/error-access.php:4
@@ -772,176 +796,210 @@ msgstr ""
772
  msgid "Show"
773
  msgstr ""
774
 
775
- #: view/settings/addons.php:10
 
 
 
 
 
 
 
 
 
 
 
 
776
  #, php-format
 
777
  msgid ""
778
- "<strong>Get Addons</strong> The following addons are available with a WP "
779
- "Offload S3 Gold license or better.<br>Visit <a href=\"%s\">deliciousbrains."
780
- "com</a> to purchase in just a few clicks."
781
  msgstr ""
782
 
783
- #: view/settings/media.php:13
784
  #, php-format
785
- msgid "<a href=\"%s\">Define your AWS keys</a> to configure WP Offload S3"
 
 
 
 
786
  msgstr ""
787
 
788
- #: view/settings/media.php:47
789
- msgid "Enable/Disable the Plugin"
 
790
  msgstr ""
791
 
792
- #: view/settings/media.php:56
793
- msgid "Copy Files to S3"
 
 
794
  msgstr ""
795
 
796
- #: view/settings/media.php:58
797
  msgid ""
798
- "When a file is uploaded to the Media Library, copy it to S3. Existing files "
799
- "are <em>not</em> copied to S3."
800
  msgstr ""
801
 
802
- #: view/settings/media.php:71
803
- msgid "Rewrite File URLs"
804
  msgstr ""
805
 
806
- #: view/settings/media.php:73
 
807
  msgid ""
808
- "For Media Library files that have been copied to S3, rewrite the URLs so "
809
- "that they are served from S3/CloudFront instead of your server."
 
810
  msgstr ""
811
 
812
- #: view/settings/media.php:80
813
- msgid "Configure File URLs"
 
 
 
814
  msgstr ""
815
 
816
- #: view/settings/media.php:101
817
- msgid "Path"
 
 
818
  msgstr ""
819
 
820
- #: view/settings/media.php:103
821
- msgid "By default the path is the same as your local WordPress files."
 
 
 
822
  msgstr ""
823
 
824
- #: view/settings/media.php:120
825
- msgid "Year/Month"
826
  msgstr ""
827
 
828
- #: view/settings/media.php:122
829
- msgid "Add the Year/Month in the URL."
830
  msgstr ""
831
 
832
- #: view/settings/media.php:135
833
- msgid "Force HTTPS"
834
  msgstr ""
835
 
836
- #: view/settings/media.php:137
 
837
  msgid ""
838
- "By default we use HTTPS when the request is HTTPS and regular HTTP when the "
839
- "request is HTTP, but you may want to force the use of HTTPS always, "
840
- "regardless of the request."
841
  msgstr ""
842
 
843
- #: view/settings/media.php:144
844
- msgid "Advanced Options"
 
 
 
 
845
  msgstr ""
846
 
847
- #: view/settings/media.php:153
848
- msgid "Remove Files From Server"
849
  msgstr ""
850
 
851
- #: view/settings/media.php:154
852
- msgid "Once a file has been copied to S3, remove it from the local server."
853
  msgstr ""
854
 
855
- #: view/settings/media.php:158
856
- msgid ""
857
- "<strong>Broken URLs</strong> &mdash; There will be broken URLs for files "
858
- "that don't exist locally. You can fix this by enabling <strong>Rewrite File "
859
- "URLs</strong> to use the S3 URLs."
860
  msgstr ""
861
 
862
- #: view/settings/media.php:169
863
- #, php-format
864
- msgid ""
865
- "<strong>Warning</strong> &mdash; Some plugins depend on the file being "
866
- "present on the local server and may not work when the file is removed. %s"
867
  msgstr ""
868
 
869
- #: view/settings/media.php:187
870
- msgid "Object Versioning"
871
  msgstr ""
872
 
873
- #: view/settings/media.php:189
 
 
 
 
874
  msgid ""
875
- "Append a timestamp to the S3 file path. Recommended when using CloudFront so "
876
- "you don't have to worry about cache invalidation."
877
  msgstr ""
878
 
879
- #: view/settings/media.php:196
880
- #: view/settings/settings.php:112
881
- msgid "Save Changes"
882
  msgstr ""
883
 
884
- #: view/settings/settings.php:19
885
- msgid "AWS Access Keys"
 
 
886
  msgstr ""
887
 
888
- #: view/settings/settings.php:23
889
- msgid "You have enabled the use of IAM roles for Amazon EC2 instances."
890
  msgstr ""
891
 
892
- #: view/settings/settings.php:30
893
- msgid ""
894
- "Please check your wp-config.php file as it looks like one of your defines is "
895
- "missing or incorrect."
896
  msgstr ""
897
 
898
- #: view/settings/settings.php:36
899
- #, php-format
900
  msgid ""
901
- "You&#8217;ve already defined your AWS access keys in your wp-config.php. If "
902
- "you&#8217;d prefer to manage them here and store them in the database (<a "
903
- "href=\"%s\">not recommended</a>), simply remove the lines from your wp-"
904
- "config."
905
  msgstr ""
906
 
907
- #: view/settings/settings.php:42
908
- msgid ""
909
- "We recommend defining your Access Keys <strong>near the top</strong> of your "
910
- "wp-config.php so long as you don&#8217;t commit it to source control (you "
911
- "shouldn&#8217;t be). Simply copy the following snippet and replace the stars "
912
- "with the keys."
913
  msgstr ""
914
 
915
- #: view/settings/settings.php:52
916
- #, php-format
917
  msgid ""
918
- "You&#8217;re storing your Access Keys in the database (<a href=\"%s\">not "
919
- "recommended</a>).</a>"
 
920
  msgstr ""
921
 
922
- #: view/settings/settings.php:56
923
- msgid ""
924
- "If you&#8217;d rather store your Access Keys in the database, <a href=\"#\" "
925
- "data-as3cf-toggle-access-keys-form>click here to reveal a form.</a>"
926
  msgstr ""
927
 
928
- #: view/settings/settings.php:66
929
- msgid "Access Key ID"
930
  msgstr ""
931
 
932
- #: view/settings/settings.php:83
933
- msgid "Secret Access Key"
 
934
  msgstr ""
935
 
936
- #: view/settings/settings.php:103
937
- msgid "This will store your AWS access keys in the database (not recommended)."
 
 
 
938
  msgstr ""
939
 
940
- #: view/settings/settings.php:115
941
- msgid "Remove Keys"
 
 
 
 
 
 
 
942
  msgstr ""
943
 
944
- #: view/settings/settings.php:127
945
  #, php-format
946
  msgid ""
947
  "Need help getting your Access Keys? <a href=\"%s\">Check out the Quick Start "
@@ -949,11 +1007,11 @@ msgid ""
949
  msgstr ""
950
 
951
  #: view/sidebar.php:13
952
- msgid "Upload existing Media Library to S3"
953
  msgstr ""
954
 
955
  #: view/sidebar.php:14
956
- msgid "Manage S3 files in WordPress"
957
  msgstr ""
958
 
959
  #: view/sidebar.php:15
8
  msgstr ""
9
  "Project-Id-Version: amazon-s3-and-cloudfront\n"
10
  "Report-Msgid-Bugs-To: nom@deliciousbrains.com\n"
11
+ "POT-Creation-Date: 2018-09-25 11:15+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:135
21
+ #: classes/amazon-s3-and-cloudfront.php:136
22
+ msgid "Offload Media"
23
  msgstr ""
24
 
25
+ #: classes/amazon-s3-and-cloudfront.php:279
26
+ #: classes/amazon-s3-and-cloudfront.php:293
27
+ msgid "Unknown"
 
 
 
 
 
 
 
 
 
 
 
 
28
  msgstr ""
29
 
30
+ #: classes/amazon-s3-and-cloudfront.php:347
31
+ #: view/bucket-setting.php:17
32
+ #: view/provider-select.php:85
33
+ msgid "defined in wp-config.php"
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  msgstr ""
35
 
36
+ #: classes/amazon-s3-and-cloudfront.php:1093
37
+ #: classes/amazon-s3-and-cloudfront.php:1232
38
  #, php-format
39
  msgid "File %s does not exist"
40
  msgstr ""
41
 
42
+ #: classes/amazon-s3-and-cloudfront.php:1106
43
  #, php-format
44
  msgid "Mime type %s is not allowed"
45
  msgstr ""
46
 
47
+ #: classes/amazon-s3-and-cloudfront.php:1117
48
+ msgid "Already offloaded to a different provider"
49
+ msgstr ""
50
+
51
+ #: classes/amazon-s3-and-cloudfront.php:1196
52
+ #: classes/amazon-s3-and-cloudfront.php:1240
53
  #, php-format
54
+ msgid "Error offloading %s to provider: %s"
55
  msgstr ""
56
 
57
+ #: classes/amazon-s3-and-cloudfront.php:2364
58
  msgid "This action can only be performed through an admin screen."
59
  msgstr ""
60
 
61
+ #: classes/amazon-s3-and-cloudfront.php:2366
62
  msgid "Cheatin&#8217; eh?"
63
  msgstr ""
64
 
65
+ #: classes/amazon-s3-and-cloudfront.php:2368
66
  msgid "You do not have sufficient permissions to access this page."
67
  msgstr ""
68
 
69
+ #: classes/amazon-s3-and-cloudfront.php:2403
70
+ msgid "No region provided."
71
+ msgstr ""
72
+
73
+ #: classes/amazon-s3-and-cloudfront.php:2418
74
  msgid "No bucket name provided."
75
  msgstr ""
76
 
77
+ #: classes/amazon-s3-and-cloudfront.php:2732
78
  msgid "Error Getting Bucket Region"
79
  msgstr ""
80
 
81
+ #: classes/amazon-s3-and-cloudfront.php:2733
82
  #, php-format
83
  msgid "There was an error attempting to get the region of the bucket %s: %s"
84
  msgstr ""
85
 
86
+ #: classes/amazon-s3-and-cloudfront.php:2852
87
  msgid ""
88
  "This is a test file to check if the user has write permission to S3. Delete "
89
  "me if found."
90
  msgstr ""
91
 
92
+ #: classes/amazon-s3-and-cloudfront.php:2858
93
  #, php-format
94
  msgid ""
95
  "There was an error attempting to check the permissions of the bucket %s: %s"
96
  msgstr ""
97
 
98
+ #: classes/amazon-s3-and-cloudfront.php:2934
99
  msgid "Error creating bucket"
100
  msgstr ""
101
 
102
+ #: classes/amazon-s3-and-cloudfront.php:2935
103
  msgid "Bucket name too short."
104
  msgstr ""
105
 
106
+ #: classes/amazon-s3-and-cloudfront.php:2936
107
  msgid "Bucket name too long."
108
  msgstr ""
109
 
110
+ #: classes/amazon-s3-and-cloudfront.php:2937
111
  msgid ""
112
  "Invalid character. Bucket names can contain lowercase letters, numbers, "
113
  "periods and hyphens."
114
  msgstr ""
115
 
116
+ #: classes/amazon-s3-and-cloudfront.php:2938
117
  msgid "Error saving bucket"
118
  msgstr ""
119
 
120
+ #: classes/amazon-s3-and-cloudfront.php:2939
121
  msgid "Error fetching buckets"
122
  msgstr ""
123
 
124
+ #: classes/amazon-s3-and-cloudfront.php:2940
125
  msgid "Error getting URL preview: "
126
  msgstr ""
127
 
128
+ #: classes/amazon-s3-and-cloudfront.php:2941
129
  msgid "The changes you made will be lost if you navigate away from this page"
130
  msgstr ""
131
 
132
+ #: classes/amazon-s3-and-cloudfront.php:2942
133
  msgid "Getting diagnostic info..."
134
  msgstr ""
135
 
136
+ #: classes/amazon-s3-and-cloudfront.php:2943
137
  msgid "Error getting diagnostic info: "
138
  msgstr ""
139
 
140
+ #: classes/amazon-s3-and-cloudfront.php:2944
141
+ msgctxt "placeholder for hidden access key, 39 char max"
142
+ msgid "-- not shown --"
143
+ msgstr ""
144
+
145
+ #: classes/amazon-s3-and-cloudfront.php:2946
146
+ #: classes/amazon-s3-and-cloudfront.php:4662
147
  msgid "Settings saved."
148
  msgstr ""
149
 
150
+ #: classes/amazon-s3-and-cloudfront.php:3020
151
  msgid "Cheatin' eh?"
152
  msgstr ""
153
 
154
+ #: classes/amazon-s3-and-cloudfront.php:3029
155
+ #: view/provider-select.php:219
156
+ msgctxt "placeholder for hidden secret access key, 39 char max"
157
+ msgid "-- not shown --"
158
+ msgstr ""
159
+
160
+ #: classes/amazon-s3-and-cloudfront.php:3074
161
  msgctxt "Show the media library tab"
162
  msgid "Media Library"
163
  msgstr ""
164
 
165
+ #: classes/amazon-s3-and-cloudfront.php:3075
166
  msgctxt "Show the addons tab"
167
  msgid "Addons"
168
  msgstr ""
169
 
170
+ #: classes/amazon-s3-and-cloudfront.php:3076
 
 
 
 
 
171
  msgctxt "Show the support tab"
172
  msgid "Support"
173
  msgstr ""
174
 
175
+ #: classes/amazon-s3-and-cloudfront.php:3295
176
  #, php-format
177
  msgid ""
178
+ "<strong>WP Offload Media</strong> &mdash; The file %s has been given %s "
179
+ "permissions in the bucket."
180
  msgstr ""
181
 
182
+ #: classes/amazon-s3-and-cloudfront.php:3314
183
  msgid ""
184
+ "<strong>WP Offload Media Requirement Missing</strong> &mdash; Looks like you "
185
  "don't have an image manipulation library installed on this server and "
186
  "configured with PHP. You may run into trouble if you try to edit images. "
187
  "Please setup GD or ImageMagick."
188
  msgstr ""
189
 
190
+ #: classes/amazon-s3-and-cloudfront.php:3942
191
  #, php-format
192
  msgid ""
193
+ "<a href=\"%s\">Define your access keys</a> to enable write access to the "
194
+ "bucket"
195
  msgstr ""
196
 
197
+ #: classes/amazon-s3-and-cloudfront.php:3949
198
  msgid "Quick Start Guide"
199
  msgstr ""
200
 
201
+ #: classes/amazon-s3-and-cloudfront.php:3951
202
  #, php-format
203
  msgid ""
204
  "Looks like we don't have write access to this bucket. It's likely that the "
207
  "correctly."
208
  msgstr ""
209
 
210
+ #: classes/amazon-s3-and-cloudfront.php:3953
211
  #, php-format
212
  msgid ""
213
  "Looks like we don't have access to the buckets. It's likely that the user "
215
  "Please see our %s for instructions on setting up permissions correctly."
216
  msgstr ""
217
 
218
+ #: classes/amazon-s3-and-cloudfront.php:4103
219
+ msgid "WP Offload Media Activation"
220
  msgstr ""
221
 
222
+ #: classes/amazon-s3-and-cloudfront.php:4104
223
  msgid ""
224
+ "WP Offload Media Lite and WP Offload Media cannot both be active. We've "
225
+ "automatically deactivated WP Offload Media Lite."
226
  msgstr ""
227
 
228
+ #: classes/amazon-s3-and-cloudfront.php:4106
229
+ msgid "WP Offload Media Lite Activation"
230
  msgstr ""
231
 
232
+ #: classes/amazon-s3-and-cloudfront.php:4107
233
  msgid ""
234
+ "WP Offload Media Lite and WP Offload Media cannot both be active. We've "
235
+ "automatically deactivated WP Offload Media."
236
  msgstr ""
237
 
238
+ #: classes/amazon-s3-and-cloudfront.php:4159
239
  msgid "More&nbsp;info&nbsp;&raquo;"
240
  msgstr ""
241
 
242
+ #: classes/amazon-s3-and-cloudfront.php:4254
243
  msgid "this doc"
244
  msgstr ""
245
 
246
+ #: classes/amazon-s3-and-cloudfront.php:4256
247
+ msgid "WP Offload Media Feature Removed"
248
  msgstr ""
249
 
250
+ #: classes/amazon-s3-and-cloudfront.php:4257
251
  #, php-format
252
  msgid ""
253
  "You had the \"Always non-SSL\" option selected in your settings, but we've "
258
  "to the old behavior."
259
  msgstr ""
260
 
261
+ #: classes/amazon-s3-and-cloudfront.php:4287
262
+ msgid "Offload"
263
+ msgstr ""
264
+
265
+ #: classes/amazon-s3-and-cloudfront.php:4395
266
+ msgctxt "Storage provider key name"
267
+ msgid "Storage Provider"
268
  msgstr ""
269
 
270
+ #: classes/amazon-s3-and-cloudfront.php:4396
271
+ msgctxt "Storage provider name"
272
+ msgid "Storage Provider"
273
+ msgstr ""
274
+
275
+ #: classes/amazon-s3-and-cloudfront.php:4397
276
+ msgctxt "Bucket name"
277
  msgid "Bucket"
278
  msgstr ""
279
 
280
+ #: classes/amazon-s3-and-cloudfront.php:4398
281
+ msgctxt "Path to file in bucket"
282
  msgid "Path"
283
  msgstr ""
284
 
285
+ #: classes/amazon-s3-and-cloudfront.php:4399
286
+ msgctxt "Location of bucket"
287
  msgid "Region"
288
  msgstr ""
289
 
290
+ #: classes/amazon-s3-and-cloudfront.php:4400
291
+ msgctxt "Access control list of the file in bucket"
292
  msgid "Access"
293
  msgstr ""
294
 
295
+ #: classes/amazon-s3-and-cloudfront.php:4401
296
  msgid "URL"
297
  msgstr ""
298
 
299
+ #: classes/amazon-s3-and-cloudfront.php:4625
300
  msgid "Assets Pull"
301
  msgstr ""
302
 
303
+ #: classes/amazon-s3-and-cloudfront.php:4626
304
  msgid ""
305
+ "An addon for WP Offload Media to serve your site's JS, CSS, and other "
306
+ "enqueued assets from Amazon CloudFront or another CDN."
307
  msgstr ""
308
 
309
+ #: classes/amazon-s3-and-cloudfront.php:4630
310
  msgid "Feature"
311
  msgstr ""
312
 
313
+ #: classes/amazon-s3-and-cloudfront.php:4676
314
  #, php-format
315
  msgid ""
316
  "<strong>Amazon Web Services Plugin No Longer Required</strong> &mdash; As of "
317
+ "version 1.6 of WP Offload Media, the <a href=\"%1$s\">Amazon Web Services</"
318
+ "a> plugin is no longer required. We have removed the dependency by bundling "
319
+ "a small portion of the AWS SDK into WP Offload Media. As long as none of "
320
+ "your other active plugins or themes depend on the Amazon Web Services "
321
+ "plugin, it should be safe to deactivate and delete it. %2$s"
322
  msgstr ""
323
 
324
+ #: classes/amazon-s3-and-cloudfront.php:4708
325
  #, php-format
326
  msgid ""
327
+ "<strong>WP Offload Media Settings Moved</strong> &mdash; You now define your "
328
+ "AWS keys for WP Offload Media in the new <a href=\"%1$s\">Settings tab</a>. "
329
+ "Saving settings in the form below will have no effect on WP Offload Media. "
330
+ "%2$s"
331
  msgstr ""
332
 
333
  #: classes/as3cf-compatibility-check.php:317
339
  msgid "You can %s the %s plugin to get rid of this notice."
340
  msgstr ""
341
 
342
+ #: classes/as3cf-compatibility-check.php:337
343
  #, php-format
344
  msgid "%s has been disabled as it requires the %s plugin."
345
  msgstr ""
346
 
347
+ #: classes/as3cf-compatibility-check.php:341
348
  msgid "which is currently disabled."
349
  msgstr ""
350
 
351
+ #: classes/as3cf-compatibility-check.php:343
352
  msgid "It appears to be installed already."
353
  msgstr ""
354
 
355
+ #: classes/as3cf-compatibility-check.php:345
356
  msgctxt "Activate plugin"
357
  msgid "Activate it now."
358
  msgstr ""
359
 
360
+ #: classes/as3cf-compatibility-check.php:352
361
  #, php-format
362
  msgid "<a href=\"%s\">Install</a> and activate it."
363
  msgstr ""
364
 
365
+ #: classes/as3cf-compatibility-check.php:363
366
  #, php-format
367
  msgid ""
368
  "%s has been disabled as it requires version %s or later of the %s plugin."
369
  msgstr ""
370
 
371
+ #: classes/as3cf-compatibility-check.php:366
372
  #, php-format
373
  msgid "You currently have version %s installed."
374
  msgstr ""
375
 
376
+ #: classes/as3cf-compatibility-check.php:373
377
+ #: classes/as3cf-compatibility-check.php:411
378
  #, php-format
379
  msgid "A valid license for %s is required to update."
380
  msgstr ""
381
 
382
+ #: classes/as3cf-compatibility-check.php:382
383
  msgid "Update to the latest version"
384
  msgstr ""
385
 
386
+ #: classes/as3cf-compatibility-check.php:393
387
  #, php-format
388
  msgid ""
389
  "%1$s has been disabled because it is not a supported addon of the %2$s "
390
  "plugin."
391
  msgstr ""
392
 
393
+ #: classes/as3cf-compatibility-check.php:402
394
  #, php-format
395
  msgid ""
396
  "%1$s has been disabled because it will not work with the version of the %2$s "
397
  "plugin installed. %1$s %3$s or later is required."
398
  msgstr ""
399
 
400
+ #: classes/as3cf-compatibility-check.php:405
401
  #, php-format
402
  msgid "Update %s to the latest version"
403
  msgstr ""
404
 
405
+ #: classes/as3cf-compatibility-check.php:474
406
  #, php-format
407
  msgid "The %s plugin has been deactivated."
408
  msgstr ""
409
 
410
+ #: classes/as3cf-compatibility-check.php:620
411
  msgid "a PHP version less than 5.5"
412
  msgstr ""
413
 
414
+ #: classes/as3cf-compatibility-check.php:624
415
  msgid "no PHP cURL library activated"
416
  msgstr ""
417
 
418
+ #: classes/as3cf-compatibility-check.php:630
419
  msgid "a cURL version less than 7.16.2"
420
  msgstr ""
421
 
422
+ #: classes/as3cf-compatibility-check.php:645
423
  msgid "cURL compiled without"
424
  msgstr ""
425
 
426
+ #: classes/as3cf-compatibility-check.php:650
427
  msgid "the function curl_multi_exec disabled"
428
  msgstr ""
429
 
430
+ #: classes/as3cf-compatibility-check.php:668
431
  msgid ""
432
  "The official Amazon&nbsp;Web&nbsp;Services SDK requires PHP 5.5+ and cURL "
433
  "7.16.2+ compiled with OpenSSL and zlib. Your server currently has"
441
  msgid "Invalid notice ID."
442
  msgstr ""
443
 
444
+ #: classes/as3cf-plugin-base.php:499
445
  msgid "Settings"
446
  msgstr ""
447
 
454
  #: classes/as3cf-plugin-compatibility.php:588
455
  #: classes/upgrades/upgrade-meta-wp-error.php:81
456
  #, php-format
457
+ msgid ""
458
+ "There was an error attempting to download the file %s from the bucket: %s"
459
  msgstr ""
460
 
461
+ #: classes/as3cf-plugin-compatibility.php:880
462
  #, php-format
463
  msgid ""
464
  "<strong>Warning:</strong> This site is using PHP %1$s, in a future update WP "
465
+ "Offload Media will require PHP %2$s or later. %3$s"
466
  msgstr ""
467
 
468
+ #: classes/providers/provider.php:361
469
  #, php-format
470
  msgid "You must first <a href=\"%s\">set your access keys</a>."
471
  msgstr ""
529
  #: classes/upgrades/upgrade-region-meta.php:46
530
  msgid ""
531
  "and updating the metadata with the bucket region it is served from. This "
532
+ "will allow us to serve your files from the proper region subdomain <span "
533
  "style=\"white-space:nowrap;\">(e.g. s3-us-west-2.amazonaws.com)</span>."
534
  msgstr ""
535
 
536
+ #: classes/upgrades/upgrade-wpos3-to-as3cf.php:36
537
+ msgid ""
538
+ "and updating the metadata to use key names compatible with the current "
539
+ "version."
540
+ msgstr ""
541
+
542
  #: classes/upgrades/upgrade.php:405
543
  msgid "Pause Update"
544
  msgstr ""
555
  #, php-format
556
  msgid ""
557
  "<strong>Running %1$s Update%2$s</strong> &mdash; We&#8217;re going through "
558
+ "all the offloaded Media Library items %3$s This will be done quietly in the "
559
+ "background, processing a small batch of Media Library items every %4$d "
560
  "minutes. There should be no noticeable impact on your server&#8217;s "
561
  "performance."
562
  msgstr ""
573
  msgid ""
574
  "<strong>Error Updating %1$s</strong> &mdash; We ran into some errors "
575
  "attempting to update the %2$s for all your Media Library items that have "
576
+ "been offloaded. Please check your error log for details. (#%3$d)"
577
  msgstr ""
578
 
579
  #: classes/upgrades/upgrade.php:491
610
  msgid "Install Now"
611
  msgstr ""
612
 
613
+ #: view/attachment-metabox.php:19
614
+ msgid "This item has not been offloaded yet."
615
  msgstr ""
616
 
617
+ #: view/attachment-metabox.php:48
618
  msgid "File does not exist on server"
619
  msgstr ""
620
 
621
+ #: view/bucket-select.php:10
622
  msgid "Change bucket"
623
  msgstr ""
624
 
625
+ #: view/bucket-select.php:10
626
  msgid "What bucket would you like to use?"
627
  msgstr ""
628
 
629
+ #: view/bucket-select.php:24
630
+ #: view/bucket-select.php:80
631
+ #: view/bucket-select.php:136
632
+ msgid "Region:"
633
+ msgstr ""
634
+
635
+ #: view/bucket-select.php:39
636
+ #: view/bucket-select.php:95
637
+ #: view/bucket-select.php:151
638
+ #, php-format
639
+ msgid "%s (defined in wp-config.php)"
640
+ msgstr ""
641
+
642
+ #: view/bucket-select.php:46
643
+ #: view/bucket-select.php:101
644
+ #: view/bucket-select.php:157
645
+ #: view/bucket-setting.php:8
646
+ msgid "Bucket:"
647
+ msgstr ""
648
+
649
+ #: view/bucket-select.php:49
650
  msgid "Existing bucket name"
651
  msgstr ""
652
 
653
+ #: view/bucket-select.php:54
654
+ #: view/bucket-select.php:59
655
  msgid "Saving..."
656
  msgstr ""
657
 
658
+ #: view/bucket-select.php:54
659
+ #: view/bucket-select.php:59
660
  msgid "Save Bucket"
661
  msgstr ""
662
 
663
+ #: view/bucket-select.php:55
664
  msgid "Browse existing buckets"
665
  msgstr ""
666
 
667
+ #: view/bucket-select.php:56
668
+ #: view/bucket-select.php:117
669
+ #: view/bucket-select.php:122
670
  msgid "Create new bucket"
671
  msgstr ""
672
 
673
+ #: view/bucket-select.php:60
674
+ #: view/bucket-select.php:112
675
+ #: view/bucket-select.php:167
676
  msgid "Cancel"
677
  msgstr ""
678
 
679
+ #: view/bucket-select.php:65
680
  msgid "Select bucket"
681
  msgstr ""
682
 
683
+ #: view/bucket-select.php:104
684
+ #: view/bucket-select.php:109
685
  msgid "Loading..."
686
  msgstr ""
687
 
688
+ #: view/bucket-select.php:104
689
+ #: view/bucket-select.php:109
690
+ msgid "Nothing found"
691
  msgstr ""
692
 
693
+ #: view/bucket-select.php:113
694
+ #: view/bucket-select.php:118
695
+ msgid "Refresh"
 
 
 
 
 
 
 
696
  msgstr ""
697
 
698
+ #: view/bucket-select.php:116
699
+ msgid "Enter bucket name"
700
  msgstr ""
701
 
702
+ #: view/bucket-select.php:160
703
+ msgid "New bucket name"
 
704
  msgstr ""
705
 
706
+ #: view/bucket-select.php:166
707
  msgid "Creating..."
708
  msgstr ""
709
 
710
+ #: view/bucket-select.php:166
711
  msgid "Create New Bucket"
712
  msgstr ""
713
 
 
 
 
 
714
  #: view/bucket-setting.php:13
715
+ msgid "View in provider's console"
716
  msgstr ""
717
 
718
  #: view/bucket-setting.php:19
719
+ #: view/provider-setting.php:11
720
  msgid "Change"
721
  msgstr ""
722
 
723
+ #: view/bucket-setting.php:22
724
+ msgid "The region that the bucket is in."
725
+ msgstr ""
726
+
727
+ #: view/bucket-setting.php:43
728
  #, php-format
729
  msgid ""
730
  "<strong>Bucket Select Disabled</strong> &mdash; <a href=\"%s\">Define your "
731
+ "access keys</a> to configure the bucket"
732
  msgstr ""
733
 
734
+ #: view/bucket-setting.php:52
735
  msgid ""
736
+ "<strong>Provider &amp; Bucket Select Disabled</strong> &mdash; Provider and "
737
+ "bucket selection has been disabled while files are copied between buckets."
738
  msgstr ""
739
 
740
  #: view/cloudfront-setting.php:7
772
  msgstr ""
773
 
774
  #: view/domain-setting.php:19
775
+ msgid "Custom Domain (CNAME)"
776
  msgstr ""
777
 
778
  #: view/domain-setting.php:21
779
+ #, php-format
780
  msgid ""
781
+ "We strongly recommend you configure a CDN to point at your bucket and "
782
+ "configure a subdomain of %1$s to point at your CDN. If you don't enter a "
783
+ "subdomain of your site's domain in the field below it will negatively impact "
784
+ "your site's SEO."
785
  msgstr ""
786
 
787
  #: view/error-access.php:4
796
  msgid "Show"
797
  msgstr ""
798
 
799
+ #: view/provider-select.php:14
800
+ msgid "&laquo;&nbsp;Back"
801
+ msgstr ""
802
+
803
+ #: view/provider-select.php:17
804
+ msgid "Storage Provider"
805
+ msgstr ""
806
+
807
+ #: view/provider-select.php:104
808
+ msgid "Define access keys in wp-config.php"
809
+ msgstr ""
810
+
811
+ #: view/provider-select.php:112
812
  #, php-format
813
+ msgctxt "Access Keys defined in multiple defines."
814
  msgid ""
815
+ "You've defined your access keys in your wp-config.php. To select a different "
816
+ "option here, simply comment out or remove the '%1$s' defines in your wp-"
817
+ "config.php."
818
  msgstr ""
819
 
820
+ #: view/provider-select.php:114
821
  #, php-format
822
+ msgctxt "Access Keys defined in single define."
823
+ msgid ""
824
+ "You've defined your access keys in your wp-config.php. To select a different "
825
+ "option here, simply comment out or remove the '%1$s' define in your wp-"
826
+ "config.php."
827
  msgstr ""
828
 
829
+ #: view/provider-select.php:116
830
+ msgctxt "joins multiple define keys in notice"
831
+ msgid " & "
832
  msgstr ""
833
 
834
+ #: view/provider-select.php:125
835
+ msgid ""
836
+ "Please check your wp-config.php file as it looks like one of your access key "
837
+ "defines is missing or incorrect."
838
  msgstr ""
839
 
840
+ #: view/provider-select.php:131
841
  msgid ""
842
+ "Copy the following snippet <strong>near the top</strong> of your wp-config."
843
+ "php and replace the stars with the keys."
844
  msgstr ""
845
 
846
+ #: view/provider-select.php:156
847
+ msgid "My server is on Amazon EC2 and I'd like to use IAM Roles"
848
  msgstr ""
849
 
850
+ #: view/provider-select.php:162
851
+ #, php-format
852
  msgid ""
853
+ "You've defined the '%1$s' constant in your wp-config.php. To select a "
854
+ "different option here, simply comment out or remove the define in your wp-"
855
+ "config.php."
856
  msgstr ""
857
 
858
+ #: view/provider-select.php:166
859
+ msgid ""
860
+ "If you host your WordPress site on an Amazon EC2 instance you should make "
861
+ "use of IAM Roles. To tell WP Offload Media you're using IAM Roles, copy the "
862
+ "following snippet <strong>near the top</strong> of your wp-config.php."
863
  msgstr ""
864
 
865
+ #: view/provider-select.php:187
866
+ msgid ""
867
+ "I understand the risks but I'd like to store access keys in the database "
868
+ "anyway (not recommended)"
869
  msgstr ""
870
 
871
+ #: view/provider-select.php:193
872
+ msgid ""
873
+ "Storing your access keys in the database is less secure than the options "
874
+ "above, but if you're ok with that, go ahead and enter your keys in the form "
875
+ "below."
876
  msgstr ""
877
 
878
+ #: view/provider-select.php:198
879
+ msgid "Access Key ID"
880
  msgstr ""
881
 
882
+ #: view/provider-select.php:213
883
+ msgid "Secret Access Key"
884
  msgstr ""
885
 
886
+ #: view/provider-setting.php:6
887
+ msgid "Provider:"
888
  msgstr ""
889
 
890
+ #: view/settings/addons.php:10
891
+ #, php-format
892
  msgid ""
893
+ "<strong>Get Addons</strong> The following addons are available with a WP "
894
+ "Offload Media Gold license or better.<br>Visit <a href=\"%s"
895
+ "\">deliciousbrains.com</a> to purchase in just a few clicks."
896
  msgstr ""
897
 
898
+ #: view/settings/media.php:53
899
+ #, php-format
900
+ msgid ""
901
+ "Yikes! That's not a very SEO-friendly URL. We strongly recommend you "
902
+ "configure a CDN to point at your bucket and configure a subdomain of %1$s to "
903
+ "point at your CDN. %2$s"
904
  msgstr ""
905
 
906
+ #: view/settings/media.php:69
907
+ msgid "Storage"
908
  msgstr ""
909
 
910
+ #: view/settings/media.php:97
911
+ msgid "Copy Files to Bucket"
912
  msgstr ""
913
 
914
+ #: view/settings/media.php:99
915
+ msgid "When a file is uploaded to the Media Library, copy it to the bucket."
 
 
 
916
  msgstr ""
917
 
918
+ #: view/settings/media.php:114
919
+ msgid "Path"
 
 
 
920
  msgstr ""
921
 
922
+ #: view/settings/media.php:116
923
+ msgid "By default the path is the same as your local WordPress files."
924
  msgstr ""
925
 
926
+ #: view/settings/media.php:134
927
+ msgid "Year/Month"
928
+ msgstr ""
929
+
930
+ #: view/settings/media.php:136
931
  msgid ""
932
+ "Add the Year/Month to the end of the path above just like WordPress does by "
933
+ "default."
934
  msgstr ""
935
 
936
+ #: view/settings/media.php:149
937
+ msgid "Object Versioning"
 
938
  msgstr ""
939
 
940
+ #: view/settings/media.php:151
941
+ msgid ""
942
+ "Append a timestamp to the file's bucket path. Recommended when using a CDN "
943
+ "so you don't have to worry about cache invalidation."
944
  msgstr ""
945
 
946
+ #: view/settings/media.php:159
947
+ msgid "URL Rewriting"
948
  msgstr ""
949
 
950
+ #: view/settings/media.php:169
951
+ msgid "Rewrite Media URLs"
 
 
952
  msgstr ""
953
 
954
+ #: view/settings/media.php:171
 
955
  msgid ""
956
+ "For Media Library files that have been copied to your bucket, rewrite the "
957
+ "URLs so that they are served from the bucket or CDN instead of your server."
 
 
958
  msgstr ""
959
 
960
+ #: view/settings/media.php:187
961
+ msgid "Force HTTPS"
 
 
 
 
962
  msgstr ""
963
 
964
+ #: view/settings/media.php:189
 
965
  msgid ""
966
+ "By default we use HTTPS when the request is HTTPS and regular HTTP when the "
967
+ "request is HTTP, but you may want to force the use of HTTPS always, "
968
+ "regardless of the request."
969
  msgstr ""
970
 
971
+ #: view/settings/media.php:197
972
+ msgid "Advanced Options"
 
 
973
  msgstr ""
974
 
975
+ #: view/settings/media.php:207
976
+ msgid "Remove Files From Server"
977
  msgstr ""
978
 
979
+ #: view/settings/media.php:208
980
+ msgid ""
981
+ "Once a file has been copied to the bucket, remove it from the local server."
982
  msgstr ""
983
 
984
+ #: view/settings/media.php:212
985
+ msgid ""
986
+ "<strong>Broken URLs</strong> &mdash; There will be broken URLs for files "
987
+ "that don't exist locally. You can fix this by enabling <strong>Rewrite Media "
988
+ "URLs</strong> to use the offloaded media."
989
  msgstr ""
990
 
991
+ #: view/settings/media.php:223
992
+ #, php-format
993
+ msgid ""
994
+ "<strong>Warning</strong> &mdash; Some plugins depend on the file being "
995
+ "present on the local server and may not work when the file is removed. %s"
996
+ msgstr ""
997
+
998
+ #: view/settings/media.php:236
999
+ msgid "Save Changes"
1000
  msgstr ""
1001
 
1002
+ #: view/settings/media.php:248
1003
  #, php-format
1004
  msgid ""
1005
  "Need help getting your Access Keys? <a href=\"%s\">Check out the Quick Start "
1007
  msgstr ""
1008
 
1009
  #: view/sidebar.php:13
1010
+ msgid "Offload existing Media Library items"
1011
  msgstr ""
1012
 
1013
  #: view/sidebar.php:14
1014
+ msgid "Manage offloaded files in WordPress"
1015
  msgstr ""
1016
 
1017
  #: view/sidebar.php:15
readme.txt CHANGED
@@ -1,64 +1,73 @@
1
- === WP Offload S3 Lite ===
2
- Contributors: bradt, deliciousbrains
3
- Tags: uploads, amazon, s3, amazon s3, mirror, admin, media, cdn, cloudfront
4
- Requires at least: 4.6
5
  Tested up to: 4.9
6
  Requires PHP: 5.5
7
- Stable tag: 1.4.3
8
  License: GPLv3
9
 
10
- Copies files to Amazon S3 as they are uploaded to the Media Library. Optionally configure Amazon CloudFront for faster delivery.
11
 
12
  == Description ==
13
 
 
 
14
  https://www.youtube.com/watch?v=_PVybEGaRXc
15
 
16
- This plugin automatically copies images, videos, documents, and any other media added through WordPress' media uploader to [Amazon S3](http://aws.amazon.com/s3/). It then automatically replaces the URL to each media file with their respective Amazon S3 URL or, if you have configured [Amazon CloudFront](http://aws.amazon.com/cloudfront/), the respective CloudFront URL. Image thumbnails are also copied to Amazon S3 and delivered through S3/CloudFront.
17
 
18
- Uploading files *directly* to your Amazon S3 account is not currently supported by this plugin. They are uploaded to your server first, then copied to Amazon S3. There is an option to automatically remove the files from your server once they are copied to Amazon S3 however.
19
 
20
- If you're adding this plugin to a site that's been around for a while, your existing media files will not be copied or served from Amazon S3. Only newly uploaded files will be copied and served from Amazon S3. The pro upgrade has an upload tool to handle existing media files.
21
 
22
  **PRO Upgrade with Email Support and More Features**
23
 
24
- * Upload existing Media Library to Amazon S3
25
- * Control Amazon S3 files from the Media Library
26
- * [Assets addon](https://deliciousbrains.com/wp-offload-s3/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=assets%2Baddon#addons) - Serve your CSS & JS from Amazon S3/CloudFront
27
- * [WooCommerce integration](https://deliciousbrains.com/wp-offload-s3/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=woocommerce%2Baddon#integrations)
28
- * [Easy Digital Downloads integration](https://deliciousbrains.com/wp-offload-s3/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=edd%2Baddon#integrations)
29
  * PriorityExpert&trade; email support
30
 
31
- [Compare pro vs free &rarr;](https://deliciousbrains.com/wp-offload-s3/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
32
 
33
  The video below runs through the pro upgrade features...
34
 
35
  https://www.youtube.com/watch?v=55xNGnbJ_CY
36
 
37
- *This plugin has been completely rewritten, but was originally a fork of
38
- [Amazon S3 for WordPress with CloudFront](http://wordpress.org/extend/plugins/tantan-s3-cloudfront/)
39
- which is a fork of [Amazon S3 for WordPress](http://wordpress.org/extend/plugins/tantan-s3/), also known as tantan-s3.*
40
 
41
  == Installation ==
42
 
43
  1. Install this plugin using WordPress' built-in installer
44
- 2. Access the *Offload S3* option under *Settings*
45
- 3. Follow the instructions to setup your AWS access keys and configure
46
 
47
- Check out the [Quick Start Guide](https://deliciousbrains.com/wp-offload-s3/doc/quick-start-guide/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting) for more information on configuring WP Offload S3.
48
 
49
  == Frequently Asked Questions ==
50
 
51
  = What are the minimum requirements? =
52
 
53
- You can see the minimum requirements [here](https://deliciousbrains.com/wp-offload-s3/pricing/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=requirements#requirements).
 
 
 
 
54
 
55
  == Screenshots ==
56
 
57
- 1. Choosing/creating a bucket
58
- 2. Settings screen
 
 
59
 
60
  == Upgrade Notice ==
61
 
 
 
 
62
  = 1.1 =
63
  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.
64
 
@@ -67,6 +76,12 @@ This version requires PHP 5.3.3+ and the Amazon Web Services plugin
67
 
68
  == Changelog ==
69
 
 
 
 
 
 
 
70
  = WP Offload S3 Lite 1.4.3 - 2018-08-02 =
71
  * Bug fix: Images remotely edited via stream wrapper sometimes set as private on S3
72
 
1
+ === WP Offload Media Lite for Amazon S3 and DigitalOcean Spaces ===
2
+ Contributors: bradt, deliciousbrains, ianmjones
3
+ Tags: uploads, amazon, s3, amazon s3, digitalocean, digitalocean spaces, mirror, admin, media, cdn, cloudfront
4
+ Requires at least: 4.7
5
  Tested up to: 4.9
6
  Requires PHP: 5.5
7
+ Stable tag: 2.0
8
  License: GPLv3
9
 
10
+ Copies files to Amazon S3 or DigitalOcean Spaces as they are uploaded to the Media Library. Optionally configure Amazon CloudFront or another CDN for faster delivery.
11
 
12
  == Description ==
13
 
14
+ FORMERLY WP OFFLOAD S3 LITE
15
+
16
  https://www.youtube.com/watch?v=_PVybEGaRXc
17
 
18
+ This plugin automatically copies images, videos, documents, and any other media added through WordPress' media uploader to [Amazon S3](http://aws.amazon.com/s3/) or [DigitalOcean Spaces](https://www.digitalocean.com/products/spaces/). It then automatically replaces the URL to each media file with their respective Amazon S3 or DigitalOcean Spaces URL or, if you have configured [Amazon CloudFront](http://aws.amazon.com/cloudfront/) or another CDN with or without a custom domain, that URL instead. Image thumbnails are also copied to the bucket and delivered through the correct remote URL.
19
 
20
+ Uploading files *directly* to your Amazon S3 or DigitalOcean Spaces account is not currently supported by this plugin. They are uploaded to your server first, then copied to the bucket. There is an option to automatically remove the files from your server once they are copied to the bucket however.
21
 
22
+ If you're adding this plugin to a site that's been around for a while, your existing media files will not be copied to or served from Amazon S3 or DigitalOcean Spaces. Only newly uploaded files will be copied to and served from the bucket. The pro upgrade has an upload tool to handle existing media files.
23
 
24
  **PRO Upgrade with Email Support and More Features**
25
 
26
+ * Upload existing Media Library to Amazon S3 or DigitalOcean Spaces
27
+ * Control offloaded files from the Media Library
28
+ * [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
29
+ * [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)
30
+ * [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)
31
  * PriorityExpert&trade; email support
32
 
33
+ [Compare pro vs free &rarr;](https://deliciousbrains.com/wp-offload-media/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting)
34
 
35
  The video below runs through the pro upgrade features...
36
 
37
  https://www.youtube.com/watch?v=55xNGnbJ_CY
38
 
39
+ *This plugin has been completely rewritten, but was originally a fork of [Amazon S3 for WordPress with CloudFront](http://wordpress.org/extend/plugins/tantan-s3-cloudfront/) which is a fork of [Amazon S3 for WordPress](http://wordpress.org/extend/plugins/tantan-s3/), also known as tantan-s3.*
 
 
40
 
41
  == Installation ==
42
 
43
  1. Install this plugin using WordPress' built-in installer
44
+ 2. Access the *Offload Media* option under *Settings*
45
+ 3. Follow the instructions to set up your AWS or DigitalOcean access keys and configure
46
 
47
+ Check out the [Quick Start Guide](https://deliciousbrains.com/wp-offload-media/doc/quick-start-guide/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting) for more information on configuring WP Offload Media.
48
 
49
  == Frequently Asked Questions ==
50
 
51
  = What are the minimum requirements? =
52
 
53
+ You can see the minimum requirements [here](https://deliciousbrains.com/wp-offload-media/pricing/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting&utm_content=requirements#requirements).
54
+
55
+ = Do you offer email support? =
56
+
57
+ If you upgrade to the pro version of [WP Offload Media](https://deliciousbrains.com/wp-offload-media/upgrade/?utm_campaign=WP%2BOffload%2BS3&utm_source=wordpress.org&utm_medium=free%2Bplugin%2Blisting), we will gladly provide you with email support. We take pride in delivering exceptional customer support. We do not provide email support for the free version.
58
 
59
  == Screenshots ==
60
 
61
+ 1. Select Cloud Storage Provider
62
+ 2. Select or Create Bucket
63
+ 3. Settings Screen
64
+ 3. Custom Domain Used With CDN
65
 
66
  == Upgrade Notice ==
67
 
68
+ = 2.0 =
69
+ 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+.
70
+
71
  = 1.1 =
72
  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.
73
 
76
 
77
  == Changelog ==
78
 
79
+ = WP Offload Media Lite 2.0 - 2018-09-24 =
80
+ * [Release Summary Blog Post](https://deliciousbrains.com/wp-offload-media-supports-digitalocean-spaces/)
81
+ * New: DigitalOcean Spaces is now supported
82
+ * New: Plugin name updated from WP Offload S3 Lite to WP Offload Media Lite
83
+ * Improvement: More logical UI layout and better description of each setting
84
+
85
  = WP Offload S3 Lite 1.4.3 - 2018-08-02 =
86
  * Bug fix: Images remotely edited via stream wrapper sometimes set as private on S3
87
 
vendor/Aws3/Aws/Api/AbstractModel.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
  /**
6
  * Base class that is used by most API shapes
@@ -15,7 +15,7 @@ abstract class AbstractModel implements \ArrayAccess
15
  * @param array $definition Service description
16
  * @param ShapeMap $shapeMap Shapemap used for creating shapes
17
  */
18
- public function __construct(array $definition, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ShapeMap $shapeMap)
19
  {
20
  $this->definition = $definition;
21
  $this->shapeMap = $shapeMap;
@@ -49,6 +49,6 @@ abstract class AbstractModel implements \ArrayAccess
49
  }
50
  protected function shapeFor(array $definition)
51
  {
52
- return isset($definition['shape']) ? $this->shapeMap->resolve($definition) : \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape::create($definition, $this->shapeMap);
53
  }
54
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
  /**
6
  * Base class that is used by most API shapes
15
  * @param array $definition Service description
16
  * @param ShapeMap $shapeMap Shapemap used for creating shapes
17
  */
18
+ public function __construct(array $definition, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ShapeMap $shapeMap)
19
  {
20
  $this->definition = $definition;
21
  $this->shapeMap = $shapeMap;
49
  }
50
  protected function shapeFor(array $definition)
51
  {
52
+ return isset($definition['shape']) ? $this->shapeMap->resolve($definition) : \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape::create($definition, $this->shapeMap);
53
  }
54
  }
vendor/Aws3/Aws/Api/ApiProvider.php CHANGED
@@ -1,8 +1,8 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Exception\UnresolvedApiException;
6
  /**
7
  * API providers.
8
  *
@@ -72,7 +72,7 @@ class ApiProvider
72
  } else {
73
  $msg = "You must specify a service name to retrieve its API data.";
74
  }
75
- throw new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Exception\UnresolvedApiException($msg);
76
  }
77
  /**
78
  * Default SDK API provider.
@@ -83,7 +83,7 @@ class ApiProvider
83
  */
84
  public static function defaultProvider()
85
  {
86
- return new self(__DIR__ . '/../data', \DeliciousBrains\WP_Offload_S3\Aws3\Aws\manifest());
87
  }
88
  /**
89
  * Loads API data after resolving the version to the latest, compatible,
@@ -174,7 +174,7 @@ class ApiProvider
174
  $version = $this->manifest[$service]['versions'][$version];
175
  $path = "{$this->modelsDir}/{$service}/{$version}/{$type}.json";
176
  try {
177
- return \DeliciousBrains\WP_Offload_S3\Aws3\Aws\load_compiled_json($path);
178
  } catch (\InvalidArgumentException $e) {
179
  return null;
180
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedApiException;
6
  /**
7
  * API providers.
8
  *
72
  } else {
73
  $msg = "You must specify a service name to retrieve its API data.";
74
  }
75
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\UnresolvedApiException($msg);
76
  }
77
  /**
78
  * Default SDK API provider.
83
  */
84
  public static function defaultProvider()
85
  {
86
+ return new self(__DIR__ . '/../data', \DeliciousBrains\WP_Offload_Media\Aws3\Aws\manifest());
87
  }
88
  /**
89
  * Loads API data after resolving the version to the latest, compatible,
174
  $version = $this->manifest[$service]['versions'][$version];
175
  $path = "{$this->modelsDir}/{$service}/{$version}/{$type}.json";
176
  try {
177
+ return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\load_compiled_json($path);
178
  } catch (\InvalidArgumentException $e) {
179
  return null;
180
  }
vendor/Aws3/Aws/Api/DateTimeResult.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
  /**
6
  * DateTime overrides that make DateTime work more seamlessly as a string,
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
  /**
6
  * DateTime overrides that make DateTime work more seamlessly as a string,
vendor/Aws3/Aws/Api/DocModel.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
  /**
6
  * Encapsulates the documentation strings for a given service-version and
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
  /**
6
  * Encapsulates the documentation strings for a given service-version and
vendor/Aws3/Aws/Api/ErrorParser/JsonParserTrait.php CHANGED
@@ -1,16 +1,16 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ErrorParser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\PayloadParserTrait;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface;
7
  /**
8
  * Provides basic JSON error parsing functionality.
9
  */
10
  trait JsonParserTrait
11
  {
12
  use PayloadParserTrait;
13
- private function genericHandler(\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response)
14
  {
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())];
1
  <?php
2
 
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.
9
  */
10
  trait JsonParserTrait
11
  {
12
  use PayloadParserTrait;
13
+ private function genericHandler(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
14
  {
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())];
vendor/Aws3/Aws/Api/ErrorParser/JsonRpcErrorParser.php CHANGED
@@ -1,15 +1,15 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ErrorParser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface;
6
  /**
7
  * Parsers JSON-RPC errors.
8
  */
9
  class JsonRpcErrorParser
10
  {
11
  use JsonParserTrait;
12
- public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response)
13
  {
14
  $data = $this->genericHandler($response);
15
  // Make the casing consistent across services.
1
  <?php
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
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
13
  {
14
  $data = $this->genericHandler($response);
15
  // Make the casing consistent across services.
vendor/Aws3/Aws/Api/ErrorParser/RestJsonErrorParser.php CHANGED
@@ -1,15 +1,15 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ErrorParser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface;
6
  /**
7
  * Parses JSON-REST errors.
8
  */
9
  class RestJsonErrorParser
10
  {
11
  use JsonParserTrait;
12
- public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response)
13
  {
14
  $data = $this->genericHandler($response);
15
  // Merge in error data from the JSON body
1
  <?php
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
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
13
  {
14
  $data = $this->genericHandler($response);
15
  // Merge in error data from the JSON body
vendor/Aws3/Aws/Api/ErrorParser/XmlErrorParser.php CHANGED
@@ -1,16 +1,16 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ErrorParser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\PayloadParserTrait;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface;
7
  /**
8
  * Parses XML errors.
9
  */
10
  class XmlErrorParser
11
  {
12
  use PayloadParserTrait;
13
- public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response)
14
  {
15
  $code = (string) $response->getStatusCode();
16
  $data = ['type' => $code[0] == '4' ? 'client' : 'server', 'request_id' => null, 'code' => null, 'message' => null, 'parsed' => null];
@@ -22,7 +22,7 @@ class XmlErrorParser
22
  }
23
  return $data;
24
  }
25
- private function parseHeaders(\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response, array &$data)
26
  {
27
  if ($response->getStatusCode() == '404') {
28
  $data['code'] = 'NotFound';
1
  <?php
2
 
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
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
14
  {
15
  $code = (string) $response->getStatusCode();
16
  $data = ['type' => $code[0] == '4' ? 'client' : 'server', 'request_id' => null, 'code' => null, 'message' => null, 'parsed' => null];
22
  }
23
  return $data;
24
  }
25
+ private function parseHeaders(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, array &$data)
26
  {
27
  if ($response->getStatusCode() == '404') {
28
  $data['code'] = 'NotFound';
vendor/Aws3/Aws/Api/ListShape.php CHANGED
@@ -1,14 +1,14 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
  /**
6
  * Represents a list shape.
7
  */
8
- class ListShape extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape
9
  {
10
  private $member;
11
- public function __construct(array $definition, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ShapeMap $shapeMap)
12
  {
13
  $definition['type'] = 'list';
14
  parent::__construct($definition, $shapeMap);
@@ -23,7 +23,7 @@ class ListShape extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape
23
  if (!isset($this->definition['member'])) {
24
  throw new \RuntimeException('No member attribute specified');
25
  }
26
- $this->member = \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape::create($this->definition['member'], $this->shapeMap);
27
  }
28
  return $this->member;
29
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
  /**
6
  * Represents a list shape.
7
  */
8
+ class ListShape extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape
9
  {
10
  private $member;
11
+ public function __construct(array $definition, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ShapeMap $shapeMap)
12
  {
13
  $definition['type'] = 'list';
14
  parent::__construct($definition, $shapeMap);
23
  if (!isset($this->definition['member'])) {
24
  throw new \RuntimeException('No member attribute specified');
25
  }
26
+ $this->member = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape::create($this->definition['member'], $this->shapeMap);
27
  }
28
  return $this->member;
29
  }
vendor/Aws3/Aws/Api/MapShape.php CHANGED
@@ -1,17 +1,17 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
  /**
6
  * Represents a map shape.
7
  */
8
- class MapShape extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape
9
  {
10
  /** @var Shape */
11
  private $value;
12
  /** @var Shape */
13
  private $key;
14
- public function __construct(array $definition, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ShapeMap $shapeMap)
15
  {
16
  $definition['type'] = 'map';
17
  parent::__construct($definition, $shapeMap);
@@ -26,7 +26,7 @@ class MapShape extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape
26
  if (!isset($this->definition['value'])) {
27
  throw new \RuntimeException('No value specified');
28
  }
29
- $this->value = \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape::create($this->definition['value'], $this->shapeMap);
30
  }
31
  return $this->value;
32
  }
@@ -36,7 +36,7 @@ class MapShape extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape
36
  public function getKey()
37
  {
38
  if (!$this->key) {
39
- $this->key = isset($this->definition['key']) ? \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape::create($this->definition['key'], $this->shapeMap) : new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape(['type' => 'string'], $this->shapeMap);
40
  }
41
  return $this->key;
42
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
  /**
6
  * Represents a map shape.
7
  */
8
+ class MapShape extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape
9
  {
10
  /** @var Shape */
11
  private $value;
12
  /** @var Shape */
13
  private $key;
14
+ public function __construct(array $definition, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ShapeMap $shapeMap)
15
  {
16
  $definition['type'] = 'map';
17
  parent::__construct($definition, $shapeMap);
26
  if (!isset($this->definition['value'])) {
27
  throw new \RuntimeException('No value specified');
28
  }
29
+ $this->value = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape::create($this->definition['value'], $this->shapeMap);
30
  }
31
  return $this->value;
32
  }
36
  public function getKey()
37
  {
38
  if (!$this->key) {
39
+ $this->key = isset($this->definition['key']) ? \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape::create($this->definition['key'], $this->shapeMap) : new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape(['type' => 'string'], $this->shapeMap);
40
  }
41
  return $this->key;
42
  }
vendor/Aws3/Aws/Api/Operation.php CHANGED
@@ -1,16 +1,16 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
  /**
6
  * Represents an API operation.
7
  */
8
- class Operation extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\AbstractModel
9
  {
10
  private $input;
11
  private $output;
12
  private $errors;
13
- public function __construct(array $definition, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ShapeMap $shapeMap)
14
  {
15
  $definition['type'] = 'structure';
16
  if (!isset($definition['http']['method'])) {
@@ -44,7 +44,7 @@ class Operation extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\AbstractMode
44
  if ($input = $this['input']) {
45
  $this->input = $this->shapeFor($input);
46
  } else {
47
- $this->input = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape([], $this->shapeMap);
48
  }
49
  }
50
  return $this->input;
@@ -60,7 +60,7 @@ class Operation extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\AbstractMode
60
  if ($output = $this['output']) {
61
  $this->output = $this->shapeFor($output);
62
  } else {
63
- $this->output = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape([], $this->shapeMap);
64
  }
65
  }
66
  return $this->output;
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
  /**
6
  * Represents an API operation.
7
  */
8
+ class Operation extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\AbstractModel
9
  {
10
  private $input;
11
  private $output;
12
  private $errors;
13
+ public function __construct(array $definition, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ShapeMap $shapeMap)
14
  {
15
  $definition['type'] = 'structure';
16
  if (!isset($definition['http']['method'])) {
44
  if ($input = $this['input']) {
45
  $this->input = $this->shapeFor($input);
46
  } else {
47
+ $this->input = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape([], $this->shapeMap);
48
  }
49
  }
50
  return $this->input;
60
  if ($output = $this['output']) {
61
  $this->output = $this->shapeFor($output);
62
  } else {
63
+ $this->output = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape([], $this->shapeMap);
64
  }
65
  }
66
  return $this->output;
vendor/Aws3/Aws/Api/Parser/AbstractParser.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\ResultInterface;
8
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface;
9
  /**
10
  * @internal
11
  */
@@ -16,7 +16,7 @@ abstract class AbstractParser
16
  /**
17
  * @param Service $api Service description.
18
  */
19
- public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api)
20
  {
21
  $this->api = $api;
22
  }
@@ -26,5 +26,5 @@ abstract class AbstractParser
26
  *
27
  * @return ResultInterface
28
  */
29
- public abstract function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response);
30
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\ResultInterface;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
9
  /**
10
  * @internal
11
  */
16
  /**
17
  * @param Service $api Service description.
18
  */
19
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api)
20
  {
21
  $this->api = $api;
22
  }
26
  *
27
  * @return ResultInterface
28
  */
29
+ public abstract function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response);
30
  }
vendor/Aws3/Aws/Api/Parser/AbstractRestParser.php CHANGED
@@ -1,17 +1,17 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\DateTimeResult;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape;
8
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Result;
9
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface;
10
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface;
11
  /**
12
  * @internal
13
  */
14
- abstract class AbstractRestParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\AbstractParser
15
  {
16
  use PayloadParserTrait;
17
  /**
@@ -23,8 +23,8 @@ abstract class AbstractRestParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aw
23
  *
24
  * @return mixed
25
  */
26
- protected abstract function payload(\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $member, array &$result);
27
- public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response)
28
  {
29
  $output = $this->api->getOperation($command->getName())->getOutput();
30
  $result = [];
@@ -48,9 +48,9 @@ abstract class AbstractRestParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aw
48
  // if no payload was found, then parse the contents of the body
49
  $this->payload($response, $output, $result);
50
  }
51
- return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Result($result);
52
  }
53
- private function extractPayload($payload, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $output, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response, array &$result)
54
  {
55
  $member = $output->getMember($payload);
56
  if ($member instanceof StructureShape) {
@@ -65,7 +65,7 @@ abstract class AbstractRestParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aw
65
  /**
66
  * Extract a single header from the response into the result.
67
  */
68
- private function extractHeader($name, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response, &$result)
69
  {
70
  $value = $response->getHeaderLine($shape['locationName'] ?: $name);
71
  switch ($shape->getType()) {
@@ -84,7 +84,7 @@ abstract class AbstractRestParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aw
84
  break;
85
  case 'timestamp':
86
  try {
87
- $value = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\DateTimeResult($value);
88
  break;
89
  } catch (\Exception $e) {
90
  // If the value cannot be parsed, then do not add it to the
@@ -102,7 +102,7 @@ abstract class AbstractRestParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aw
102
  /**
103
  * Extract a map of headers with an optional prefix from the response.
104
  */
105
- private function extractHeaders($name, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response, &$result)
106
  {
107
  // Check if the headers are prefixed by a location name
108
  $result[$name] = [];
@@ -119,7 +119,7 @@ abstract class AbstractRestParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aw
119
  /**
120
  * Places the status code of the response into the result array.
121
  */
122
- private function extractStatus($name, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response, array &$result)
123
  {
124
  $result[$name] = (int) $response->getStatusCode();
125
  }
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\Aws\Api\StructureShape;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Result;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
10
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
11
  /**
12
  * @internal
13
  */
14
+ abstract class AbstractRestParser extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\AbstractParser
15
  {
16
  use PayloadParserTrait;
17
  /**
23
  *
24
  * @return mixed
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, array &$result);
27
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
28
  {
29
  $output = $this->api->getOperation($command->getName())->getOutput();
30
  $result = [];
48
  // if no payload was found, then parse the contents of the body
49
  $this->payload($response, $output, $result);
50
  }
51
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Result($result);
52
  }
53
+ private function extractPayload($payload, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $output, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, array &$result)
54
  {
55
  $member = $output->getMember($payload);
56
  if ($member instanceof StructureShape) {
65
  /**
66
  * Extract a single header from the response into the result.
67
  */
68
+ private function extractHeader($name, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, &$result)
69
  {
70
  $value = $response->getHeaderLine($shape['locationName'] ?: $name);
71
  switch ($shape->getType()) {
84
  break;
85
  case 'timestamp':
86
  try {
87
+ $value = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult($value);
88
  break;
89
  } catch (\Exception $e) {
90
  // If the value cannot be parsed, then do not add it to the
102
  /**
103
  * Extract a map of headers with an optional prefix from the response.
104
  */
105
+ private function extractHeaders($name, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, &$result)
106
  {
107
  // Check if the headers are prefixed by a location name
108
  $result[$name] = [];
119
  /**
120
  * Places the status code of the response into the result array.
121
  */
122
+ private function extractStatus($name, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, array &$result)
123
  {
124
  $result[$name] = (int) $response->getStatusCode();
125
  }
vendor/Aws3/Aws/Api/Parser/Crc32ValidatingParser.php CHANGED
@@ -1,15 +1,15 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Exception\AwsException;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface;
8
- use DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7;
9
  /**
10
  * @internal Decorates a parser and validates the x-amz-crc32 header.
11
  */
12
- class Crc32ValidatingParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\AbstractParser
13
  {
14
  /** @var callable */
15
  private $parser;
@@ -20,12 +20,12 @@ class Crc32ValidatingParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\
20
  {
21
  $this->parser = $parser;
22
  }
23
- public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response)
24
  {
25
  if ($expected = $response->getHeaderLine('x-amz-crc32')) {
26
- $hash = hexdec(\DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\hash($response->getBody(), 'crc32b'));
27
  if ($expected != $hash) {
28
- throw new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Exception\AwsException("crc32 mismatch. Expected {$expected}, found {$hash}.", $command, ['code' => 'ClientChecksumMismatch', 'connection_error' => true, 'response' => $response]);
29
  }
30
  }
31
  $fn = $this->parser;
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
9
  /**
10
  * @internal Decorates a parser and validates the x-amz-crc32 header.
11
  */
12
+ class Crc32ValidatingParser extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\AbstractParser
13
  {
14
  /** @var callable */
15
  private $parser;
20
  {
21
  $this->parser = $parser;
22
  }
23
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
24
  {
25
  if ($expected = $response->getHeaderLine('x-amz-crc32')) {
26
+ $hash = hexdec(\DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\hash($response->getBody(), 'crc32b'));
27
  if ($expected != $hash) {
28
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Exception\AwsException("crc32 mismatch. Expected {$expected}, found {$hash}.", $command, ['code' => 'ClientChecksumMismatch', 'connection_error' => true, 'response' => $response]);
29
  }
30
  }
31
  $fn = $this->parser;
vendor/Aws3/Aws/Api/Parser/Exception/ParserException.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\Exception;
4
 
5
  class ParserException extends \RuntimeException
6
  {
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\Exception;
4
 
5
  class ParserException extends \RuntimeException
6
  {
vendor/Aws3/Aws/Api/Parser/JsonParser.php CHANGED
@@ -1,15 +1,15 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\DateTimeResult;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape;
7
  /**
8
  * @internal Implements standard JSON parsing.
9
  */
10
  class JsonParser
11
  {
12
- public function parse(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value)
13
  {
14
  if ($value === null) {
15
  return $value;
@@ -42,7 +42,7 @@ class JsonParser
42
  // The Unix epoch (or Unix time or POSIX time or Unix
43
  // timestamp) is the number of seconds that have elapsed since
44
  // January 1, 1970 (midnight UTC/GMT).
45
- return \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\DateTimeResult::fromEpoch($value);
46
  case 'blob':
47
  return base64_decode($value);
48
  default:
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
  /**
8
  * @internal Implements standard JSON parsing.
9
  */
10
  class JsonParser
11
  {
12
+ public function parse(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $value)
13
  {
14
  if ($value === null) {
15
  return $value;
42
  // The Unix epoch (or Unix time or POSIX time or Unix
43
  // timestamp) is the number of seconds that have elapsed since
44
  // January 1, 1970 (midnight UTC/GMT).
45
+ return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult::fromEpoch($value);
46
  case 'blob':
47
  return base64_decode($value);
48
  default:
vendor/Aws3/Aws/Api/Parser/JsonRpcParser.php CHANGED
@@ -1,15 +1,15 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Result;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface;
8
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface;
9
  /**
10
  * @internal Implements JSON-RPC parsing (e.g., DynamoDB)
11
  */
12
- class JsonRpcParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\AbstractParser
13
  {
14
  use PayloadParserTrait;
15
  private $parser;
@@ -17,15 +17,15 @@ class JsonRpcParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\A
17
  * @param Service $api Service description
18
  * @param JsonParser $parser JSON body builder
19
  */
20
- public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\JsonParser $parser = null)
21
  {
22
  parent::__construct($api);
23
- $this->parser = $parser ?: new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\JsonParser();
24
  }
25
- public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response)
26
  {
27
  $operation = $this->api->getOperation($command->getName());
28
  $result = null === $operation['output'] ? null : $this->parser->parse($operation->getOutput(), $this->parseJson($response->getBody()));
29
- return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Result($result ?: []);
30
  }
31
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Result;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
9
  /**
10
  * @internal Implements JSON-RPC parsing (e.g., DynamoDB)
11
  */
12
+ class JsonRpcParser extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\AbstractParser
13
  {
14
  use PayloadParserTrait;
15
  private $parser;
17
  * @param Service $api Service description
18
  * @param JsonParser $parser JSON body builder
19
  */
20
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser $parser = null)
21
  {
22
  parent::__construct($api);
23
+ $this->parser = $parser ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser();
24
  }
25
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
26
  {
27
  $operation = $this->api->getOperation($command->getName());
28
  $result = null === $operation['output'] ? null : $this->parser->parse($operation->getOutput(), $this->parseJson($response->getBody()));
29
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Result($result ?: []);
30
  }
31
  }
vendor/Aws3/Aws/Api/Parser/PayloadParserTrait.php CHANGED
@@ -1,8 +1,8 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\Exception\ParserException;
6
  trait PayloadParserTrait
7
  {
8
  /**
@@ -16,7 +16,7 @@ trait PayloadParserTrait
16
  {
17
  $jsonPayload = json_decode($json, true);
18
  if (JSON_ERROR_NONE !== json_last_error()) {
19
- throw new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\Exception\ParserException('Error parsing JSON: ' . json_last_error_msg());
20
  }
21
  return $jsonPayload;
22
  }
@@ -37,7 +37,7 @@ trait PayloadParserTrait
37
  throw new \RuntimeException($error->message);
38
  }
39
  } catch (\Exception $e) {
40
- throw new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\Exception\ParserException("Error parsing XML: {$e->getMessage()}", 0, $e);
41
  } finally {
42
  libxml_use_internal_errors($priorSetting);
43
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\Exception\ParserException;
6
  trait PayloadParserTrait
7
  {
8
  /**
16
  {
17
  $jsonPayload = json_decode($json, true);
18
  if (JSON_ERROR_NONE !== json_last_error()) {
19
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\Exception\ParserException('Error parsing JSON: ' . json_last_error_msg());
20
  }
21
  return $jsonPayload;
22
  }
37
  throw new \RuntimeException($error->message);
38
  }
39
  } catch (\Exception $e) {
40
+ throw new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\Exception\ParserException("Error parsing XML: {$e->getMessage()}", 0, $e);
41
  } finally {
42
  libxml_use_internal_errors($priorSetting);
43
  }
vendor/Aws3/Aws/Api/Parser/QueryParser.php CHANGED
@@ -1,15 +1,15 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Result;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface;
8
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface;
9
  /**
10
  * @internal Parses query (XML) responses (e.g., EC2, SQS, and many others)
11
  */
12
- class QueryParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\AbstractParser
13
  {
14
  use PayloadParserTrait;
15
  /** @var XmlParser */
@@ -23,19 +23,19 @@ class QueryParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\Abs
23
  * back of result wrappers from the
24
  * output structure.
25
  */
26
- public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\XmlParser $xmlParser = null, $honorResultWrapper = true)
27
  {
28
  parent::__construct($api);
29
- $this->xmlParser = $xmlParser ?: new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\XmlParser();
30
  $this->honorResultWrapper = $honorResultWrapper;
31
  }
32
- public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response)
33
  {
34
  $output = $this->api->getOperation($command->getName())->getOutput();
35
  $xml = $this->parseXml($response->getBody());
36
  if ($this->honorResultWrapper && $output['resultWrapper']) {
37
  $xml = $xml->{$output['resultWrapper']};
38
  }
39
- return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Result($this->xmlParser->parse($output, $xml));
40
  }
41
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Result;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
9
  /**
10
  * @internal Parses query (XML) responses (e.g., EC2, SQS, and many others)
11
  */
12
+ class QueryParser extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\AbstractParser
13
  {
14
  use PayloadParserTrait;
15
  /** @var XmlParser */
23
  * back of result wrappers from the
24
  * output structure.
25
  */
26
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\XmlParser $xmlParser = null, $honorResultWrapper = true)
27
  {
28
  parent::__construct($api);
29
+ $this->xmlParser = $xmlParser ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\XmlParser();
30
  $this->honorResultWrapper = $honorResultWrapper;
31
  }
32
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command, \DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response)
33
  {
34
  $output = $this->api->getOperation($command->getName())->getOutput();
35
  $xml = $this->parseXml($response->getBody());
36
  if ($this->honorResultWrapper && $output['resultWrapper']) {
37
  $xml = $xml->{$output['resultWrapper']};
38
  }
39
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Result($this->xmlParser->parse($output, $xml));
40
  }
41
  }
vendor/Aws3/Aws/Api/Parser/RestJsonParser.php CHANGED
@@ -1,14 +1,14 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface;
8
  /**
9
  * @internal Implements REST-JSON parsing (e.g., Glacier, Elastic Transcoder)
10
  */
11
- class RestJsonParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\AbstractRestParser
12
  {
13
  use PayloadParserTrait;
14
  /** @var JsonParser */
@@ -17,12 +17,12 @@ class RestJsonParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\
17
  * @param Service $api Service description
18
  * @param JsonParser $parser JSON body builder
19
  */
20
- public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\JsonParser $parser = null)
21
  {
22
  parent::__construct($api);
23
- $this->parser = $parser ?: new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\JsonParser();
24
  }
25
- protected function payload(\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $member, array &$result)
26
  {
27
  $jsonBody = $this->parseJson($response->getBody());
28
  if ($jsonBody) {
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
8
  /**
9
  * @internal Implements REST-JSON parsing (e.g., Glacier, Elastic Transcoder)
10
  */
11
+ class RestJsonParser extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\AbstractRestParser
12
  {
13
  use PayloadParserTrait;
14
  /** @var JsonParser */
17
  * @param Service $api Service description
18
  * @param JsonParser $parser JSON body builder
19
  */
20
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser $parser = null)
21
  {
22
  parent::__construct($api);
23
+ $this->parser = $parser ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\JsonParser();
24
  }
25
+ protected function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member, array &$result)
26
  {
27
  $jsonBody = $this->parseJson($response->getBody());
28
  if ($jsonBody) {
vendor/Aws3/Aws/Api/Parser/RestXmlParser.php CHANGED
@@ -1,14 +1,14 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface;
8
  /**
9
  * @internal Implements REST-XML parsing (e.g., S3, CloudFront, etc...)
10
  */
11
- class RestXmlParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\AbstractRestParser
12
  {
13
  use PayloadParserTrait;
14
  /** @var XmlParser */
@@ -17,12 +17,12 @@ class RestXmlParser extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\A
17
  * @param Service $api Service description
18
  * @param XmlParser $parser XML body parser
19
  */
20
- public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\XmlParser $parser = null)
21
  {
22
  parent::__construct($api);
23
- $this->parser = $parser ?: new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\XmlParser();
24
  }
25
- protected function payload(\DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $member, array &$result)
26
  {
27
  $xml = $this->parseXml($response->getBody());
28
  $result += $this->parser->parse($member, $xml);
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface;
8
  /**
9
  * @internal Implements REST-XML parsing (e.g., S3, CloudFront, etc...)
10
  */
11
+ class RestXmlParser extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\AbstractRestParser
12
  {
13
  use PayloadParserTrait;
14
  /** @var XmlParser */
17
  * @param Service $api Service description
18
  * @param XmlParser $parser XML body parser
19
  */
20
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\XmlParser $parser = null)
21
  {
22
  parent::__construct($api);
23
+ $this->parser = $parser ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\XmlParser();
24
  }
25
+ protected function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\ResponseInterface $response, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member, array &$result)
26
  {
27
  $xml = $this->parseXml($response->getBody());
28
  $result += $this->parser->parse($member, $xml);
vendor/Aws3/Aws/Api/Parser/XmlParser.php CHANGED
@@ -1,18 +1,18 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\DateTimeResult;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ListShape;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\MapShape;
8
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape;
9
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape;
10
  /**
11
  * @internal Implements standard XML parsing for REST-XML and Query protocols.
12
  */
13
  class XmlParser
14
  {
15
- public function parse(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $shape, \SimpleXMLElement $value)
16
  {
17
  return $this->dispatch($shape, $value);
18
  }
@@ -25,7 +25,7 @@ class XmlParser
25
  }
26
  return (string) $value;
27
  }
28
- private function parse_structure(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $shape, \SimpleXMLElement $value)
29
  {
30
  $target = [];
31
  foreach ($shape->getMembers() as $name => $member) {
@@ -37,7 +37,7 @@ class XmlParser
37
  }
38
  return $target;
39
  }
40
- private function memberKey(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $name)
41
  {
42
  if (null !== $shape['locationName']) {
43
  return $shape['locationName'];
@@ -47,7 +47,7 @@ class XmlParser
47
  }
48
  return $name;
49
  }
50
- private function parse_list(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ListShape $shape, \SimpleXMLElement $value)
51
  {
52
  $target = [];
53
  $member = $shape->getMember();
@@ -59,7 +59,7 @@ class XmlParser
59
  }
60
  return $target;
61
  }
62
- private function parse_map(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\MapShape $shape, \SimpleXMLElement $value)
63
  {
64
  $target = [];
65
  if (!$shape['flattened']) {
@@ -76,24 +76,24 @@ class XmlParser
76
  }
77
  return $target;
78
  }
79
- private function parse_blob(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value)
80
  {
81
  return base64_decode((string) $value);
82
  }
83
- private function parse_float(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value)
84
  {
85
  return (double) (string) $value;
86
  }
87
- private function parse_integer(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value)
88
  {
89
  return (int) (string) $value;
90
  }
91
- private function parse_boolean(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value)
92
  {
93
  return $value == 'true';
94
  }
95
- private function parse_timestamp(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value)
96
  {
97
- return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\DateTimeResult($value);
98
  }
99
  }
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\ListShape;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\MapShape;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
10
  /**
11
  * @internal Implements standard XML parsing for REST-XML and Query protocols.
12
  */
13
  class XmlParser
14
  {
15
+ public function parse(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $shape, \SimpleXMLElement $value)
16
  {
17
  return $this->dispatch($shape, $value);
18
  }
25
  }
26
  return (string) $value;
27
  }
28
+ private function parse_structure(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $shape, \SimpleXMLElement $value)
29
  {
30
  $target = [];
31
  foreach ($shape->getMembers() as $name => $member) {
37
  }
38
  return $target;
39
  }
40
+ private function memberKey(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $name)
41
  {
42
  if (null !== $shape['locationName']) {
43
  return $shape['locationName'];
47
  }
48
  return $name;
49
  }
50
+ private function parse_list(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ListShape $shape, \SimpleXMLElement $value)
51
  {
52
  $target = [];
53
  $member = $shape->getMember();
59
  }
60
  return $target;
61
  }
62
+ private function parse_map(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\MapShape $shape, \SimpleXMLElement $value)
63
  {
64
  $target = [];
65
  if (!$shape['flattened']) {
76
  }
77
  return $target;
78
  }
79
+ private function parse_blob(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $value)
80
  {
81
  return base64_decode((string) $value);
82
  }
83
+ private function parse_float(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $value)
84
  {
85
  return (double) (string) $value;
86
  }
87
+ private function parse_integer(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $value)
88
  {
89
  return (int) (string) $value;
90
  }
91
+ private function parse_boolean(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $value)
92
  {
93
  return $value == 'true';
94
  }
95
+ private function parse_timestamp(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $value)
96
  {
97
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\DateTimeResult($value);
98
  }
99
  }
vendor/Aws3/Aws/Api/Serializer/Ec2ParamBuilder.php CHANGED
@@ -1,23 +1,23 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ListShape;
7
  /**
8
  * @internal
9
  */
10
- class Ec2ParamBuilder extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\QueryParamBuilder
11
  {
12
- protected function queryName(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $default = null)
13
  {
14
  return $shape['queryName'] ?: ucfirst($shape['locationName']) ?: $default;
15
  }
16
- protected function isFlat(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape)
17
  {
18
  return false;
19
  }
20
- protected function format_list(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ListShape $shape, array $value, $prefix, &$query)
21
  {
22
  // Handle empty list serialization
23
  if (!$value) {
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ListShape;
7
  /**
8
  * @internal
9
  */
10
+ class Ec2ParamBuilder extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\QueryParamBuilder
11
  {
12
+ protected function queryName(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $default = null)
13
  {
14
  return $shape['queryName'] ?: ucfirst($shape['locationName']) ?: $default;
15
  }
16
+ protected function isFlat(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape)
17
  {
18
  return false;
19
  }
20
+ protected function format_list(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ListShape $shape, array $value, $prefix, &$query)
21
  {
22
  // Handle empty list serialization
23
  if (!$value) {
vendor/Aws3/Aws/Api/Serializer/JsonBody.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\TimestampShape;
8
  /**
9
  * Formats the JSON body of a JSON-REST or JSON-RPC operation.
10
  * @internal
@@ -12,7 +12,7 @@ use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\TimestampShape;
12
  class JsonBody
13
  {
14
  private $api;
15
- public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api)
16
  {
17
  $this->api = $api;
18
  }
@@ -23,7 +23,7 @@ class JsonBody
23
  *
24
  * @return string
25
  */
26
- public static function getContentType(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $service)
27
  {
28
  return 'application/x-amz-json-' . number_format($service->getMetadata('jsonVersion'), 1);
29
  }
@@ -35,12 +35,12 @@ class JsonBody
35
  *
36
  * @return string
37
  */
38
- public function build(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, array $args)
39
  {
40
  $result = json_encode($this->format($shape, $args));
41
  return $result == '[]' ? '{}' : $result;
42
  }
43
- private function format(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value)
44
  {
45
  switch ($shape['type']) {
46
  case 'structure':
@@ -70,7 +70,7 @@ class JsonBody
70
  case 'blob':
71
  return base64_encode($value);
72
  case 'timestamp':
73
- return \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\TimestampShape::format($value, 'unixTimestamp');
74
  default:
75
  return $value;
76
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\TimestampShape;
8
  /**
9
  * Formats the JSON body of a JSON-REST or JSON-RPC operation.
10
  * @internal
12
  class JsonBody
13
  {
14
  private $api;
15
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api)
16
  {
17
  $this->api = $api;
18
  }
23
  *
24
  * @return string
25
  */
26
+ public static function getContentType(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $service)
27
  {
28
  return 'application/x-amz-json-' . number_format($service->getMetadata('jsonVersion'), 1);
29
  }
35
  *
36
  * @return string
37
  */
38
+ public function build(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, array $args)
39
  {
40
  $result = json_encode($this->format($shape, $args));
41
  return $result == '[]' ? '{}' : $result;
42
  }
43
+ private function format(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $value)
44
  {
45
  switch ($shape['type']) {
46
  case 'structure':
70
  case 'blob':
71
  return base64_encode($value);
72
  case 'timestamp':
73
+ return \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\TimestampShape::format($value, 'unixTimestamp');
74
  default:
75
  return $value;
76
  }
vendor/Aws3/Aws/Api/Serializer/JsonRpcSerializer.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Request;
8
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface;
9
  /**
10
  * Prepares a JSON-RPC request for transfer.
11
  * @internal
@@ -25,12 +25,12 @@ class JsonRpcSerializer
25
  * @param string $endpoint Endpoint to connect to
26
  * @param JsonBody $jsonFormatter Optional JSON formatter to use
27
  */
28
- public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api, $endpoint, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\JsonBody $jsonFormatter = null)
29
  {
30
  $this->endpoint = $endpoint;
31
  $this->api = $api;
32
- $this->jsonFormatter = $jsonFormatter ?: new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\JsonBody($this->api);
33
- $this->contentType = \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\JsonBody::getContentType($api);
34
  }
35
  /**
36
  * When invoked with an AWS command, returns a serialization array
@@ -40,10 +40,10 @@ class JsonRpcSerializer
40
  *
41
  * @return RequestInterface
42
  */
43
- public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command)
44
  {
45
  $name = $command->getName();
46
  $operation = $this->api->getOperation($name);
47
- return new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Request($operation['http']['method'], $this->endpoint, ['X-Amz-Target' => $this->api->getMetadata('targetPrefix') . '.' . $name, 'Content-Type' => $this->contentType], $this->jsonFormatter->build($operation->getInput(), $command->toArray()));
48
  }
49
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
9
  /**
10
  * Prepares a JSON-RPC request for transfer.
11
  * @internal
25
  * @param string $endpoint Endpoint to connect to
26
  * @param JsonBody $jsonFormatter Optional JSON formatter to use
27
  */
28
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, $endpoint, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody $jsonFormatter = null)
29
  {
30
  $this->endpoint = $endpoint;
31
  $this->api = $api;
32
+ $this->jsonFormatter = $jsonFormatter ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody($this->api);
33
+ $this->contentType = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody::getContentType($api);
34
  }
35
  /**
36
  * When invoked with an AWS command, returns a serialization array
40
  *
41
  * @return RequestInterface
42
  */
43
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command)
44
  {
45
  $name = $command->getName();
46
  $operation = $this->api->getOperation($name);
47
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request($operation['http']['method'], $this->endpoint, ['X-Amz-Target' => $this->api->getMetadata('targetPrefix') . '.' . $name, 'Content-Type' => $this->contentType], $this->jsonFormatter->build($operation->getInput(), $command->toArray()));
48
  }
49
  }
vendor/Aws3/Aws/Api/Serializer/QueryParamBuilder.php CHANGED
@@ -1,19 +1,19 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ListShape;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\MapShape;
8
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape;
9
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\TimestampShape;
10
  /**
11
  * @internal
12
  */
13
  class QueryParamBuilder
14
  {
15
  private $methods;
16
- protected function queryName(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $default = null)
17
  {
18
  if (null !== $shape['queryName']) {
19
  return $shape['queryName'];
@@ -26,11 +26,11 @@ class QueryParamBuilder
26
  }
27
  return $default;
28
  }
29
- protected function isFlat(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape)
30
  {
31
  return $shape['flattened'] === true;
32
  }
33
- public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $shape, array $params)
34
  {
35
  if (!$this->methods) {
36
  $this->methods = array_fill_keys(get_class_methods($this), true);
@@ -39,7 +39,7 @@ class QueryParamBuilder
39
  $this->format_structure($shape, $params, '', $query);
40
  return $query;
41
  }
42
- protected function format(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value, $prefix, array &$query)
43
  {
44
  $type = 'format_' . $shape['type'];
45
  if (isset($this->methods[$type])) {
@@ -48,7 +48,7 @@ class QueryParamBuilder
48
  $query[$prefix] = (string) $value;
49
  }
50
  }
51
- protected function format_structure(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $shape, array $value, $prefix, &$query)
52
  {
53
  if ($prefix) {
54
  $prefix .= '.';
@@ -60,7 +60,7 @@ class QueryParamBuilder
60
  }
61
  }
62
  }
63
- protected function format_list(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ListShape $shape, array $value, $prefix, &$query)
64
  {
65
  // Handle empty list serialization
66
  if (!$value) {
@@ -80,7 +80,7 @@ class QueryParamBuilder
80
  $this->format($items, $v, $prefix . '.' . ($k + 1), $query);
81
  }
82
  }
83
- protected function format_map(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\MapShape $shape, array $value, $prefix, array &$query)
84
  {
85
  $vals = $shape->getValue();
86
  $keys = $shape->getKey();
@@ -96,15 +96,15 @@ class QueryParamBuilder
96
  $this->format($vals, $v, sprintf($valueName, $prefix, $i), $query);
97
  }
98
  }
99
- protected function format_blob(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value, $prefix, array &$query)
100
  {
101
  $query[$prefix] = base64_encode($value);
102
  }
103
- protected function format_timestamp(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\TimestampShape $shape, $value, $prefix, array &$query)
104
  {
105
- $query[$prefix] = \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\TimestampShape::format($value, 'iso8601');
106
  }
107
- protected function format_boolean(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value, $prefix, array &$query)
108
  {
109
  $query[$prefix] = $value ? 'true' : 'false';
110
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ListShape;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\MapShape;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\TimestampShape;
10
  /**
11
  * @internal
12
  */
13
  class QueryParamBuilder
14
  {
15
  private $methods;
16
+ protected function queryName(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $default = null)
17
  {
18
  if (null !== $shape['queryName']) {
19
  return $shape['queryName'];
26
  }
27
  return $default;
28
  }
29
+ protected function isFlat(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape)
30
  {
31
  return $shape['flattened'] === true;
32
  }
33
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $shape, array $params)
34
  {
35
  if (!$this->methods) {
36
  $this->methods = array_fill_keys(get_class_methods($this), true);
39
  $this->format_structure($shape, $params, '', $query);
40
  return $query;
41
  }
42
+ protected function format(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $value, $prefix, array &$query)
43
  {
44
  $type = 'format_' . $shape['type'];
45
  if (isset($this->methods[$type])) {
48
  $query[$prefix] = (string) $value;
49
  }
50
  }
51
+ protected function format_structure(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $shape, array $value, $prefix, &$query)
52
  {
53
  if ($prefix) {
54
  $prefix .= '.';
60
  }
61
  }
62
  }
63
+ protected function format_list(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ListShape $shape, array $value, $prefix, &$query)
64
  {
65
  // Handle empty list serialization
66
  if (!$value) {
80
  $this->format($items, $v, $prefix . '.' . ($k + 1), $query);
81
  }
82
  }
83
+ protected function format_map(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\MapShape $shape, array $value, $prefix, array &$query)
84
  {
85
  $vals = $shape->getValue();
86
  $keys = $shape->getKey();
96
  $this->format($vals, $v, sprintf($valueName, $prefix, $i), $query);
97
  }
98
  }
99
+ protected function format_blob(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $value, $prefix, array &$query)
100
  {
101
  $query[$prefix] = base64_encode($value);
102
  }
103
+ protected function format_timestamp(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\TimestampShape $shape, $value, $prefix, array &$query)
104
  {
105
+ $query[$prefix] = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\TimestampShape::format($value, 'iso8601');
106
  }
107
+ protected function format_boolean(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $value, $prefix, array &$query)
108
  {
109
  $query[$prefix] = $value ? 'true' : 'false';
110
  }
vendor/Aws3/Aws/Api/Serializer/QuerySerializer.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Request;
8
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface;
9
  /**
10
  * Serializes a query protocol request.
11
  * @internal
@@ -15,11 +15,11 @@ class QuerySerializer
15
  private $endpoint;
16
  private $api;
17
  private $paramBuilder;
18
- public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api, $endpoint, callable $paramBuilder = null)
19
  {
20
  $this->api = $api;
21
  $this->endpoint = $endpoint;
22
- $this->paramBuilder = $paramBuilder ?: new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\QueryParamBuilder();
23
  }
24
  /**
25
  * When invoked with an AWS command, returns a serialization array
@@ -29,7 +29,7 @@ class QuerySerializer
29
  *
30
  * @return RequestInterface
31
  */
32
- public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command)
33
  {
34
  $operation = $this->api->getOperation($command->getName());
35
  $body = ['Action' => $command->getName(), 'Version' => $this->api->getMetadata('apiVersion')];
@@ -39,6 +39,6 @@ class QuerySerializer
39
  $body += call_user_func($this->paramBuilder, $operation->getInput(), $params);
40
  }
41
  $body = http_build_query($body, null, '&', PHP_QUERY_RFC3986);
42
- return new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Request('POST', $this->endpoint, ['Content-Length' => strlen($body), 'Content-Type' => 'application/x-www-form-urlencoded'], $body);
43
  }
44
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
9
  /**
10
  * Serializes a query protocol request.
11
  * @internal
15
  private $endpoint;
16
  private $api;
17
  private $paramBuilder;
18
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, $endpoint, callable $paramBuilder = null)
19
  {
20
  $this->api = $api;
21
  $this->endpoint = $endpoint;
22
+ $this->paramBuilder = $paramBuilder ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\QueryParamBuilder();
23
  }
24
  /**
25
  * When invoked with an AWS command, returns a serialization array
29
  *
30
  * @return RequestInterface
31
  */
32
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command)
33
  {
34
  $operation = $this->api->getOperation($command->getName());
35
  $body = ['Action' => $command->getName(), 'Version' => $this->api->getMetadata('apiVersion')];
39
  $body += call_user_func($this->paramBuilder, $operation->getInput(), $params);
40
  }
41
  $body = http_build_query($body, null, '&', PHP_QUERY_RFC3986);
42
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request('POST', $this->endpoint, ['Content-Length' => strlen($body), 'Content-Type' => 'application/x-www-form-urlencoded'], $body);
43
  }
44
  }
vendor/Aws3/Aws/Api/Serializer/RestJsonSerializer.php CHANGED
@@ -1,14 +1,14 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape;
7
  /**
8
  * Serializes requests for the REST-JSON protocol.
9
  * @internal
10
  */
11
- class RestJsonSerializer extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\RestSerializer
12
  {
13
  /** @var JsonBody */
14
  private $jsonFormatter;
@@ -19,13 +19,13 @@ class RestJsonSerializer extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Ser
19
  * @param string $endpoint Endpoint to connect to
20
  * @param JsonBody $jsonFormatter Optional JSON formatter to use
21
  */
22
- public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api, $endpoint, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\JsonBody $jsonFormatter = null)
23
  {
24
  parent::__construct($api, $endpoint);
25
- $this->contentType = \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\JsonBody::getContentType($api);
26
- $this->jsonFormatter = $jsonFormatter ?: new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\JsonBody($api);
27
  }
28
- protected function payload(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $member, array $value, array &$opts)
29
  {
30
  $opts['headers']['Content-Type'] = $this->contentType;
31
  $opts['body'] = (string) $this->jsonFormatter->build($member, $value);
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
7
  /**
8
  * Serializes requests for the REST-JSON protocol.
9
  * @internal
10
  */
11
+ class RestJsonSerializer extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\RestSerializer
12
  {
13
  /** @var JsonBody */
14
  private $jsonFormatter;
19
  * @param string $endpoint Endpoint to connect to
20
  * @param JsonBody $jsonFormatter Optional JSON formatter to use
21
  */
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 = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\JsonBody::getContentType($api);
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)
29
  {
30
  $opts['headers']['Content-Type'] = $this->contentType;
31
  $opts['body'] = (string) $this->jsonFormatter->build($member, $value);
vendor/Aws3/Aws/Api/Serializer/RestSerializer.php CHANGED
@@ -1,18 +1,18 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\MapShape;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Operation;
8
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape;
9
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape;
10
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\TimestampShape;
11
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface;
12
- use DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7;
13
- use DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Uri;
14
- use DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\UriResolver;
15
- use DeliciousBrains\WP_Offload_S3\Aws3\Psr\Http\Message\RequestInterface;
16
  /**
17
  * Serializes HTTP locations like header, uri, payload, etc...
18
  * @internal
@@ -27,23 +27,23 @@ abstract class RestSerializer
27
  * @param Service $api Service API description
28
  * @param string $endpoint Endpoint to connect to
29
  */
30
- public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api, $endpoint)
31
  {
32
  $this->api = $api;
33
- $this->endpoint = \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\uri_for($endpoint);
34
  }
35
  /**
36
  * @param CommandInterface $command Command to serialized
37
  *
38
  * @return RequestInterface
39
  */
40
- public function __invoke(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\CommandInterface $command)
41
  {
42
  $operation = $this->api->getOperation($command->getName());
43
  $args = $command->toArray();
44
  $opts = $this->serialize($operation, $args);
45
  $uri = $this->buildEndpoint($operation, $args, $opts);
46
- return new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Request($operation['http']['method'], $uri, isset($opts['headers']) ? $opts['headers'] : [], isset($opts['body']) ? $opts['body'] : null);
47
  }
48
  /**
49
  * Modifies a hash of request options for a payload body.
@@ -52,8 +52,8 @@ abstract class RestSerializer
52
  * @param array $value Value to serialize
53
  * @param array $opts Request options to modify.
54
  */
55
- protected abstract function payload(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $member, array $value, array &$opts);
56
- private function serialize(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Operation $operation, array $args)
57
  {
58
  $opts = [];
59
  $input = $operation->getInput();
@@ -81,7 +81,7 @@ abstract class RestSerializer
81
  }
82
  return $opts;
83
  }
84
- private function applyPayload(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $input, $name, array $args, array &$opts)
85
  {
86
  if (!isset($args[$name])) {
87
  return;
@@ -90,15 +90,15 @@ abstract class RestSerializer
90
  if ($m['streaming'] || ($m['type'] == 'string' || $m['type'] == 'blob')) {
91
  // Streaming bodies or payloads that are strings are
92
  // always just a stream of data.
93
- $opts['body'] = \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\stream_for($args[$name]);
94
  return;
95
  }
96
  $this->payload($m, $args[$name], $opts);
97
  }
98
- private function applyHeader($name, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $member, $value, array &$opts)
99
  {
100
  if ($member->getType() == 'timestamp') {
101
- $value = \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\TimestampShape::format($value, 'rfc822');
102
  }
103
  if ($member['jsonvalue']) {
104
  $value = json_encode($value);
@@ -112,14 +112,14 @@ abstract class RestSerializer
112
  /**
113
  * Note: This is currently only present in the Amazon S3 model.
114
  */
115
- private function applyHeaderMap($name, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $member, array $value, array &$opts)
116
  {
117
  $prefix = $member['locationName'];
118
  foreach ($value as $k => $v) {
119
  $opts['headers'][$prefix . $k] = $v;
120
  }
121
  }
122
- private function applyQuery($name, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $member, $value, array &$opts)
123
  {
124
  if ($member instanceof MapShape) {
125
  $opts['query'] = isset($opts['query']) && is_array($opts['query']) ? $opts['query'] + $value : $value;
@@ -130,7 +130,7 @@ abstract class RestSerializer
130
  $opts['query'][$member['locationName'] ?: $name] = $value;
131
  }
132
  }
133
- private function buildEndpoint(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Operation $operation, array $args, array $opts)
134
  {
135
  $varspecs = [];
136
  // Create an associative array of varspecs used in expansions
@@ -152,11 +152,11 @@ abstract class RestSerializer
152
  }, $operation['http']['requestUri']);
153
  // Add the query string variables or appending to one if needed.
154
  if (!empty($opts['query'])) {
155
- $append = \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\build_query($opts['query']);
156
  $relative .= strpos($relative, '?') ? "&{$append}" : "?{$append}";
157
  }
158
  // Expand path place holders using Amazon's slightly different URI
159
  // template syntax.
160
- return \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\UriResolver::resolve($this->endpoint, new \DeliciousBrains\WP_Offload_S3\Aws3\GuzzleHttp\Psr7\Uri($relative));
161
  }
162
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\MapShape;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Operation;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
10
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\TimestampShape;
11
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface;
12
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7;
13
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri;
14
+ use DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\UriResolver;
15
+ use DeliciousBrains\WP_Offload_Media\Aws3\Psr\Http\Message\RequestInterface;
16
  /**
17
  * Serializes HTTP locations like header, uri, payload, etc...
18
  * @internal
27
  * @param Service $api Service API description
28
  * @param string $endpoint Endpoint to connect to
29
  */
30
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, $endpoint)
31
  {
32
  $this->api = $api;
33
+ $this->endpoint = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\uri_for($endpoint);
34
  }
35
  /**
36
  * @param CommandInterface $command Command to serialized
37
  *
38
  * @return RequestInterface
39
  */
40
+ public function __invoke(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\CommandInterface $command)
41
  {
42
  $operation = $this->api->getOperation($command->getName());
43
  $args = $command->toArray();
44
  $opts = $this->serialize($operation, $args);
45
  $uri = $this->buildEndpoint($operation, $args, $opts);
46
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Request($operation['http']['method'], $uri, isset($opts['headers']) ? $opts['headers'] : [], isset($opts['body']) ? $opts['body'] : null);
47
  }
48
  /**
49
  * Modifies a hash of request options for a payload body.
52
  * @param array $value Value to serialize
53
  * @param array $opts Request options to modify.
54
  */
55
+ protected abstract function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member, array $value, array &$opts);
56
+ private function serialize(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Operation $operation, array $args)
57
  {
58
  $opts = [];
59
  $input = $operation->getInput();
81
  }
82
  return $opts;
83
  }
84
+ private function applyPayload(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $input, $name, array $args, array &$opts)
85
  {
86
  if (!isset($args[$name])) {
87
  return;
90
  if ($m['streaming'] || ($m['type'] == 'string' || $m['type'] == 'blob')) {
91
  // Streaming bodies or payloads that are strings are
92
  // always just a stream of data.
93
+ $opts['body'] = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\stream_for($args[$name]);
94
  return;
95
  }
96
  $this->payload($m, $args[$name], $opts);
97
  }
98
+ private function applyHeader($name, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $member, $value, array &$opts)
99
  {
100
  if ($member->getType() == 'timestamp') {
101
+ $value = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\TimestampShape::format($value, 'rfc822');
102
  }
103
  if ($member['jsonvalue']) {
104
  $value = json_encode($value);
112
  /**
113
  * Note: This is currently only present in the Amazon S3 model.
114
  */
115
+ private function applyHeaderMap($name, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $member, array $value, array &$opts)
116
  {
117
  $prefix = $member['locationName'];
118
  foreach ($value as $k => $v) {
119
  $opts['headers'][$prefix . $k] = $v;
120
  }
121
  }
122
+ private function applyQuery($name, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $member, $value, array &$opts)
123
  {
124
  if ($member instanceof MapShape) {
125
  $opts['query'] = isset($opts['query']) && is_array($opts['query']) ? $opts['query'] + $value : $value;
130
  $opts['query'][$member['locationName'] ?: $name] = $value;
131
  }
132
  }
133
+ private function buildEndpoint(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Operation $operation, array $args, array $opts)
134
  {
135
  $varspecs = [];
136
  // Create an associative array of varspecs used in expansions
152
  }, $operation['http']['requestUri']);
153
  // Add the query string variables or appending to one if needed.
154
  if (!empty($opts['query'])) {
155
+ $append = \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\build_query($opts['query']);
156
  $relative .= strpos($relative, '?') ? "&{$append}" : "?{$append}";
157
  }
158
  // Expand path place holders using Amazon's slightly different URI
159
  // template syntax.
160
+ return \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\UriResolver::resolve($this->endpoint, new \DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Psr7\Uri($relative));
161
  }
162
  }
vendor/Aws3/Aws/Api/Serializer/RestXmlSerializer.php CHANGED
@@ -1,13 +1,13 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service;
7
  /**
8
  * @internal
9
  */
10
- class RestXmlSerializer extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\RestSerializer
11
  {
12
  /** @var XmlBody */
13
  private $xmlBody;
@@ -16,12 +16,12 @@ class RestXmlSerializer extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Seri
16
  * @param string $endpoint Endpoint to connect to
17
  * @param XmlBody $xmlBody Optional XML formatter to use
18
  */
19
- public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api, $endpoint, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\XmlBody $xmlBody = null)
20
  {
21
  parent::__construct($api, $endpoint);
22
- $this->xmlBody = $xmlBody ?: new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\XmlBody($api);
23
  }
24
- protected function payload(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $member, array $value, array &$opts)
25
  {
26
  $opts['headers']['Content-Type'] = 'application/xml';
27
  $opts['body'] = (string) $this->xmlBody->build($member, $value);
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
7
  /**
8
  * @internal
9
  */
10
+ class RestXmlSerializer extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\RestSerializer
11
  {
12
  /** @var XmlBody */
13
  private $xmlBody;
16
  * @param string $endpoint Endpoint to connect to
17
  * @param XmlBody $xmlBody Optional XML formatter to use
18
  */
19
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, $endpoint, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\XmlBody $xmlBody = null)
20
  {
21
  parent::__construct($api, $endpoint);
22
+ $this->xmlBody = $xmlBody ?: new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\XmlBody($api);
23
  }
24
+ protected function payload(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $member, array $value, array &$opts)
25
  {
26
  $opts['headers']['Content-Type'] = 'application/xml';
27
  $opts['body'] = (string) $this->xmlBody->build($member, $value);
vendor/Aws3/Aws/Api/Serializer/XmlBody.php CHANGED
@@ -1,13 +1,13 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\MapShape;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape;
8
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape;
9
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ListShape;
10
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\TimestampShape;
11
  use XMLWriter;
12
  /**
13
  * @internal Formats the XML body of a REST-XML services.
@@ -19,7 +19,7 @@ class XmlBody
19
  /**
20
  * @param Service $api API being used to create the XML body.
21
  */
22
- public function __construct(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api)
23
  {
24
  $this->api = $api;
25
  }
@@ -31,7 +31,7 @@ class XmlBody
31
  *
32
  * @return string
33
  */
34
- public function build(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, array $args)
35
  {
36
  $xml = new \XMLWriter();
37
  $xml->openMemory();
@@ -40,14 +40,14 @@ class XmlBody
40
  $xml->endDocument();
41
  return $xml->outputMemory();
42
  }
43
- private function startElement(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $name, \XMLWriter $xml)
44
  {
45
  $xml->startElement($name);
46
  if ($ns = $shape['xmlNamespace']) {
47
  $xml->writeAttribute(isset($ns['prefix']) ? "xmlns:{$ns['prefix']}" : 'xmlns', $shape['xmlNamespace']['uri']);
48
  }
49
  }
50
- private function format(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
51
  {
52
  // Any method mentioned here has a custom serialization handler.
53
  static $methods = ['add_structure' => true, 'add_list' => true, 'add_blob' => true, 'add_timestamp' => true, 'add_boolean' => true, 'add_map' => true, 'add_string' => true];
@@ -58,13 +58,13 @@ class XmlBody
58
  $this->defaultShape($shape, $name, $value, $xml);
59
  }
60
  }
61
- private function defaultShape(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
62
  {
63
  $this->startElement($shape, $name, $xml);
64
  $xml->writeRaw($value);
65
  $xml->endElement();
66
  }
67
- private function add_structure(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $shape, $name, array $value, \XMLWriter $xml)
68
  {
69
  $this->startElement($shape, $name, $xml);
70
  foreach ($this->getStructureMembers($shape, $value) as $k => $definition) {
@@ -72,7 +72,7 @@ class XmlBody
72
  }
73
  $xml->endElement();
74
  }
75
- private function getStructureMembers(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $shape, array $value)
76
  {
77
  $members = [];
78
  foreach ($value as $k => $v) {
@@ -88,7 +88,7 @@ class XmlBody
88
  }
89
  return $members;
90
  }
91
- private function add_list(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ListShape $shape, $name, array $value, \XMLWriter $xml)
92
  {
93
  $items = $shape->getMember();
94
  if ($shape['flattened']) {
@@ -104,7 +104,7 @@ class XmlBody
104
  $xml->endElement();
105
  }
106
  }
107
- private function add_map(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\MapShape $shape, $name, array $value, \XMLWriter $xml)
108
  {
109
  $xmlEntry = $shape['flattened'] ? $shape['locationName'] : 'entry';
110
  $xmlKey = $shape->getKey()['locationName'] ?: 'key';
@@ -118,25 +118,25 @@ class XmlBody
118
  }
119
  $xml->endElement();
120
  }
121
- private function add_blob(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
122
  {
123
  $this->startElement($shape, $name, $xml);
124
  $xml->writeRaw(base64_encode($value));
125
  $xml->endElement();
126
  }
127
- private function add_timestamp(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\TimestampShape $shape, $name, $value, \XMLWriter $xml)
128
  {
129
  $this->startElement($shape, $name, $xml);
130
- $xml->writeRaw(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\TimestampShape::format($value, 'iso8601'));
131
  $xml->endElement();
132
  }
133
- private function add_boolean(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
134
  {
135
  $this->startElement($shape, $name, $xml);
136
  $xml->writeRaw($value ? 'true' : 'false');
137
  $xml->endElement();
138
  }
139
- private function add_string(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
140
  {
141
  if ($shape['xmlAttribute']) {
142
  $xml->writeAttribute($shape['locationName'] ?: $name, $value);
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\MapShape;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape;
8
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
9
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ListShape;
10
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\TimestampShape;
11
  use XMLWriter;
12
  /**
13
  * @internal Formats the XML body of a REST-XML services.
19
  /**
20
  * @param Service $api API being used to create the XML body.
21
  */
22
+ public function __construct(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api)
23
  {
24
  $this->api = $api;
25
  }
31
  *
32
  * @return string
33
  */
34
+ public function build(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, array $args)
35
  {
36
  $xml = new \XMLWriter();
37
  $xml->openMemory();
40
  $xml->endDocument();
41
  return $xml->outputMemory();
42
  }
43
+ private function startElement(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $name, \XMLWriter $xml)
44
  {
45
  $xml->startElement($name);
46
  if ($ns = $shape['xmlNamespace']) {
47
  $xml->writeAttribute(isset($ns['prefix']) ? "xmlns:{$ns['prefix']}" : 'xmlns', $shape['xmlNamespace']['uri']);
48
  }
49
  }
50
+ private function format(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
51
  {
52
  // Any method mentioned here has a custom serialization handler.
53
  static $methods = ['add_structure' => true, 'add_list' => true, 'add_blob' => true, 'add_timestamp' => true, 'add_boolean' => true, 'add_map' => true, 'add_string' => true];
58
  $this->defaultShape($shape, $name, $value, $xml);
59
  }
60
  }
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->writeRaw($value);
65
  $xml->endElement();
66
  }
67
+ private function add_structure(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $shape, $name, array $value, \XMLWriter $xml)
68
  {
69
  $this->startElement($shape, $name, $xml);
70
  foreach ($this->getStructureMembers($shape, $value) as $k => $definition) {
72
  }
73
  $xml->endElement();
74
  }
75
+ private function getStructureMembers(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape $shape, array $value)
76
  {
77
  $members = [];
78
  foreach ($value as $k => $v) {
88
  }
89
  return $members;
90
  }
91
+ private function add_list(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ListShape $shape, $name, array $value, \XMLWriter $xml)
92
  {
93
  $items = $shape->getMember();
94
  if ($shape['flattened']) {
104
  $xml->endElement();
105
  }
106
  }
107
+ private function add_map(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\MapShape $shape, $name, array $value, \XMLWriter $xml)
108
  {
109
  $xmlEntry = $shape['flattened'] ? $shape['locationName'] : 'entry';
110
  $xmlKey = $shape->getKey()['locationName'] ?: 'key';
118
  }
119
  $xml->endElement();
120
  }
121
+ private function add_blob(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
122
  {
123
  $this->startElement($shape, $name, $xml);
124
  $xml->writeRaw(base64_encode($value));
125
  $xml->endElement();
126
  }
127
+ private function add_timestamp(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\TimestampShape $shape, $name, $value, \XMLWriter $xml)
128
  {
129
  $this->startElement($shape, $name, $xml);
130
+ $xml->writeRaw(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\TimestampShape::format($value, 'iso8601'));
131
  $xml->endElement();
132
  }
133
+ private function add_boolean(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
134
  {
135
  $this->startElement($shape, $name, $xml);
136
  $xml->writeRaw($value ? 'true' : 'false');
137
  $xml->endElement();
138
  }
139
+ private function add_string(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $name, $value, \XMLWriter $xml)
140
  {
141
  if ($shape['xmlAttribute']) {
142
  $xml->writeAttribute($shape['locationName'] ?: $name, $value);
vendor/Aws3/Aws/Api/Service.php CHANGED
@@ -1,14 +1,14 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\QuerySerializer;
6
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\Ec2ParamBuilder;
7
- use DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\QueryParser;
8
  /**
9
  * Represents a web service API model.
10
  */
11
- class Service extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\AbstractModel
12
  {
13
  /** @var callable */
14
  private $apiProvider;
@@ -35,7 +35,7 @@ class Service extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\AbstractModel
35
  $definition['metadata'] += $defaultMeta;
36
  $this->definition = $definition;
37
  $this->apiProvider = $provider;
38
- parent::__construct($definition, new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ShapeMap($definition['shapes']));
39
  if (isset($definition['metadata']['serviceIdentifier'])) {
40
  $this->serviceName = $this->getServiceName();
41
  } else {
@@ -52,15 +52,15 @@ class Service extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\AbstractModel
52
  * @return callable
53
  * @throws \UnexpectedValueException
54
  */
55
- public static function createSerializer(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api, $endpoint)
56
  {
57
- static $mapping = ['json' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Serializer\\JsonRpcSerializer', 'query' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Serializer\\QuerySerializer', 'rest-json' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Serializer\\RestJsonSerializer', 'rest-xml' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Serializer\\RestXmlSerializer'];
58
  $proto = $api->getProtocol();
59
  if (isset($mapping[$proto])) {
60
  return new $mapping[$proto]($api, $endpoint);
61
  }
62
  if ($proto == 'ec2') {
63
- return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\QuerySerializer($api, $endpoint, new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Serializer\Ec2ParamBuilder());
64
  }
65
  throw new \UnexpectedValueException('Unknown protocol: ' . $api->getProtocol());
66
  }
@@ -74,7 +74,7 @@ class Service extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\AbstractModel
74
  */
75
  public static function createErrorParser($protocol)
76
  {
77
- static $mapping = ['json' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\ErrorParser\\JsonRpcErrorParser', 'query' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser', 'rest-json' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\ErrorParser\\RestJsonErrorParser', 'rest-xml' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser', 'ec2' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\ErrorParser\\XmlErrorParser'];
78
  if (isset($mapping[$protocol])) {
79
  return new $mapping[$protocol]();
80
  }
@@ -87,15 +87,15 @@ class Service extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\AbstractModel
87
  * @return callable
88
  * @throws \UnexpectedValueException
89
  */
90
- public static function createParser(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Service $api)
91
  {
92
- static $mapping = ['json' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Parser\\JsonRpcParser', 'query' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Parser\\QueryParser', 'rest-json' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Parser\\RestJsonParser', 'rest-xml' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Parser\\RestXmlParser'];
93
  $proto = $api->getProtocol();
94
  if (isset($mapping[$proto])) {
95
  return new $mapping[$proto]($api);
96
  }
97
  if ($proto == 'ec2') {
98
- return new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Parser\QueryParser($api, null, false);
99
  }
100
  throw new \UnexpectedValueException('Unknown protocol: ' . $api->getProtocol());
101
  }
@@ -207,7 +207,7 @@ class Service extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\AbstractModel
207
  if (!isset($this->definition['operations'][$name])) {
208
  throw new \InvalidArgumentException("Unknown operation: {$name}");
209
  }
210
- $this->operations[$name] = new \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Operation($this->definition['operations'][$name], $this->shapeMap);
211
  }
212
  return $this->operations[$name];
213
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\QuerySerializer;
6
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\Ec2ParamBuilder;
7
+ use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\QueryParser;
8
  /**
9
  * Represents a web service API model.
10
  */
11
+ class Service extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\AbstractModel
12
  {
13
  /** @var callable */
14
  private $apiProvider;
35
  $definition['metadata'] += $defaultMeta;
36
  $this->definition = $definition;
37
  $this->apiProvider = $provider;
38
+ parent::__construct($definition, new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ShapeMap($definition['shapes']));
39
  if (isset($definition['metadata']['serviceIdentifier'])) {
40
  $this->serviceName = $this->getServiceName();
41
  } else {
52
  * @return callable
53
  * @throws \UnexpectedValueException
54
  */
55
+ public static function createSerializer(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api, $endpoint)
56
  {
57
+ static $mapping = ['json' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Serializer\\JsonRpcSerializer', 'query' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Serializer\\QuerySerializer', 'rest-json' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Serializer\\RestJsonSerializer', 'rest-xml' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Serializer\\RestXmlSerializer'];
58
  $proto = $api->getProtocol();
59
  if (isset($mapping[$proto])) {
60
  return new $mapping[$proto]($api, $endpoint);
61
  }
62
  if ($proto == 'ec2') {
63
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\QuerySerializer($api, $endpoint, new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer\Ec2ParamBuilder());
64
  }
65
  throw new \UnexpectedValueException('Unknown protocol: ' . $api->getProtocol());
66
  }
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
  }
87
  * @return callable
88
  * @throws \UnexpectedValueException
89
  */
90
+ public static function createParser(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service $api)
91
  {
92
+ static $mapping = ['json' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Parser\\JsonRpcParser', 'query' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Parser\\QueryParser', 'rest-json' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Parser\\RestJsonParser', 'rest-xml' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Parser\\RestXmlParser'];
93
  $proto = $api->getProtocol();
94
  if (isset($mapping[$proto])) {
95
  return new $mapping[$proto]($api);
96
  }
97
  if ($proto == 'ec2') {
98
+ return new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Parser\QueryParser($api, null, false);
99
  }
100
  throw new \UnexpectedValueException('Unknown protocol: ' . $api->getProtocol());
101
  }
207
  if (!isset($this->definition['operations'][$name])) {
208
  throw new \InvalidArgumentException("Unknown operation: {$name}");
209
  }
210
+ $this->operations[$name] = new \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Operation($this->definition['operations'][$name], $this->shapeMap);
211
  }
212
  return $this->operations[$name];
213
  }
vendor/Aws3/Aws/Api/Shape.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
  /**
6
  * Base class representing a modeled shape.
7
  */
8
- class Shape extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\AbstractModel
9
  {
10
  /**
11
  * Get a concrete shape for the given definition.
@@ -16,9 +16,9 @@ class Shape extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\AbstractModel
16
  * @return mixed
17
  * @throws \RuntimeException if the type is invalid
18
  */
19
- public static function create(array $definition, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ShapeMap $shapeMap)
20
  {
21
- static $map = ['structure' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\StructureShape', 'map' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\MapShape', 'list' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\ListShape', 'timestamp' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\TimestampShape', 'integer' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Shape', 'double' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Shape', 'float' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Shape', 'long' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Shape', 'string' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Shape', 'byte' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Shape', 'character' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Shape', 'blob' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Shape', 'boolean' => 'DeliciousBrains\\WP_Offload_S3\\Aws3\\Aws\\Api\\Shape'];
22
  if (isset($definition['shape'])) {
23
  return $shapeMap->resolve($definition);
24
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
  /**
6
  * Base class representing a modeled shape.
7
  */
8
+ class Shape extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\AbstractModel
9
  {
10
  /**
11
  * Get a concrete shape for the given definition.
16
  * @return mixed
17
  * @throws \RuntimeException if the type is invalid
18
  */
19
+ public static function create(array $definition, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ShapeMap $shapeMap)
20
  {
21
+ static $map = ['structure' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\StructureShape', 'map' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\MapShape', 'list' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\ListShape', 'timestamp' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\TimestampShape', 'integer' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Shape', 'double' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Shape', 'float' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Shape', 'long' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Shape', 'string' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Shape', 'byte' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Shape', 'character' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Shape', 'blob' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Shape', 'boolean' => 'DeliciousBrains\\WP_Offload_Media\\Aws3\\Aws\\Api\\Shape'];
22
  if (isset($definition['shape'])) {
23
  return $shapeMap->resolve($definition);
24
  }
vendor/Aws3/Aws/Api/ShapeMap.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
  /**
6
  * Builds shape based on shape references.
@@ -48,7 +48,7 @@ class ShapeMap
48
  $definition = $shapeRef + $this->definitions[$shape];
49
  $definition['name'] = $definition['shape'];
50
  unset($definition['shape']);
51
- $result = \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape::create($definition, $this);
52
  if ($isSimple) {
53
  $this->simple[$shape] = $result;
54
  }
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
  /**
6
  * Builds shape based on shape references.
48
  $definition = $shapeRef + $this->definitions[$shape];
49
  $definition['name'] = $definition['shape'];
50
  unset($definition['shape']);
51
+ $result = \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape::create($definition, $this);
52
  if ($isSimple) {
53
  $this->simple[$shape] = $result;
54
  }
vendor/Aws3/Aws/Api/StructureShape.php CHANGED
@@ -1,17 +1,17 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
  /**
6
  * Represents a structure shape and resolve member shape references.
7
  */
8
- class StructureShape extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape
9
  {
10
  /**
11
  * @var Shape[]
12
  */
13
  private $members;
14
- public function __construct(array $definition, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ShapeMap $shapeMap)
15
  {
16
  $definition['type'] = 'structure';
17
  if (!isset($definition['members'])) {
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
  /**
6
  * Represents a structure shape and resolve member shape references.
7
  */
8
+ class StructureShape extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape
9
  {
10
  /**
11
  * @var Shape[]
12
  */
13
  private $members;
14
+ public function __construct(array $definition, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ShapeMap $shapeMap)
15
  {
16
  $definition['type'] = 'structure';
17
  if (!isset($definition['members'])) {
vendor/Aws3/Aws/Api/TimestampShape.php CHANGED
@@ -1,13 +1,13 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
  /**
6
  * Represents a timestamp shape.
7
  */
8
- class TimestampShape extends \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape
9
  {
10
- public function __construct(array $definition, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ShapeMap $shapeMap)
11
  {
12
  $definition['type'] = 'timestamp';
13
  parent::__construct($definition, $shapeMap);
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
  /**
6
  * Represents a timestamp shape.
7
  */
8
+ class TimestampShape extends \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape
9
  {
10
+ public function __construct(array $definition, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ShapeMap $shapeMap)
11
  {
12
  $definition['type'] = 'timestamp';
13
  parent::__construct($definition, $shapeMap);
vendor/Aws3/Aws/Api/Validator.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- namespace DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api;
4
 
5
  use Aws;
6
  /**
@@ -32,7 +32,7 @@ class Validator
32
  *
33
  * @throws \InvalidArgumentException if the input is invalid.
34
  */
35
- public function validate($name, \DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, array $input)
36
  {
37
  $this->dispatch($shape, $input);
38
  if ($this->errors) {
@@ -41,7 +41,7 @@ class Validator
41
  throw new \InvalidArgumentException($message);
42
  }
43
  }
44
- private function dispatch(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value)
45
  {
46
  static $methods = ['structure' => 'check_structure', 'list' => 'check_list', 'map' => 'check_map', 'blob' => 'check_blob', 'boolean' => 'check_boolean', 'integer' => 'check_numeric', 'float' => 'check_numeric', 'long' => 'check_numeric', 'string' => 'check_string', 'byte' => 'check_string', 'char' => 'check_string'];
47
  $type = $shape->getType();
@@ -49,7 +49,7 @@ class Validator
49
  $this->{$methods[$type]}($shape, $value);
50
  }
51
  }
52
- private function check_structure(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\StructureShape $shape, $value)
53
  {
54
  if (!$this->checkAssociativeArray($value)) {
55
  return;
@@ -71,10 +71,10 @@ class Validator
71
  }
72
  }
73
  }
74
- private function check_list(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\ListShape $shape, $value)
75
  {
76
  if (!is_array($value)) {
77
- $this->addError('must be an array. Found ' . \DeliciousBrains\WP_Offload_S3\Aws3\Aws\describe_type($value));
78
  return;
79
  }
80
  $this->validateRange($shape, count($value), "list element count");
@@ -85,7 +85,7 @@ class Validator
85
  array_pop($this->path);
86
  }
87
  }
88
- private function check_map(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\MapShape $shape, $value)
89
  {
90
  if (!$this->checkAssociativeArray($value)) {
91
  return;
@@ -97,40 +97,40 @@ class Validator
97
  array_pop($this->path);
98
  }
99
  }
100
- private function check_blob(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value)
101
  {
102
  static $valid = ['string' => true, 'integer' => true, 'double' => true, 'resource' => true];
103
  $type = gettype($value);
104
  if (!isset($valid[$type])) {
105
  if ($type != 'object' || !method_exists($value, '__toString')) {
106
- $this->addError('must be an fopen resource, a ' . 'DeliciousBrains\\WP_Offload_S3\\Aws3\\GuzzleHttp\\Stream\\StreamInterface object, or something ' . 'that can be cast to a string. Found ' . \DeliciousBrains\WP_Offload_S3\Aws3\Aws\describe_type($value));
107
  }
108
  }
109
  }
110
- private function check_numeric(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value)
111
  {
112
  if (!is_numeric($value)) {
113
- $this->addError('must be numeric. Found ' . \DeliciousBrains\WP_Offload_S3\Aws3\Aws\describe_type($value));
114
  return;
115
  }
116
  $this->validateRange($shape, $value, "numeric value");
117
  }
118
- private function check_boolean(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value)
119
  {
120
  if (!is_bool($value)) {
121
- $this->addError('must be a boolean. Found ' . \DeliciousBrains\WP_Offload_S3\Aws3\Aws\describe_type($value));
122
  }
123
  }
124
- private function check_string(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $value)
125
  {
126
  if ($shape['jsonvalue']) {
127
  if (!self::canJsonEncode($value)) {
128
- $this->addError('must be a value encodable with \'json_encode\'.' . ' Found ' . \DeliciousBrains\WP_Offload_S3\Aws3\Aws\describe_type($value));
129
  }
130
  return;
131
  }
132
  if (!$this->checkCanString($value)) {
133
- $this->addError('must be a string or an object that implements ' . '__toString(). Found ' . \DeliciousBrains\WP_Offload_S3\Aws3\Aws\describe_type($value));
134
  return;
135
  }
136
  $this->validateRange($shape, strlen($value), "string length");
@@ -141,7 +141,7 @@ class Validator
141
  }
142
  }
143
  }
144
- private function validateRange(\DeliciousBrains\WP_Offload_S3\Aws3\Aws\Api\Shape $shape, $length, $descriptor)
145
  {
146
  if ($this->constraints['min']) {
147
  $min = $shape['min'];
@@ -165,7 +165,7 @@ class Validator
165
  private function checkAssociativeArray($value)
166
  {
167
  if (!is_array($value) || isset($value[0])) {
168
- $this->addError('must be an associative array. Found ' . \DeliciousBrains\WP_Offload_S3\Aws3\Aws\describe_type($value));
169
  return false;
170
  }
171
  return true;
1
  <?php
2
 
3
+ namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api;
4
 
5
  use Aws;
6
  /**
32
  *
33
  * @throws \InvalidArgumentException if the input is invalid.
34
  */
35
+ public function validate($name, \DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, array $input)
36
  {
37
  $this->dispatch($shape, $input);
38
  if ($this->errors) {
41
  throw new \InvalidArgumentException($message);
42
  }
43
  }
44
+ private function dispatch(\DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape $shape, $value)
45
  {
46
  static $methods = ['structure' => 'check_structure', 'list' => 'check_list', 'map' => 'check_map', 'blob' => 'check_blob', 'boolean' => 'check_boolean', 'integer' => 'check_numeric', 'float' => 'check_numeric', 'long' => 'check_numeric', 'string' => 'check_string', 'byte' => 'check_string', 'char' => 'check_string'];
47
  $type = $shape->getType();
49
  $this->{$methods[$type]}($shape, $value);
50